เลย์เอาต์

พอดแคสต์ CSS - 009: เลย์เอาต์

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

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

เลย์เอาต์: ประวัติโดยย่อ

ในยุคแรกๆ ของเว็บ มีการออกแบบที่ซับซ้อนกว่าเอกสารธรรมดาด้วยองค์ประกอบ <table> การแยก HTML ออกจากสไตล์ภาพทำได้ง่ายขึ้นเมื่อเบราว์เซอร์ใช้ CSS กันอย่างแพร่หลายในช่วงปลายยุค 90 CSS เปิดประตูสู่นักพัฒนาที่สามารถเปลี่ยนแปลงรูปลักษณ์ของเว็บไซต์ได้อย่างสิ้นเชิงโดยไม่ต้องยุ่งเกี่ยวกับ HTML เลย ความสามารถใหม่นี้จุดประกายให้โปรเจ็กต์ต่างๆ เช่น The CSS Zen Garden ซึ่งสร้างขึ้นเพื่อแสดงประสิทธิภาพของ CSS เพื่อส่งเสริมให้นักพัฒนาซอฟต์แวร์จำนวนมากขึ้นได้เรียนรู้เกี่ยวกับเรื่องนี้

CSS เปลี่ยนแปลงไปตามความต้องการด้านการออกแบบเว็บและเทคโนโลยีของเบราว์เซอร์ที่เราเปลี่ยนแปลงไป อ่านการเปลี่ยนแปลงของเลย์เอาต์ CSS และแนวทางการจัดวางของเราเมื่อเวลาผ่านไปในบทความนี้โดย Rachel Andrew

ลำดับเวลาแสดงพัฒนาการของ CSS ในช่วงหลายปีที่ผ่านมา ตั้งแต่ปี 1996 ไปจนถึง 2021

เลย์เอาต์: ปัจจุบันและอนาคต

CSS ที่ทันสมัยมีเครื่องมือเลย์เอาต์ที่มีประสิทธิภาพเป็นพิเศษ เรามีระบบสำหรับการจัดวางโดยเฉพาะ และเราจะดูรายละเอียดโดยรวมของสิ่งที่เรามี ก่อนที่จะเจาะลึกลงไปในรายละเอียดของ Flexbox และ Grid ในโมดูลถัดไป

ทำความเข้าใจพร็อพเพอร์ตี้ display

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

.my-element {
  display: inline;
}

องค์ประกอบในบรรทัดทำงานเหมือนคำในประโยค ทั้งสองนั่งอยู่ข้างกันในทิศทางในบรรทัด องค์ประกอบอย่างเช่น <span> และ <strong> ซึ่งโดยทั่วไปจะใช้เพื่อจัดรูปแบบข้อความภายในที่มีองค์ประกอบต่างๆ เช่น <p> (ย่อหน้า) จะอยู่แทรกในบรรทัดโดยค่าเริ่มต้น และยังรักษาช่องว่างโดยรอบไว้

แผนภาพแสดงกล่องขนาดต่างๆ ทั้งหมดและส่วนการกำหนดขนาดแต่ละส่วนเริ่มต้นและสิ้นสุด

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

.my-element {
    display: block;
}

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

.my-element {
    display: flex;
}

พร็อพเพอร์ตี้ display ยังกำหนดลักษณะการทํางานของบุตรหลานขององค์ประกอบด้วย ตัวอย่างเช่น การตั้งค่าพร็อพเพอร์ตี้ display เป็น display: flex จะทำให้ช่องดังกล่าวเป็นกล่องระดับบล็อก และแปลงรายการย่อยเป็นรายการแบบยืดหยุ่นด้วย ซึ่งจะเป็นการเปิดใช้พร็อพเพอร์ตี้ Flex ที่ควบคุมการจัดเรียง การจัดเรียง และการไหล

Flexbox และตารางกริด

