เลย์เอาต์

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

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

CSS มอบวิธีที่หลากหลาย ในการแก้ปัญหาเลย์เอาต์ บนแกนแนวนอน แกนแนวตั้ง หรือทั้งคู่ การเลือกวิธีการจัดวางที่เหมาะสมกับบริบทอาจเป็นเรื่องยาก และบ่อยครั้งคุณอาจต้องใช้เลย์เอาต์มากกว่า 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 และ Grid

มีกลไกเลย์เอาต์หลัก 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;
}

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

ตารางกริดช่วยให้คุณเขียนกฎเลย์เอาต์ในองค์ประกอบที่มี display: grid และแนะนำพื้นฐานใหม่ๆ 2-3 อย่างสำหรับการจัดรูปแบบเลย์เอาต์ เช่น ฟังก์ชัน 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 จากคอลัมน์แรก ตามด้วยแถวที่สาม จากแถวแรก

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

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

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

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

p span {
    display: inline-block;
}

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

p span {
    margin-top: 0.5rem;
}

แบบลอย

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

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;
}

ขยับองค์ประกอบนี้ลง 10px ตามตำแหน่งปัจจุบันในเอกสาร เนื่องจากอยู่ในตำแหน่งที่สัมพันธ์กับตัวเอง การเพิ่ม 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 ที่คุณตั้งไว้

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

สรุป

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

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

ทดสอบความรู้เกี่ยวกับการจัดวาง

2 สิ่งที่พร็อพเพอร์ตี้ display ทําได้มีอะไรบ้าง

กำหนด inline หรือ block หรือ none
เครื่องมือเลย์เอาต์จำเป็นต้องทราบว่าช่องนี้มีความกว้างเต็มขนาดหรือไม่ และต้องมีการขึ้นบรรทัดใหม่หรือไม่
กำหนดเฟรมเลย์เอาต์แบบตารางกริด
พร็อพเพอร์ตี้การแสดงผลสามารถตั้งค่าการแสดงผลเป็นตารางกริดได้ แต่ไม่เกี่ยวข้องกับเฟรมเลย์เอาต์
กำหนดพฤติกรรมของเด็ก
Flexbox และ grid มีความคิดเห็นและฟีเจอร์ใหม่ๆ สำหรับบุตรหลาน
กำหนดว่าช่องควรเลื่อนหรือไม่
นั่นคือพร็อพเพอร์ตี้ 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 มีฟีเจอร์การห่อชั้นพิเศษที่ต้องใช้รูปแบบเพิ่มเติม