- 1 พื้นฐาน
- 2 Flexbox
- 3 ตารางกริดและตารางกริดย่อย
- 4 การค้นหาคอนเทนเนอร์
- 5 การวางซ้อนแบบเนทีฟ การวางตำแหน่งโฆษณา Anchor และบริบทการซ้อน
- 6 การติดตามการล้นและความเสถียรของเลย์เอาต์
- 7 กลไกของวิวพอร์ตและการกระจายแทร็ก
- 8 เลนตารางกริด (หรือที่เรียกว่า Masonry)
1 Fundamentals
ใช้เครื่องมือเลย์เอาต์ของเบราว์เซอร์เมื่อเป็นไปได้เพื่อประสิทธิภาพที่ดีขึ้น ใช้การกำหนดขนาดภายใน พร็อพเพอร์ตี้เชิงตรรกะ และ aspect-ratio ก่อนที่จะใช้มิติข้อมูลที่ฮาร์ดโค้ดหรือการค้นหาสื่อที่ซับซ้อน
1.1 ควรใช้โหมดเลย์เอาต์ใด
โดยไล่ตามแผนผังการตัดสินใจจากบนลงล่างและหยุดที่รายการแรกที่ตรงกัน โปรดทราบว่าเลย์เอาต์สามารถฝังอยู่ภายในเลย์เอาต์อื่นๆ ได้ และการตัดสินใจแต่ละครั้งจะขึ้นอยู่กับกรณีการใช้งานของคอนเทนเนอร์นั้นๆ
- เป็นแถวหรือคอลัมน์ของรายการแบบง่ายๆ ใช่ไหม ใช้ Flexbox — 1 มิติ เน้นเนื้อหาเป็นหลัก เนื้อหาจะกระจายไปตามแกนเดียว
- องค์ประกอบที่ฝังจำเป็นต้องสอดคล้องกับแทร็กของตารางกริดระดับปู่ย่าตายายหรือไม่ ใช้ subgrid — 2 มิติ, เน้นความสัมพันธ์, รับค่าแทร็กหลักเพื่อให้หลานสามารถจัดแนวข้ามพี่น้องได้
- เป็นหน้าหรือโครงสร้างคอมโพเนนต์ที่ซับซ้อนซึ่งมีทั้งแถวและคอลัมน์ใช่ไหม ใช้ grid — 2 มิติ, เลย์เอาต์มาก่อน, คุณกำหนดโครงร่างและเนื้อหาจะเติมเต็ม
- เนื้อหาเป็นข้อความยาวๆ ที่ควรแบ่งออกเป็นคอลัมน์ที่สมดุลหรือไม่ ใช้หลายคอลัมน์ — โฟลว์ 1 มิติ สไตล์หนังสือพิมพ์
- สินค้ามีความสูงต่างกันและต้องบรรจุอย่างแน่นหนาใช่ไหม ใช้ grid กับ
grid-auto-flow: denseในปัจจุบัน และใช้ Masonry แบบเนทีฟ (หรือที่เรียกว่า "เลนตารางกริด") เฉพาะเมื่อจัดส่งในเป้าหมาย Baseline (ดู §8) - องค์ประกอบจำเป็นต้องลอยอยู่เหนือหน้าเว็บและเชื่อมโยงเชิงพื้นที่กับทริกเกอร์หรือไม่ แม้จะข้ามขอบเขต DOM หรือบริบทการซ้อน ใช้การจัดตำแหน่ง Anchor -
anchor-nameในทริกเกอร์,position-anchorในการวางซ้อน (ดู §5)
1.2 หลักการทำงาน
- ใช้พร็อพเพอร์ตี้เชิงตรรกะ (
inline-size,block-size,margin-inline,padding-block,inset-inline-start) สำหรับขนาดเลย์เอาต์และระยะห่าง — ดูรายละเอียดทั้งหมดได้ที่ CSS: Modern Architecture - ใช้โมเดลทางความคิดแบบเนื้อหามาก่อนเทียบกับเลย์เอาต์มาก่อน: flexbox เมื่อรายการกำหนดโฟลว์, grid เมื่อคุณกำหนดโครงร่างก่อน
- ใช้ชวเลข
place-*(place-content,place-items,place-self) เพื่อจัดแนวทั้ง 2 แกนในการประกาศเดียว - ใช้การกำหนดขนาดภายใน (
min-content,max-content,fit-content()) และแทร็กที่ยืดหยุ่น (fr,minmax()) ก่อนwidth/heightแบบคงที่ ซึ่งจะช่วยลดการค้นหาสื่อและทำให้เลย์เอาต์มีความยืดหยุ่นมากขึ้น - อย่าใช้
overflow: hiddenเพื่อปกปิดปัญหาเกี่ยวกับเลย์เอาต์ แต่ให้แก้ไขที่ต้นทาง ตัวอย่างเช่น องค์ประกอบที่ถูกแทนที่บางอย่าง เช่น<canvas>,<img>,<svg>,<video>,<iframe>จะใช้display: inlineโดยค่าเริ่มต้น ซึ่งอาจเพิ่มช่องว่างในเลย์เอาต์บางอย่าง แทนที่จะตัดช่องว่างด้วยoverflowให้นำออกโดยใช้ค่า display-outside แบบบล็อก (เช่นdisplay: block,grid,flexเป็นต้น) - ใช้
aspect-ratioเพื่อจองพื้นที่สำหรับสื่อและป้องกันไม่ให้เลย์เอาต์เปลี่ยนแปลงก่อนที่ชิ้นงานจะโหลด
.sidebar { inline-size: max-content; } /* Size to longest unbreakable token. */
.main-content { inline-size: fit-content; } /* Grow to available space, no further. */
.media { aspect-ratio: 16 / 9; inline-size: 100%; block-size: auto; }
body.centered { display: grid; place-content: center; min-block-size: 100dvb; }
ดูข้อมูลเกี่ยวกับ
calc-size()และการปรับขนาดภายในที่คำนึงถึงข้อจำกัดได้ที่คำนวณด้วยขนาดภายใน
2 Flexbox
เลย์เอาต์แบบ 1 มิติ - รายการจะไหลไปตามแกนหลักแกนเดียวโดยมีการจัดแนวบนแกนไขว้ ใช้สำหรับแถบนำทาง แถบเครื่องมือ แถวรายการ และการกระจายแถวหรือคอลัมน์เดียว
สิ่งที่ควรทำ
- สร้างบริบทด้วย
display: flexและตั้งค่าแกนหลักด้วยflex-direction(ค่าเริ่มต้นrow) - ใช้
flex-wrap: wrapเมื่อใดก็ตามที่อาจเกิดการล้น —nowrapที่ไม่มีoverflow: auto/hiddenจะล้นในวิวพอร์ตแคบๆ - เลเยอร์
flex-wrap: balanceหลังflex-wrap: wrapในแถวที่ตัดขึ้นบรรทัดใหม่ของรายการขนาดกะทัดรัด (เช่น กลุ่มแท็ก, เม็ดยาตัวกรอง, กลุ่มปุ่ม หรือลิงก์การนำทาง) เพื่อกระจายรายการอย่างสม่ำเสมอในบรรทัดต่างๆ และป้องกันไม่ให้มีรายการเดียวที่ไม่มีคู่ในแถวสุดท้าย เบราว์เซอร์ที่ไม่รองรับจะเปลี่ยนไปใช้wrap - ใช้ชวเลข
flex<grow> <shrink> <basis>(เช่นflex: 1 1 250px) กับรายการแทนการตั้งค่าflex-grow/flex-shrink/flex-basisทีละรายการ - ใช้
gap(หรือrow-gap/column-gapแบบเต็ม) เพื่อเว้นวรรคระหว่างรายการแทนระยะขอบย่อย - ใส่
safe(เช่นalign-items: safe center) ไว้หน้าการจัดตำแหน่งตามตำแหน่งเพื่อให้เนื้อหาที่โฟกัสได้ไม่ถูกตัดเมื่อคอนเทนเนอร์แคบกว่าเนื้อหา - ดันรายการเดียวไปที่ปลายสุดของแกนหลักด้วย
margin-inline-start: auto(หรือmargin-block-start: auto) ซึ่งเป็นวิธีมาตรฐานในการหลีกเลี่ยงปัญหา - ลบล้างการปรับแนวแกนไขว้ต่อรายการด้วย
align-self - ใช้
align-itemsเพื่อจัดกึ่งกลางรายการทั้งหมดบนแกนขวาง ใช้margin: autoกับรายการเดียวเพื่อจัดกึ่งกลางทั้ง 2 แกนอย่างอิสระ ใช้align-contentเฉพาะเมื่อคอนเทนเนอร์ตัดขึ้นบรรทัดใหม่และมีพื้นที่ว่างเพิ่มเติมในแถว - ตั้งค่า
min-inline-size: 0(หรือmin-width: 0) ในรายการ Flex ที่มีเนื้อหาแบบไม่ขึ้นบรรทัดใหม่ที่ยาว (URL, โค้ด, สตริงยาว) โดยค่าเริ่มต้น รายการ Flex จะไม่หดตัวลงต่ำกว่าขนาดเนื้อหา ซึ่งทำให้เกิดการล้น
สิ่งที่ไม่ควรทำ
- อย่าใช้
justify-selfกับรายการ Flex เนื่องจากใช้ได้กับเลย์เอาต์แบบตารางกริด บล็อก และตำแหน่งสัมบูรณ์เท่านั้น โปรดใช้ระยะขอบอัตโนมัติแทน - อย่าใช้
orderหรือflex-direction: *-reverseเพื่อจัดเรียงเนื้อหาแบบอินเทอร์แอกทีฟใหม่ โดยจะเปลี่ยนเฉพาะลำดับภาพเท่านั้น ลำดับ DOM ยังคงขับเคลื่อนโฟกัสตามลำดับ ดังนั้นขั้นตอนการใช้แท็บแป้นพิมพ์จะไม่ตรงกับสิ่งที่ผู้ใช้เห็น - อย่าสับสนระหว่าง
space-around(ช่องว่างครึ่งหนึ่งที่ส่วนท้าย) กับspace-evenly(ช่องว่างเท่ากันก่อน ระหว่าง และหลัง) - อย่าลืมการพลิกแกน: เมื่อ
flex-direction: column,justify-contentจะจัดแนวบนแกนบล็อกและalign-itemsจะจัดแนวบนแกนอินไลน์ ซึ่งตรงข้ามกับค่าเริ่มต้น - อย่าปรับขนาดทั้งคอนเทนเนอร์และองค์ประกอบย่อยให้เต็มซึ่งกันและกัน เนื่องจากเป็นสาเหตุที่พบบ่อยของการล้นและผลลัพธ์ที่ไม่คาดคิด กำหนดขนาดที่แน่นอนให้ด้านใดด้านหนึ่ง
- อย่าตั้งค่าทั้ง
flex-basisและwidth/inline-sizeในรายการเดียวกัน เนื่องจากflex-basisจะมีความสำคัญเหนือกว่าในบริบท Flex และระบบจะไม่สนใจwidthใช้flex-basis(หรือชวเลขflex) เป็นแหล่งข้อมูลที่เชื่อถือได้เพียงแหล่งเดียว (SSOT) สำหรับการปรับขนาดรายการ Flex
.card-grid { display: flex; flex-flow: row wrap; gap: 1rem; }
.card-item { flex: 1 1 250px; } /* grow, shrink, basis */
.card-item-action { margin-inline-start: auto; } /* Push to main-axis end. */
.toolbar { display: flex; align-items: safe center; }
.tag-list { display: flex; flex-wrap: wrap; flex-wrap: balance; gap: 0.5rem; }
3 ตารางกริดและตารางกริดย่อย
เลย์เอาต์ 2 มิติ — กำหนดแถวและคอลัมน์อย่างชัดเจน หรือให้เครื่องมือดึงข้อมูลมาให้ Subgrid ช่วยให้ตารางกริดที่ฝังรับแทร็กของตารางกริดระดับบนมาใช้ เพื่อให้ตารางกริดระดับหลานจัดแนวตามตารางกริดระดับพี่น้องได้
การเลือกฟีเจอร์กริด
- คุณทราบจำนวนคอลัมน์ที่ต้องการอย่างแน่ชัดหรือไม่
- ใช่ - ใช้แทร็กที่มีเนื้อหาโจ่งแจ้ง (
grid-template-columns: 200px 1fr,repeat(3, 1fr)ฯลฯ) - คอลัมน์ต่างๆ ต้องมีขนาดต่างกันหรือไม่ (แถบด้านข้าง + หลัก, ส่วนหัวครอบคลุมทั้งหมด) → ใช้
grid-template-areasสำหรับภูมิภาคที่ตั้งชื่อและอ่านได้ - คอลัมน์ทั้งหมดมีรูปแบบเดียวกันหรือจัดตำแหน่งตามหมายเลขบรรทัดเท่านั้น → ใช้
repeat(N, ...)หรือเส้นที่มีชื่อ - No (ปรับเปลี่ยนตามอุปกรณ์ ไม่ทราบจำนวนรายการ) - ใช้
repeat(auto-fit, minmax(min, 1fr)) - รายการในแถวสุดท้ายควรยืดจนเต็มพื้นที่ที่เหลือหรือไม่ →
auto-fit - แทร็กแถวสุดท้ายที่ว่างเปล่าควรคงขนาดต่ำสุดไว้ (คงช่องว่างของคอลัมน์ไว้) หรือไม่ →
auto-fill
- ใช่ - ใช้แทร็กที่มีเนื้อหาโจ่งแจ้ง (
- คุณต้องการวางรายการในตำแหน่งที่เฉพาะเจาะจงไหม
- ใช่ - ใช้
grid-column: <start> / <end>หรือgrid-area: <name> - ไม่ (เพียงแค่ครอบคลุมหลายแทร็ก ตำแหน่งการไหลไม่สำคัญ) - ใช้
grid-column: span <n>
- ใช่ - ใช้
- องค์ประกอบย่อยจำเป็นต้องรับค่าขนาดแทร็กของตารางกริดหลัก (การจัดแนวขอบไม่สม่ำเสมอในองค์ประกอบระดับเดียวกัน) หรือไม่
- ใช่ - ใช้ตารางกริดย่อยในแกนที่ได้รับผลกระทบ
- จำนวนเด็กต่อเซลล์เป็นตัวแปรหรือไม่ → subgrid แกนเดียวเท่านั้น ใช้
grid-auto-rows/grid-auto-columnsสำหรับอีกแกนหนึ่ง - จำนวนบุตรหลานคงที่หรือไม่ → subgrid บนทั้ง 2 แกนก็ใช้ได้
- ไม่ — ตารางกริดมาตรฐาน ไม่จำเป็นต้องใช้ตารางกริดย่อย
สิ่งที่ควรทำ
- สร้างบริบทด้วย
display: grid - ใช้
grid-template-areasสำหรับเลย์เอาต์ระดับหน้าเว็บที่ซับซ้อน ชื่อพื้นที่จะเป็นเอกสารในตัว และการประกาศสามารถจัดแนวเป็นแถวและคอลัมน์เพื่อให้ดูได้ง่าย - ใช้
repeat(auto-fit, minmax(200px, 1fr))สำหรับตารางกริดการ์ดที่ปรับเปลี่ยนตามอุปกรณ์ซึ่งขยายแทร็กที่เติมแล้วให้เต็มแถว หรือใช้auto-fillเพื่อคงแทร็กที่ซ้ำกันซึ่งว่างเปล่าไว้ที่ขนาดต่ำสุด - ใช้
frสำหรับการกระจายแทร็กตามสัดส่วน และใช้minmax(min, max)สำหรับแทร็กที่ยืดหยุ่นแต่มีขอบเขต - จัดตำแหน่งรายการด้วย
grid-column: span <n>เพื่อปรับขนาดตามแทร็กgrid-column: <start> / <end>เพื่อวางที่บรรทัดที่เฉพาะเจาะจง หรือgrid-area: <name>สำหรับขอบเขตที่มีชื่อ - ใช้ Subgrid (
grid-template-columns: subgridหรือgrid-template-rows: subgrid) เพื่อแก้ปัญหา "ขอบไม่เท่ากัน" ในรายการการ์ด โดยองค์ประกอบภายใน เช่น ชื่อ ข้อมูลเมตา และ CTA จะเรียงกันในระดับเดียวกัน - จับคู่การประกาศ subgrid กับการประกาศ
grid-template-rows/-columnsที่ชัดเจนก่อนหน้าเป็นทางเลือกสำรองแบบเรียงซ้อนเดียวกันสำหรับเบราว์เซอร์รุ่นเก่า
สิ่งที่ไม่ควรทำ
- อย่าคาดหวังว่าขนาดแทร็ก
auto-fit/auto-fillจะมาจากเนื้อหาของรายการ แต่จะมาจากอาร์กิวเมนต์ขนาดrepeat() - อย่าใช้
grid-auto-flow: denseกับเนื้อหาแบบอินเทอร์แอกทีฟ ซึ่งจะจัดเรียงรายการอย่างมีประสิทธิภาพ แต่จะจัดลำดับใหม่ในเชิงภาพ ซึ่งจะทำให้ขั้นตอนการใช้แท็บแป้นพิมพ์ตามลำดับ DOM เสียไป - อย่าใช้ Subgrid กับทั้ง 2 แกนเมื่อจำนวนรายการย่อยเป็นตัวแปร ส่วนเสริมจะอยู่ในแทร็กสุดท้าย ให้ใช้
grid-auto-rows/grid-auto-columnsสำหรับแกนโดยนัยแทน - อย่าสับสนระหว่าง
justify-items/align-items(จัดแนวเนื้อหาของรายการภายในแทร็ก) กับjustify-content/align-content(จัดแนวแทร็กตารางกริดภายในคอนเทนเนอร์) การใช้ค่าที่ไม่ถูกต้องจะไม่มีผลใดๆ - อย่าใช้
repeat(auto-fit/auto-fill, ...)โดยไม่มีinline-sizeที่แน่นอนในคอนเทนเนอร์ เนื่องจากภายในdisplay: inline-gridหรือรายการ Flex ที่ไม่มีขนาด คอนเทนเนอร์จะไม่มีความกว้างให้แบ่ง ซึ่งทำให้คาดเดาจำนวนแทร็กไม่ได้
3.1 ตัวอย่างโค้ด: grid และ subgrid
Page shell: <main class="page-layout"> มี <header>, <aside>, <section class="card-grid"> ที่มี <div class="card"> รายการย่อย และ <footer>
/* Align grid-template-areas in rows and columns for readability. */
.page-layout {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-areas:
"header header header"
"sidebar main main"
"footer footer footer";
gap: 1.5rem;
}
header { grid-area: header; }
aside { grid-area: sidebar; }
footer { grid-area: footer; }
.card-grid {
grid-area: main;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
grid-template-rows: auto 1fr; /* title block, body block */
gap: 1rem;
}
.card {
grid-row: span 2;
display: grid;
/* Same-cascade fallback: ignored when subgrid is supported. */
grid-template-rows: auto 1fr;
grid-template-rows: subgrid;
}
4 การค้นหาคอนเทนเนอร์
ค้นหาขนาด (หรือสไตล์ที่คำนวณแล้ว) ของคอนเทนเนอร์ระดับบนสุดแทนวิวพอร์ต โมเดลทางความคิด: การค้นหาคอนเทนเนอร์ = บริบทของคอมโพเนนต์, การค้นหาสื่อ = เลย์เอาต์หน้าเว็บส่วนกลางและค่ากำหนดของผู้ใช้ (prefers-color-scheme, prefers-reduced-motion)
สิ่งที่ควรทำ
- สร้างบริบทการจำกัดด้วย
container-type: inline-size(การค้นหาความกว้างเท่านั้น) หรือcontainer-type: size(ทั้ง 2 แกน) ใน Wrapper ก่อนที่จะค้นหาองค์ประกอบสืบทอดได้ - ตั้งชื่อคอนเทนเนอร์ด้วย
container-name(หรือชื่อย่อcontainer:container: card / inline-size) เมื่อบริบทที่ฝังอยู่ซ้อนทับกัน - รวมหน่วยการค้นหาคอนเทนเนอร์ในการคำนวณประเภทและระยะห่างแบบไหล:
cqi/cqb(อินไลน์/บล็อกเชิงตรรกะ),cqw/cqh(กายภาพ),cqmin/cqmax - ระบุ
block-sizeที่แน่นอนให้กับคอนเทนเนอร์เมื่อใดก็ตามที่ใช้container-type: sizeหากไม่มี องค์ประกอบสืบทอดจะยุบเนื่องจากการจำกัดขนาดบังคับให้คอนเทนเนอร์ละเว้นเนื้อหา
สิ่งที่ไม่ควรทำ
- อย่าใช้
block-sizeเป็นค่าcontainer-typeเนื่องจากไม่ถูกต้อง ใช้sizeสำหรับทั้ง 2 แกน - อย่าคาดหวังว่าขนาดที่แท้จริงขององค์ประกอบย่อยจะส่งผลต่อคอนเทนเนอร์หลังจากประกาศ
container-typeระบบจะคำนวณคอนเทนเนอร์เสมือนว่าไม่มีองค์ประกอบย่อยเมื่อการกักกันทำงานอยู่ - อย่าใช้หน่วยการค้นหาคอนเทนเนอร์ภายในองค์ประกอบสืบทอดขององค์ประกอบระดับบนสุดที่ไม่เข้าเกณฑ์ เนื่องจากจะเปลี่ยนกลับไปใช้วิวพอร์ตขนาดเล็ก (
svw/svh)
4.1 ตัวอย่างโค้ด: ตัวพิมพ์แบบไหลโดยใช้หน่วยการค้นหาคอนเทนเนอร์
.card-wrapper {
container: card / inline-size; /* shorthand for container-name / container-type */
}
@container card (inline-size > 400px) {
.content {
display: flex;
gap: 2rem;
}
}
.title {
/* Fluid type bound to the container width, not the viewport. */
font-size: clamp(1rem, 4cqi, 2rem);
}
ดูรูปแบบการจัดสไตล์ที่ปรับเปลี่ยนตามอุปกรณ์ซึ่งขับเคลื่อนด้วยคอมโพเนนต์ได้ที่การจัดสไตล์ที่คำนึงถึงขนาดและการปรับขนาดแบบยืดหยุ่น
5 การวางซ้อนแบบเนทีฟ การวางตำแหน่ง Anchor และบริบทการซ้อน
กรณีที่ควรใช้แต่ละองค์ประกอบพื้นฐานของภาพซ้อนทับ
- ใช้
popoverสำหรับ UI ที่ไม่เป็นโมดัลและเกิดขึ้นชั่วคราว (เมนูแบบลอย, ข้อความโทสต์, เคล็ดลับเครื่องมือ) ซึ่งจะอยู่ในเลเยอร์บนสุด โดยไม่จำเป็นต้องจัดการz-index - ใช้
<dialog>กับ.showModal()สำหรับการโต้ตอบโมดัลที่ต้องมีการดักจับโฟกัสและฉากหลังที่ไม่มีการโต้ตอบ - อย่ารวม
popoverและ.showModal()ไว้ในองค์ประกอบเดียวกัน เนื่องจากเป็นสถานะรันไทม์ที่แยกกัน
การจัดตำแหน่ง Anchor (เลย์เอาต์เชิงพื้นที่ของภาพซ้อนทับ):
- ใช้
position-area(หรือanchor()ในส่วนแทรก) และanchor-size()เพื่อจัดตำแหน่งและขนาดของภาพซ้อนทับให้สัมพันธ์กับทริกเกอร์ - ใช้
position-try-fallbacks: flip-block(หรือflip-inline) เพื่อให้เบราว์เซอร์เปลี่ยนตำแหน่งเมื่อการวางซ้อนล้นวิวพอร์ต - อย่าผสมคีย์เวิร์ดทางกายภาพและเชิงตรรกะในค่า
position-areaเดียว ให้เลือกระบบพิกัดเดียว - ตรวจหาฟีเจอร์ด้วย
@supports (anchor-name: --x)และระบุตำแหน่งสำรองแบบสัมบูรณ์
ดูรายละเอียดการติดตั้งใช้งานทั้งหมด กลยุทธ์ Polyfill และข้อมูลอ้างอิงค่า
popoverได้ที่การควบคุมกล่องโต้ตอบและป๊อปโอเวอร์แบบประกาศ และเคล็ดลับเครื่องมือที่รับรู้ตำแหน่ง ดูข้อมูลเกี่ยวกับการกำหนดตำแหน่ง Anchor ที่ใช้กับเมนูแบบเลื่อนลง เมนูแบบลอย และตัวบ่งชี้แท็บได้ที่เมนูแบบเลื่อนลงที่รับรู้วิวพอร์ตและขีดเส้นใต้แท็บการกำหนดตำแหน่ง Anchor
6 การติดตามรายการที่เกินมาและความเสถียรของเลย์เอาต์
จัดการการเปลี่ยนแปลงเลย์เอาต์ แถบเลื่อน และการคลิปได้อย่างคาดการณ์ได้
สิ่งที่ควรทำ
- ใช้
overflow: autoเพื่อให้แถบเลื่อนปรากฏเฉพาะเมื่อเนื้อหาล้นจริงๆ เท่านั้น - ใช้
overflow: clipเพื่อตัดเนื้อหาโดยไม่สร้างคอนเทนเนอร์การเลื่อน เลือกใช้การล้นด้วยoverflow-clip-margin - ใช้
scrollbar-gutter: stableเพื่อสำรองพื้นที่สำหรับแถบเลื่อนและป้องกันไม่ให้เลย์เอาต์เปลี่ยนแปลงเมื่อเนื้อหาเพิ่มขึ้น - ใช้
overscroll-behavior: contain(หรือnone) ในขอบเขตการเลื่อนที่ซ้อนกัน (เช่น แถบด้านข้าง, โมดัล และรายการ) เพื่อหยุดไม่ให้เชนการเลื่อนแสดงขึ้นในหน้า หรือใช้overscroll-behavior: chainใน Wrapper การเลื่อนระดับกลาง (เช่น แทร็กปัดเพื่อแสดง) เมื่อการเลื่อนที่เกินมาควรส่งต่อไปยังตัวเลื่อนระดับบนโดยไม่ทริกเกอร์การเด้งแบบแถบยางในเครื่อง ใช้
-webkit-line-clamp+display: -webkit-box+-webkit-box-orient: verticalไตรแอดสำหรับการตัดทอนหลายบรรทัด แม้จะมีคำนำหน้า แต่รูปแบบนี้ได้รับการระบุอย่างสมบูรณ์และไม่ได้เลิกใช้งาน ประกาศชวเลขline-clampที่ไม่มีคำนำหน้าควบคู่กันไป เบราว์เซอร์ที่ยังไม่รองรับจะละเว้นพร็อพเพอร์ตี้ดังกล่าวโดยไม่เป็นอันตราย สิ่งที่ไม่ควรทำอย่าใช้
overflow: scrollเมื่อautoทำได้ —scrollบังคับให้มีแถบเลื่อนแม้ว่าจะไม่มีอะไรให้เลื่อนก็ตามอย่าใช้
overflow: hiddenเมื่อคุณต้องการเพียงแค่ตัดคลิปเท่านั้นhiddenจะสร้างคอนเทนเนอร์การเลื่อนที่สามารถเลื่อนได้โดยใช้โปรแกรม
.scrollable-list {
max-block-size: 400px;
overflow-y: auto;
scrollbar-gutter: stable; /* Reserve scrollbar space. */
overscroll-behavior: contain; /* No scroll chaining into the page. */
}
.snippet {
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
line-clamp: 3; /* Ignored where unsupported. */
overflow: clip;
}
ดูข้อมูลเชิงลึกเกี่ยวกับ
overflow: clipและoverflow-clip-marginได้ที่การควบคุมการตัดส่วนที่เกิน สำหรับการส่งต่อการเลื่อนที่ซ้อนกันด้วยoverscroll-behavior: chainใน UI แบบปัดเพื่อแสดง ให้ดูที่ปัดเพื่อแสดง ดูข้อมูลเกี่ยวกับสี ขนาด และธีมของแถบเลื่อนได้ที่หัวข้อปรับแต่งสีหรือความหนาของแถบเลื่อน โหมดมืด และปรับแถบเลื่อนให้เหมาะกับค่ากำหนดคอนทราสต์สูง
7 กลไกของวิวพอร์ตและการกระจายแทร็ก
- ใช้
dvh/dvwสำหรับคอนเทนเนอร์เลย์เอาต์บนอุปกรณ์เคลื่อนที่ซึ่งต้องพิจารณาการเลื่อน UI ของเบราว์เซอร์ (การยุบ/ขยายแถบ URL) - อย่าใช้
100vwสำหรับเลย์เอาต์แบบเต็มความกว้าง เนื่องจากจะละเว้นความกว้างของแถบเลื่อนและทำให้เกิดการล้นในแนวนอน โปรดใช้100%,100dvwหรือ100svwแทน
ดูข้อมูลเกี่ยวกับจุดแรกเข้าของการออกแบบที่ปรับเปลี่ยนตามอุปกรณ์ (หน่วยวิวพอร์ตแบบไดนามิก การจองพื้นที่สำหรับสื่อ การจัดพิมพ์แบบไหล) ได้ที่การออกแบบที่ปรับเปลี่ยนตามอุปกรณ์
8 เลนตารางกริด (หรือที่เรียกว่าแบบเรียงต่อกัน)
ข้อกำหนดนี้อยู่ระหว่างการพัฒนาภายใต้ชื่อ "grid lanes" (เช่น display: grid-lanes) ขณะที่ต้นแบบทดลองก่อนหน้านี้ใช้ grid-template-rows: masonry
สิ่งที่ควรทำ
- ใช้ตารางกริดที่มี
grid-auto-flow: denseเพื่อจัดวางองค์ประกอบให้ชิดกันในวันนี้ โดยยอมรับว่าลำดับ DOM อาจไม่ตรงกับลำดับภาพ - ใช้หลายคอลัมน์ (
columns: 3; column-gap: 1rem) สำหรับขั้นตอนที่คล้ายกับ Masonry ซึ่งมีเนื้อหาจำนวนมากเมื่อรายการเป็นส่วนย่อยของเอกสารแทนที่จะเป็นการ์ดที่มีน้ำหนักเท่ากัน - ใช้
grid-template-rows: masonryเป็นการเพิ่มประสิทธิภาพแบบต่อเนื่องเท่านั้น โดยตรวจหาฟีเจอร์ด้วย@supports
สิ่งที่ไม่ควรทำ
- อย่าจัดส่ง
grid-template-rows: masonryเป็นข้อกำหนดที่เข้มงวดจนกว่าเป้าหมาย Baseline จะตามทัน
.gallery { columns: 3 200px; column-gap: 1rem; }
.gallery > * { break-inside: avoid; margin-block-end: 1rem; }
@supports (grid-template-rows: masonry) {
.gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
grid-template-rows: masonry;
gap: 1rem;
columns: unset;
}
}