การจัดรูปแบบเว็บรุ่นใหม่

รับข่าวสารล่าสุดเกี่ยวกับฟีเจอร์ที่น่าสนใจใน CSS ที่ทันสมัย

ขณะนี้มีเรื่องที่น่าตื่นเต้นเกิดขึ้นใน CSS มากมาย และหลายๆ สิ่งก็ได้รองรับในเบราว์เซอร์ในปัจจุบันแล้ว เราได้พูดถึงฟีเจอร์ใหม่และฟีเจอร์ที่กำลังจะมีให้บริการซึ่งเราคิดว่าควรได้รับความสนใจในหัวข้อการบรรยายของเราที่ CDS 2019 ซึ่งคุณสามารถรับชมได้ที่ด้านล่าง

โพสต์นี้มุ่งเน้นที่ฟีเจอร์ที่คุณใช้ได้ในปัจจุบัน ดังนั้นอย่าลืมดูการพูดคุยเพื่อพูดคุยกันให้ลึกขึ้นเกี่ยวกับฟีเจอร์ที่กำลังจะเปิดตัว เช่น Houdini นอกจากนี้ คุณยังดูการสาธิตฟีเจอร์ทั้งหมดที่เราพูดถึงได้ในหน้า CSS@CDS

เนื้อหา

การเลื่อนแบบ Snap

เลื่อนสแนปให้คุณกำหนดจุดสแนปเมื่อผู้ใช้เลื่อนเนื้อหาในแนวตั้ง แนวนอน หรือทั้ง 2 อย่าง โดยจะมีแรงเฉื่อยในการเลื่อนและการลดความเร็วในตัว รวมถึงเปิดใช้การแตะ

โค้ดตัวอย่างนี้จะตั้งค่าการเลื่อนแนวนอนในองค์ประกอบ <section> โดยจุดยึดจะจัดแนวกับด้านซ้ายขององค์ประกอบ <picture> ย่อย

section {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
}

section > picture {
  scroll-snap-align: start;
}

วิธีการมีดังนี้

  • ในองค์ประกอบ <section> ระดับบนสุด
    • ตั้งค่า overflow-x เป็น auto เพื่ออนุญาตการเลื่อนแนวนอน
    • overscroll-behavior-x มีการตั้งค่าเป็น contain เพื่อป้องกันไม่ให้องค์ประกอบหลักเลื่อนเมื่อผู้ใช้ไปถึงขอบเขตของพื้นที่เลื่อนขององค์ประกอบ <section> (การดำเนินการนี้ไม่จำเป็นต่อการจับคู่ แต่มักจะเป็นความคิดที่ดี)
    • ตั้งค่า scroll-snap-type เป็น x สําหรับการสแนปแนวนอน และ mandatory เพื่อให้มั่นใจว่าวิวพอร์ตจะสแนปไปยังจุดที่มีการสแนปที่ใกล้ที่สุดเสมอ
  • ในองค์ประกอบย่อย <picture> จะมีการตั้งค่า scroll-snap-align เป็น start ซึ่งจะตั้งจุดยึดที่ด้านซ้ายของรูปภาพแต่ละรูป (สมมติว่า direction ได้รับการตั้งค่าเป็น ltr)

นี่คือการสาธิตสด:

นอกจากนี้ คุณยังดูเดโมสำหรับการจับคู่การเลื่อนแนวตั้งและการจับคู่การเลื่อนแบบเมทริกซ์ได้ด้วย

:focus-within

:focus-within แก้ไขปัญหาการช่วยเหลือพิเศษมาอย่างยาวนาน เนื่องจากมีหลายกรณีที่การโฟกัสองค์ประกอบย่อยควรส่งผลต่อการแสดงองค์ประกอบหลักเพื่อให้ผู้ใช้เทคโนโลยีความช่วยเหลือพิเศษเข้าถึง UI ได้

ตัวอย่างเช่น หากคุณมีเมนูแบบเลื่อนลงที่มีหลายรายการ เมนูควรปรากฏอยู่เสมอเมื่อมีโฟกัสที่รายการใดรายการหนึ่ง มิฉะนั้น เมนูจะหายไปสำหรับผู้ใช้แป้นพิมพ์

:focus-within บอกให้เบราว์เซอร์ใช้สไตล์เมื่อโฟกัสอยู่ที่องค์ประกอบย่อยขององค์ประกอบที่ระบุ กลับไปที่ตัวอย่างเมนู การตั้งค่า :focus-within ในองค์ประกอบเมนูจะช่วยให้องค์ประกอบนั้นยังคงแสดงอยู่เมื่อรายการในเมนูได้รับโฟกัส