กลไกเลย์เอาต์หลักที่สร้างกฎเลย์เอาต์สำหรับองค์ประกอบหลายรายการมี 2 รายการ ได้แก่ flexbox และ grid ทั้งสองแบบมีความคล้ายคลึงกัน แต่ได้รับการออกแบบมาเพื่อแก้ปัญหาด้านรูปแบบที่แตกต่างกัน

เฟล็กซ์บ็อกซ์

.my-element {
    display: flex;
}

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

รายการจะอยู่ในแกนเดียวกันและไม่ตัดออกเมื่อพื้นที่เต็ม แต่พวกมันจะพยายามตีกรอบให้อยู่บนแนวเดียวกันแทน คุณเปลี่ยนลักษณะการทำงานนี้ได้โดยใช้พร็อพเพอร์ตี้ align-items, justify-content และ flex-wrap

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

.my-element div {
    flex: 1 0 auto;
}

พร็อพเพอร์ตี้ flex เป็นชื่อย่อของ flex-grow, flex-shrink และ flex-basis ตัวอย่างด้านบนจะขยายได้ดังนี้

.my-element div {
 flex-grow: 1;
 flex-shrink: 0;
 flex-basis: auto;
}

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

GRid

.my-element {
    display: grid;
}

ตารางกริดมีความคล้ายคลึงกันมากกับ flexbox แต่ออกแบบมาเพื่อควบคุมเลย์เอาต์หลายแกนแทนเลย์เอาต์แบบแกนเดียว (พื้นที่แนวตั้งหรือแนวนอน)

ตารางกริดให้คุณเขียนกฎเลย์เอาต์ในองค์ประกอบที่มี display: grid และแนะนํารูปแบบพื้นฐานใหม่ๆ บางอย่างสำหรับการจัดรูปแบบเลย์เอาต์ เช่น ฟังก์ชัน repeat() และ minmax() หน่วยตารางกริดที่มีประโยชน์ 1 หน่วยคือหน่วย fr ซึ่งเป็นพื้นที่ส่วนหนึ่งที่เหลืออยู่ คุณสร้างตารางกริดแบบ 12 คอลัมน์แบบดั้งเดิมได้โดยมีช่องว่างระหว่างแต่ละรายการด้วยพร็อพเพอร์ตี้ CSS 3 รายการ ดังนี้

.my-element {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 1rem;
}

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

.my-element :first-child {
  grid-row: 1/3;
  grid-column: 1/4;
}

พร็อพเพอร์ตี้ grid-row และ grid-column จะสั่งให้องค์ประกอบแรกในตารางกริดทอดไปยังจุดเริ่มต้นของคอลัมน์ที่ 4 จากคอลัมน์แรกไปต่อท้ายแถวที่ 3 จากแถวแรก

เลย์เอาต์โฟลว์

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

บล็อกในบรรทัด

จำได้ไหมว่าองค์ประกอบที่อยู่รอบๆ ไม่ลดขอบของบล็อกและระยะห่างจากขอบบนองค์ประกอบในบรรทัด inline-block จะช่วยให้คุณสามารถทำสิ่งนั้นได้

p span {
    display: inline-block;
}

การใช้ inline-block จะช่วยให้คุณได้ช่องที่มีลักษณะเฉพาะขององค์ประกอบระดับบล็อก แต่ยังคงแทรกในบรรทัดไปกับข้อความ

p span {
    margin-top: 0.5rem;
}

แบบลอย

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

img {
    float: left;
    margin-right: 1em;
}

พร็อพเพอร์ตี้ float สั่งให้องค์ประกอบ "ลอย" ไปยังทิศทางที่ระบุ รูปภาพในตัวอย่างนี้จะได้รับคำสั่งให้ลอยไปทางซ้าย ซึ่งจะทำให้องค์ประกอบระดับเดียวกัน "ตัด" ล้อมรอบภาพได้ คุณสั่งให้องค์ประกอบลอย left, right หรือ inherit ได้

เลย์เอาต์หลายคอลัมน์

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