.menu:focus-within {
  display: block;
  opacity: 1;
  visibility: visible;
}

ภาพประกอบแสดงความแตกต่างของลักษณะการทำงานระหว่างการโฟกัสกับภายใน

ลองเลื่อนดูองค์ประกอบที่โฟกัสได้ในการสาธิตด้านล่าง คุณจะสังเกตเห็นว่าเมนูจะยังคงปรากฏเมื่อคุณโฟกัสที่รายการในเมนู ดังนี้

การค้นหาสื่อระดับ 5

คำค้นหาสื่อใหม่เป็นวิธีที่มีประสิทธิภาพในการปรับประสบการณ์ของผู้ใช้แอปตามค่ากำหนดอุปกรณ์ของผู้ใช้ โดยพื้นฐานแล้วเบราว์เซอร์จะทำหน้าที่เป็นพร็อกซีสำหรับค่ากําหนดระดับระบบที่เราตอบสนองได้ใน CSS โดยใช้กลุ่มคําค้นหาสื่อ prefers-* ดังนี้

แผนภาพที่แสดงการค้นหาสื่อที่ตีความค่ากําหนดของผู้ใช้ระดับระบบ

คําค้นหาใหม่ที่เราคิดว่านักพัฒนาแอปจะตื่นเต้นมากที่สุดมีดังนี้

การค้นหาเหล่านี้ถือเป็นเรื่องสำคัญอย่างยิ่งสำหรับการช่วยเหลือพิเศษ ตัวอย่างเช่น ก่อนหน้านี้เราไม่มีทางทราบเลยว่าผู้ใช้ตั้งค่าระบบปฏิบัติการเป็นโหมดคอนทราสต์สูง หากต้องการใช้โหมดคอนทราสต์สูงสำหรับเว็บแอปที่ยังคงเอกลักษณ์ของแบรนด์ คุณจะต้องขอให้ผู้ใช้เลือกจาก UI ภายในแอป ตอนนี้คุณสามารถตรวจสอบการตั้งค่าคอนทราสต์สูงจากระบบปฏิบัติการโดยใช้ prefers-contrast ได้แล้ว

ผลที่ตามมาที่น่าสนใจอย่างหนึ่งของ Media Query เหล่านี้คือเราสามารถออกแบบเพื่อรองรับค่ากําหนดของผู้ใช้ระดับระบบหลายชุดค่าผสมเพื่อรองรับค่ากําหนดของผู้ใช้และความต้องการด้านการช่วยเหลือพิเศษที่หลากหลาย หากผู้ใช้ต้องการโหมดมืดคอนทราสต์สูงเมื่ออยู่ในสภาพแวดล้อมที่มีแสงสลัว คุณก็ทำได้

Adam ให้ความสำคัญกับการใช้ "prefers reduced motion" แทน "no motion" ผู้ใช้บอกว่าต้องการภาพเคลื่อนไหวน้อยลง ไม่ใช่ว่าไม่ต้องการภาพเคลื่อนไหวเลย เขายืนยันว่าการเคลื่อนไหวที่ลดลงไม่ใช่การเคลื่อนไหวที่หยุดนิ่ง ต่อไปนี้คือตัวอย่างที่ใช้ภาพเคลื่อนไหวแบบ Crossfade เมื่อผู้ใช้ต้องการลดการเคลื่อนไหว

คุณสมบัติเชิงตรรกะ

พร็อพเพอร์ตี้เชิงตรรกะจะช่วยแก้ปัญหาที่ทำให้มีผู้พบเห็นมากขึ้นเมื่อนักพัฒนาแอปจัดการกับการปรับให้เป็นสากล คุณสมบัติเลย์เอาต์หลายอย่าง เช่น margin และ padding จะถือว่าภาษานั้นอ่านจากบนลงล่างและจากซ้ายไปขวา

แผนภาพแสดงคุณสมบัติเลย์เอาต์ CSS แบบดั้งเดิม

เมื่อออกแบบหน้าเว็บสำหรับหลายภาษาด้วยโหมดการเขียนที่หลากหลาย นักพัฒนาซอฟต์แวร์ต้องปรับพร็อพเพอร์ตี้เหล่านั้นทั้งหมดแยกกันในองค์ประกอบต่างๆ ซึ่งกลายเป็นฝันร้ายสำหรับการบำรุงรักษาไปอย่างรวดเร็ว

พร็อพเพอร์ตี้เชิงตรรกะช่วยให้คุณรักษาความสมบูรณ์ของเลย์เอาต์ในโหมดการแปลและการเขียนได้ โดยจะอัปเดตแบบไดนามิกตามการเรียงลำดับเชิงอรรถศาสตร์ของเนื้อหาแทนที่จะเป็นการจัดเรียงเชิงพื้นที่ ด้วยคุณสมบัติเชิงตรรกะ องค์ประกอบแต่ละรายการจะมีมิติข้อมูล 2 ส่วน ได้แก่

  • มิติข้อมูลบล็อกจะตั้งฉากกับลำดับข้อความในบรรทัด (ในภาษาอังกฤษ block-size เหมือนกับ height)
  • มิติข้อมูลในบรรทัดจะขนานกับโฟลว์ของข้อความในบรรทัด (ในภาษาอังกฤษ inline-size เหมือนกับ width)

ชื่อมิติข้อมูลเหล่านี้ใช้กับพร็อพเพอร์ตี้เลย์เอาต์เชิงตรรกะทั้งหมด ตัวอย่างเช่น ในภาษาอังกฤษ block-start จะเหมือนกับ top และ inline-end จะเหมือนกับ right

แผนภาพแสดงพร็อพเพอร์ตี้เลย์เอาต์เชิงตรรกะ CSS ใหม่

เมื่อใช้พร็อพเพอร์ตี้เชิงตรรกะ คุณจะอัปเดตเลย์เอาต์สำหรับภาษาอื่นๆ โดยอัตโนมัติได้ง่ายๆ เพียงเปลี่ยนพร็อพเพอร์ตี้ writing-mode และ direction สำหรับหน้าเว็บแทนการอัปเดตพร็อพเพอร์ตี้เลย์เอาต์หลายสิบรายการในองค์ประกอบแต่ละรายการ

คุณดูวิธีการทำงานของพร็อพเพอร์ตี้เชิงตรรกะได้ในตัวอย่างด้านล่างโดยการตั้งค่าพร็อพเพอร์ตี้ writing-mode ในองค์ประกอบ <body> เป็นค่าต่างๆ

position: sticky

เอลิเมนต์ที่มี position: sticky จะยังคงอยู่ในโฟลว์บล็อกจนกว่าจะเริ่มเลื่อนออกไปนอกหน้าจอ ซึ่งเมื่อถึงจุดนั้น เอลิเมนต์จะหยุดเลื่อนไปพร้อมกับส่วนที่เหลือของหน้าเว็บ และยึดอยู่ที่ตำแหน่งที่ระบุโดยค่า top ของเอลิเมนต์ พื้นที่ที่จัดสรรให้องค์ประกอบนั้นจะยังคงอยู่ในโฟลว์ และองค์ประกอบจะกลับมาเหมือนเดิมเมื่อผู้ใช้เลื่อนกลับขึ้นไป

การวางตำแหน่งแบบติดช่วยให้คุณสร้างเอฟเฟกต์ที่มีประโยชน์มากมายซึ่งก่อนหน้านี้ต้องใช้ JavaScript เราได้สร้างการสาธิตหลายรายการเพื่อแสดงตัวอย่างการใช้งาน แต่ละตัวอย่างใช้ CSS เดียวกันเป็นส่วนใหญ่ และปรับมาร์กอัป HTML เพียงเล็กน้อยเพื่อสร้างเอฟเฟกต์แต่ละรายการ

Sticky Stack

ในการสาธิตนี้ องค์ประกอบติดหนึบทั้งหมดจะใช้คอนเทนเนอร์เดียวกัน ซึ่งหมายความว่าองค์ประกอบที่ติดอยู่แต่ละรายการจะเลื่อนไปทับองค์ประกอบก่อนหน้าเมื่อผู้ใช้เลื่อนลง องค์ประกอบติดหนึบมีตำแหน่งที่ค้างตำแหน่งเดียวกัน

สไลด์ติดหนึบ

องค์ประกอบที่ติดอยู่เป็นองค์ประกอบที่คล้ายกัน (กล่าวคือ พ่อแม่ของบุตรหลานเป็นพี่น้องกัน) เมื่อองค์ประกอบติดหนึบมาถึงขอบเขตล่างของคอนเทนเนอร์ องค์ประกอบจะเลื่อนขึ้นพร้อมกับคอนเทนเนอร์ ทำให้เกิดการแสดงผลว่าองค์ประกอบติดหนึบที่ต่ำกว่ากำลังดันตัวที่อยู่ที่สูงขึ้นขึ้นมา กล่าวคือ แคมเปญดังกล่าวดูเหมือนจะแข่งขันกันเพื่อตำแหน่งที่ติดอยู่