<h1>All countries</h1>
<ul class="countries">
  <li>Argentina</li>
  <li>Aland Islands</li>
  <li>Albania</li>
  <li>Algeria</li>
  <li>American Samoa</li>
  <li>Andorra</li>
  …
</ul>
.countries {
    column-count: 2;
    column-gap: 1em;
}

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

.countries {
    width: 100%;
    column-width: 260px;
    column-gap: 1em;
}

คุณยังกำหนดความกว้างขั้นต่ำที่ต้องการได้โดยใช้ column-width แทนการตั้งค่าจำนวนคอลัมน์ที่จะแบ่งเนื้อหา เมื่อมีพื้นที่มากขึ้นในวิวพอร์ต ระบบจะสร้างคอลัมน์มากขึ้นโดยอัตโนมัติ และเมื่อพื้นที่ลดลง คอลัมน์ก็จะลดลงด้วยเช่นกัน ซึ่งจะเป็นประโยชน์มากในบริบทการออกแบบเว็บที่ตอบสนองตามอุปกรณ์

จุดยืน

ส่วนสุดท้ายสำหรับภาพรวมของกลไกการออกแบบนี้คือการวางตำแหน่ง พร็อพเพอร์ตี้ position จะเปลี่ยนลักษณะการทำงานขององค์ประกอบในเส้นทางปกติของเอกสาร และความเกี่ยวข้องกับองค์ประกอบอื่นๆ ตัวเลือกที่ใช้ได้คือ relative, absolute, fixed และ sticky โดยมีค่าเริ่มต้นเป็น static

.my-element {
  position: relative;
  top: 10px;
}

องค์ประกอบนี้จะขยับลง 10 พิกเซลตามตำแหน่งปัจจุบันในเอกสารเนื่องจากอยู่ในตำแหน่งที่สัมพันธ์กับตัวมันเอง การเพิ่ม position: relative ลงในองค์ประกอบจะทำให้องค์ประกอบดังกล่าวเป็นบล็อกที่มีองค์ประกอบย่อยทุกรายการที่มี position: absolute อยู่ด้วย ซึ่งหมายความว่าตอนนี้จะมีการเลื่อนตำแหน่งย่อยไปยังองค์ประกอบเฉพาะนี้ แทนระดับบนสุดที่เกี่ยวข้องที่สุดเมื่อมีการใช้ตําแหน่งสัมบูรณ์

.my-element {
  position: relative;
  width: 100px;
  height: 100px;
}

.another-element {
    position: absolute;
    bottom: 0;
    right: 0;
    width: 50px;
    height: 50px;
}

เมื่อตั้งค่า position เป็น absolute ระบบจะแยกองค์ประกอบออกจากโฟลว์เอกสารปัจจุบัน กรณีนี้มี 2 สิ่งต่อไปนี้

  1. คุณวางตำแหน่งองค์ประกอบนี้ได้ทุกที่ที่ต้องการ โดยใช้ top, right, bottom และ left ในระดับบนสุดที่เกี่ยวข้อง
  2. เนื้อหาทั้งหมดที่อยู่รอบองค์ประกอบแบบสัมบูรณ์จะจัดเรียงใหม่เพื่อให้เต็มพื้นที่ที่เหลือขององค์ประกอบนั้น

องค์ประกอบที่มีค่า position เป็น fixed มีลักษณะการทำงานคล้ายกับ absolute โดยมีระดับบนสุดเป็นองค์ประกอบ <html> รูท องค์ประกอบของตำแหน่งคงที่จะยึดตำแหน่งจากด้านซ้ายบนตามค่า top, right, bottom และ left ที่คุณตั้งไว้

คุณจะใช้ sticky เพื่อบรรลุด้าน Anchor แบบคงที่ของ fixed และลักษณะการไหลของเอกสารที่คาดเดาได้มากขึ้นของ relative ค่านี้เมื่อวิวพอร์ตเลื่อนผ่านองค์ประกอบไป ค่าจะยึดกับค่า top, right, bottom และ left ที่คุณตั้งไว้