Sticky Desperado

องค์ประกอบแบบติดหนึบในเดโมนี้มีความคล้ายคลึงกับสไลด์แบบติดหนึบ อย่างไรก็ตาม ได้มีการวางไว้ในคอนเทนเนอร์ที่ตั้งค่าเป็นเลย์เอาต์แบบตารางแบบ 2 คอลัมน์

backdrop-filter

พร็อพเพอร์ตี้ backdrop-filter ช่วยให้คุณใช้เอฟเฟกต์กราฟิกกับพื้นที่ด้านหลังองค์ประกอบแทนที่จะใช้กับองค์ประกอบนั้นๆ ซึ่งทำให้มีเอฟเฟกต์เจ๋งๆ มากมายที่ก่อนหน้านี้ทำได้เมื่อใช้การแฮ็ก CSS และ JavaScript ที่ซับซ้อนด้วย CSS เพียงบรรทัดเดียว

ตัวอย่างเช่น เดโมนี้ใช้ backdrop-filter เพื่อให้ได้ภาพเบลอสไตล์ระบบปฏิบัติการ

เรามีโพสต์ที่ยอดเยี่ยมเกี่ยวกับ backdrop-filter อยู่แล้ว โปรดไปที่โพสต์ดังกล่าวเพื่อดูข้อมูลเพิ่มเติม

:is()

แม้ว่า :is() Pseudo-class จะมีอายุมากกว่า 10 ปี แต่ก็ยังไม่มีการใช้งานมากเท่าที่เราคิดว่าสมควร ระบบจะใช้รายการที่คั่นด้วยคอมมาของตัวเลือกเป็นอาร์กิวเมนต์ และตรงกับตัวเลือกทั้งหมดในรายการนั้น ความยืดหยุ่นนี้ทําให้ใช้งานได้ง่ายมากและสามารถลดจํานวน CSS ที่ส่งไปได้อย่างมาก

ต่อไปนี้คือตัวอย่างสั้นๆ

button.focus,
button:focus {
  
}

article > h1,
article > h2,
article > h3,
article > h4,
article > h5,
article > h6 {
  
}

/* selects the same elements as the code above */
button:is(.focus, :focus) {
  
}

article > :is(h1,h2,h3,h4,h5,h6) {
  
}

gap

เลย์เอาต์ตาราง CSS มี gap (ก่อนหน้านี้คือ grid-gap) มาระยะหนึ่งแล้ว gap ช่วยแก้ปัญหาการจัดวางที่พบได้ทั่วไปหลายอย่างด้วยการระบุระยะห่างภายในขององค์ประกอบที่บรรจุแทนระยะห่างรอบๆ องค์ประกอบย่อย ตัวอย่างเช่น เมื่อใช้ระยะห่าง คุณไม่ต้องกังวลว่าระยะขอบขององค์ประกอบย่อยจะทำให้เกิดพื้นที่ว่างที่ไม่ต้องการรอบๆ ขอบขององค์ประกอบที่บรรจุ

ภาพแสดงวิธีที่พร็อพเพอร์ตี้ช่องว่างหลีกเลี่ยงการเว้นระยะห่างรอบขอบขององค์ประกอบคอนเทนเนอร์โดยไม่ได้ตั้งใจ

ข่าวดียิ่งกว่านั้นคือ gap จะพร้อมใช้งานใน Flexbox ซึ่งจะมาพร้อมสิทธิประโยชน์ด้านระยะห่างทั้งหมดที่ตารางกริดมีดังนี้

  • มีการประกาศการเว้นวรรคเพียงรายการเดียวแทนที่จะเป็นหลายรายการ
  • คุณไม่จำเป็นต้องกำหนดรูปแบบสำหรับโปรเจ็กต์ว่าองค์ประกอบย่อยใดควรเป็นเจ้าของการเว้นวรรค องค์ประกอบที่บรรจุจะเป็นเจ้าของการเว้นวรรคแทน
  • โค้ดนี้เข้าใจง่ายกว่ากลยุทธ์เก่าๆ เช่น นกฮูกที่สมองถูกทำลาย

วิดีโอต่อไปนี้แสดงประโยชน์ของการใช้พร็อพเพอร์ตี้ gap รายการเดียวสำหรับองค์ประกอบ 2 รายการ โดยรายการหนึ่งมีเลย์เอาต์ตารางกริดและอีกรายการมีเลย์เอาต์ Flex

ปัจจุบันมีเพียง Firefox เท่านั้นที่รองรับ gap ในเลย์เอาต์ Flex แต่ลองใช้การสาธิตนี้เพื่อดูวิธีการทํางาน

CSS Houdini

Houdini คือชุด API ระดับล่างสําหรับเครื่องมือแสดงผลของเบราว์เซอร์ที่ช่วยให้คุณบอกเบราว์เซอร์ว่าจะตีความ CSS ที่กําหนดเองอย่างไร กล่าวคือ จะช่วยให้คุณเข้าถึง CSS Object Model ซึ่งช่วยให้คุณextend CSS ผ่าน JavaScript ได้ ซึ่งมีประโยชน์หลายประการ ดังนี้

  • คุณจะสร้างฟีเจอร์ CSS ที่กำหนดเองได้มากขึ้น
  • แยกข้อกังวลเกี่ยวกับการเรนเดอร์ออกจากตรรกะของแอปพลิเคชันได้ง่ายขึ้น
  • ประสิทธิภาพดีกว่าการพึ่งพาโค้ด CSS ที่เราใช้กับ JavaScript อยู่ในปัจจุบัน เนื่องจากเบราว์เซอร์จะไม่ต้องแยกวิเคราะห์สคริปต์และทำการเรนเดอร์รอบที่ 2 อีกต่อไป โค้ด Houdini จะได้รับการแยกวิเคราะห์ในรอบการแสดงผลแรก

ภาพแสดงวิธีการทํางานของ Houdini เทียบกับ polyfill ของ JavaScript แบบดั้งเดิม

Houdini เป็นชื่อรวมของ API หลายรายการ หากต้องการข้อมูลเพิ่มเติมเกี่ยวกับบุคคลและสถานะปัจจุบันขององค์กร โปรดดูที่ฮูดินี่พร้อมหรือยัง ในการพูดคุยครั้งนี้ เราพูดถึง Properties and Values API, Paint API และ Animation Worklet เนื่องจากเป็น API ที่รองรับมากที่สุดในปัจจุบัน เราอาจเขียนโพสต์แบบเต็มเกี่ยวกับ API ที่น่าตื่นเต้นแต่ละรายการเหล่านี้ได้ง่ายๆ แต่ตอนนี้โปรดดูการบรรยายเพื่อดูภาพรวมและตัวอย่างที่น่าสนใจซึ่งจะช่วยให้คุณเห็นภาพว่า API เหล่านี้ทำอะไรได้บ้าง

รายการเพิ่มเติม

ยังมีอีก 2-3 อย่างที่อยากจะพูดถึงแต่ไม่มีเวลาอธิบายอย่างละเอียด เราจึงขอสรุปสั้นๆ ให้คุณฟัง⚡ หากคุณยังไม่เคยได้ยินเกี่ยวกับฟีเจอร์เหล่านี้ โปรดดูช่วงท้ายของการบรรยาย

  • size: พร็อพเพอร์ตี้ที่ช่วยให้คุณตั้งค่าความสูงและความกว้างพร้อมกันได้
  • aspect-ratio: พร็อพเพอร์ตี้ที่กำหนดสัดส่วนภาพขององค์ประกอบที่ไม่ได้มีอยู่แล้ว
  • min(), max() และ clamp(): ฟังก์ชันที่ช่วยให้คุณกำหนดข้อจำกัดเชิงตัวเลขในพร็อพเพอร์ตี้ CSS ใดก็ได้ ไม่ใช่แค่ความกว้างและความสูง
  • list-style-type เป็นพร็อพเพอร์ตี้ที่มีอยู่ แต่เร็วๆ นี้จะรองรับค่าที่หลากหลายมากขึ้น ซึ่งรวมถึงอีโมจิและ SVG
  • display: outer inner: ในเร็วๆ นี้พร็อพเพอร์ตี้ display จะยอมรับพารามิเตอร์ 2 รายการ ซึ่งจะช่วยให้คุณระบุเลย์เอาต์ด้านนอกและด้านในได้อย่างชัดเจนแทนที่จะใช้คีย์เวิร์ดแบบผสม เช่น inline-flex
  • ภูมิภาค CSS: ช่วยให้คุณกรอกข้อมูลในบริเวณที่ไม่ใช่สี่เหลี่ยมผืนผ้าที่ระบุซึ่งเนื้อหาจะไหลเข้าและออกได้
  • โมดูล CSS: JavaScript จะสามารถขอโมดูล CSS และรับออบเจ็กต์ Rich กลับมาซึ่งง่ายต่อการดำเนินการ