สรุป

เลย์เอาต์ CSS มีตัวเลือกและความยืดหยุ่นมากมาย หากต้องการเจาะลึกเกี่ยวกับความสามารถของ CSS Flexbox และ Grid ให้ดำเนินการต่อในโมดูลต่อๆ ไป

ตรวจสอบความเข้าใจของคุณ

ทดสอบความรู้ของคุณเกี่ยวกับเลย์เอาต์

พร็อพเพอร์ตี้ display ทําอะไร 2 อย่าง

กำหนด inline หรือ block หรือ none
เครื่องมือเลย์เอาต์จำเป็นต้องทราบว่าช่องนี้มีความกว้างเต็มขนาดหรือไม่ และจำเป็นต้องขึ้นบรรทัดใหม่
กำหนดเฟรมเลย์เอาต์แบบตารางกริด
พร็อพเพอร์ตี้ Display สามารถตั้งค่าการแสดงผลเป็นตารางกริดได้ แต่ไม่ได้เกี่ยวข้องกับเฟรมเลย์เอาต์
กำหนดพฤติกรรมของบุตรหลาน
Flexbox และตารางกริดมีความคิดเห็นและฟีเจอร์ใหม่ๆ สำหรับบุตรหลาน
กำหนดว่าควรเลื่อนช่องดังกล่าวหรือไม่
นี่คือพร็อพเพอร์ตี้ overflow

หากต้องการเปลี่ยนหลายย่อหน้าลงในคอลัมน์ พร็อพเพอร์ตี้ CSS ใดเหมาะกับงานนี้มากที่สุด

display: grid
แม้ว่าตารางกริดอาจใส่หลายย่อหน้าลงในคอลัมน์ได้ แต่คอลัมน์เหล่านั้นจะเป็นคอลัมน์ของตัวเอง ไม่ได้เรียงต่อกันจากย่อหน้าหนึ่งไปยังอีกคอลัมน์หนึ่ง
column-count
ย่อหน้าจะเริ่มจากจุดสิ้นสุดของคอลัมน์หนึ่งไปจนถึงจุดเริ่มต้นของย่อหน้าถัดไป เช่นเดียวกับที่นิตยสารหรือหนังสือพิมพ์ทำ
display: flex
แม้ Flex สามารถใส่หลายย่อหน้าลงในคอลัมน์ได้ แต่คอลัมน์เหล่านั้นจะเป็นคอลัมน์ของตัวเอง โดยไม่จำเป็นต้องเรียงต่อกันจากคอลัมน์หนึ่งไปยังรายการถัดไป
float
ลองอีกครั้งนะ

หากบล็อกออกไม่ได้หมายความว่าอย่างไร

ติดอยู่ที่ฝั่งแม่น้ำค่ะ
บริบทจะเป็น CSS ไม่ใช่ภูมิศาสตร์
มีการระบุค่าตำแหน่ง top หรือ left
การมีพร็อพเพอร์ตี้เหล่านี้เพียงอย่างเดียวไม่ได้ทำให้สับสนได้
ไม่ได้อิงตามตำแหน่งข้างเคียงอีกต่อไป
ตัวอย่างเช่น ช่องที่มี position: absolute จะวางตำแหน่งด้วยพิกัด x และ y ตามการบล็อกที่มีอยู่ ไม่ใช่ลำดับกับองค์ประกอบระดับข้างเคียงอื่นๆ

Flexbox และ Grid รวมบุตรหลานโดยค่าเริ่มต้นไหม

จริง
คุณต้องเลือกใช้ด้วย flex-wrap: wrap หรือ repeat(auto-fit, 30ch)
เท็จ
Flexbox และ Grid มีฟีเจอร์การตัดแบบพิเศษที่ต้องใช้รูปแบบเพิ่มเติม