2 คะแนน โดย GN⁺ 2024-08-17 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • CSS Grid ได้รับการรองรับอย่างกว้างขวางในเบราว์เซอร์หลักตั้งแต่เดือนมีนาคม 2017 แต่ grid-template-areas ยังถูกใช้น้อยกว่า ทั้งที่สามารถแสดงเลย์เอาต์ใน CSS ได้แบบเป็นภาพ โดยไม่ต้องคำนวณหมายเลข line
  • grid-template-areas ทำงานโดยจัดวางชื่อพื้นที่ด้วยสตริง แล้วเชื่อมโยงองค์ประกอบลูกด้วย grid-area โดยชื่อเดียวกันจะต้องก่อตัวเป็น พื้นที่สี่เหลี่ยมผืนผ้า เสมอ
  • named grid lines คือการตั้งชื่อให้ line เช่น content-start / content-end และแพตเทิร์น *-start กับ *-end เบราว์เซอร์สามารถนำไปใช้เหมือนเป็น พื้นที่โดยนัย ได้
  • ในกรณีอย่างการพลิกการ์ด, header แบบ responsive, เลย์เอาต์เชิง editorial, โพสต์สไตล์ Threads, การ์ดที่ซ้อนทับกัน และเลย์เอาต์แบบมีเงื่อนไขด้วย :has() สามารถจัดการ รูปแบบการจัดวาง ได้โดยเปลี่ยนแค่สตริงพื้นที่ของ parent
  • Chrome, Safari และ Firefox ล้วนมี DevTools สำหรับพื้นที่ Grid โดย Firefox มีประโยชน์เป็นพิเศษตรงการแสดงชื่อพื้นที่และ autocomplete ชื่อ line ที่เป็นไปได้เมื่อแก้ไข grid-area

ทำให้เลย์เอาต์อ่านง่ายขึ้นด้วย grid-template-areas

  • การจัดวาง CSS Grid แบบเดิมมักใช้วิธีกำหนด หมายเลข line โดยตรง เช่น grid-column: 1 / 3
  • หมายเลข line มองไม่เห็นจนกว่าจะตรวจสอบใน DevTools และในเลย์เอาต์ที่มีทั้งคอลัมน์และแถว การคำนวณหมายเลขที่ถูกต้องในหัวทำได้ยาก
  • grid-template-areas จัดวางโดยตั้งชื่อให้แต่ละเซลล์ ทำให้โค้ด CSS เองดูเหมือน แผนที่ ของเลย์เอาต์
.page {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-areas: "item1 item2";
  gap: 1rem;
}

.item-1 {
  grid-area: item1;
}

.item-2 {
  grid-area: item2;
}
  • องค์ประกอบลูกจะถูกแมปไปยังพื้นที่ที่มีชื่อผ่าน grid-area
  • ในตัวอย่างการ์ด สามารถกำหนดเป็น "featured featured article" เพื่อให้พื้นที่ featured กิน 2 คอลัมน์ และพื้นที่ article กิน 1 คอลัมน์ได้

ไวยากรณ์และกฎที่ต้องปฏิบัติตาม

  • grid-template-areas รับ สตริงพื้นที่ ตั้งแต่หนึ่งรายการขึ้นไป
    • สตริงหนึ่งรายการสร้างเลย์เอาต์หนึ่งมิติที่มีเฉพาะคอลัมน์
    • หลายสตริงประกอบเป็นเลย์เอาต์หลายมิติที่มีแถวและคอลัมน์
  • เมื่อต้องใช้หลายสตริง การเขียนแยกบรรทัดจะทำให้อ่านเลย์เอาต์ได้ง่ายขึ้น
.element {
  display: grid;
  grid-template-columns: 200px 1fr;
  grid-template-areas:
    "aside main"
    "footer footer";
}
  • แต่ละสตริงแทน แถว หนึ่งของกริด และสามารถคิดเหมือนเป็นตารางได้
  • พื้นที่ที่กำหนดด้วยชื่อเดียวกันต้องเป็น สี่เหลี่ยมผืนผ้า ในโค้ด
/* invalid */
.layout {
  grid-template-areas:
    "header header"
    "sidebar main"
    "header footer";
}

/* valid */
.layout {
  grid-template-areas:
    "header header"
    "sidebar main"
    "sidebar footer";
}
  • ทุกแถวต้องมีจำนวน token ของพื้นที่เท่ากัน และแม้จะไม่ใช้พื้นที่ที่ต้องการ ก็ยังต้องกำหนดตัวเซลล์เอง
  • เซลล์ว่างสามารถแทนด้วยจุดหนึ่งจุดหรือหลายจุดได้
.element {
  grid-template-areas:
    "aside main"
    "... footer";
}
  • จุดคือ null cell token ในข้อกำหนด CSS Grid ใช้แทนเซลล์กริดที่ว่าง

ความสัมพันธ์ระหว่าง named grid lines กับพื้นที่

  • ใน CSS Grid จำนวน line จะมากกว่าจำนวนคอลัมน์หนึ่งเสมอ
    • หากมี 3 คอลัมน์ จะมี grid line 4 เส้น
  • named grid lines คือการตั้ง ชื่อเฉพาะ ให้ line แทนการใช้ตัวเลขพื้นฐาน
.layout {
  grid-template-columns:
    [full-start] 1fr
    [content-start] 2fr
    [content-end] 1fr [full-end];
}

.item {
  grid-column: content-start / content-end;
}
  • แม้จะตั้งชื่อให้ line แล้ว ก็ยังใช้ line แบบตัวเลขต่อไปได้
  • ขนาด track (track size) หมายถึงขนาดของคอลัมน์หรือแถว และค่าประเภท 1fr 1fr คือขนาด track
  • ใน named lines จะตั้งชื่อ line ที่ล้อมรอบ track
.layout {
  display: grid;
  grid-template-columns:
    [aside-start] 200px [aside-end main-start] 1fr [main-end];
}
  • line หนึ่งสามารถมีหลายชื่อร่วมกันได้ และในตัวอย่างข้างต้น aside-end กับ main-start คือ line เดียวกัน
  • หากกำหนดชื่อแบบ *-start / *-end เช่น aside-start และ aside-end เบราว์เซอร์จะอนุญาตให้ใช้รูปแบบอย่าง grid-column: aside ผ่าน ชื่อ line โดยนัย ได้
  • ไม่จำเป็นต้องตั้งชื่อให้ทุก line สามารถเลือกตั้งชื่อเฉพาะ line ที่สำคัญได้
  • ขณะจัดวาง สามารถผสมตัวเลขกับชื่อได้ เช่น grid-column: 1 / content-end

จัดการรูปแบบการจัดวางด้วยสตริงพื้นที่ของ parent

  • เมื่อใช้ grid-template-areas สามารถเปลี่ยนเลย์เอาต์โดยรวมได้โดยคงชื่อ grid-area ขององค์ประกอบลูกไว้เหมือนเดิม แล้วเปลี่ยนเฉพาะสตริงพื้นที่ของ parent
.aside {
  grid-area: aside;
}

.main {
  grid-area: main;
}

.footer {
  grid-area: footer;
}
  • เมื่อคงชื่อ aside, main, footer เดิมไว้ แล้วเปลี่ยนเฉพาะสตริง grid-template-areas การจัดวางทั้งหมดจะอัปเดตโดยอัตโนมัติ
  • การควบคุมเลย์เอาต์ถูก รวมศูนย์ อยู่ที่นิยามพื้นที่ของ parent ทำให้ปรับแต่งได้ง่ายขึ้น

พลิกทิศทางการ์ด

  • ใน Flexbox สามารถพลิกทิศทางการ์ดได้ง่ายด้วย flex-direction: row-reverse
  • ใน CSS Grid หากใช้หมายเลข line เมื่อเปลี่ยนทิศทางจะต้องแก้ทั้งนิยามคอลัมน์และค่า grid-column ของลูกแต่ละตัว
  • เมื่อใช้พื้นที่ที่มีชื่อ ให้กำหนดรูปภาพและเนื้อหาของการ์ดเป็นพื้นที่ แล้วเปลี่ยนเฉพาะลำดับพื้นที่ของ parent ก็พอ
.card {
  display: grid;
  grid-template-columns: 150px 1fr;
  grid-template-areas: "thumb content";
}

.card__thumb {
  grid-area: thumb;
}

.card__content {
  grid-area: content;
}

.card--flip {
  grid-template-columns: 1fr 150px;
  grid-template-areas: "content thumb";
}
  • สามารถแสดงการจัดวางแบบเดียวกันด้วย shorthand property grid-template ได้เช่นกัน
.card--flip {
  grid-template: "content image" / 1fr 150px;
}
  • shorthand property เป็นทางเลือก และบางคนอาจมองว่า longhand property อ่านง่ายกว่า

เลย์เอาต์ header แบบ responsive

  • header ที่มีโลโก้ การนำทาง และพื้นที่ action สามารถเริ่มจากคอลัมน์ขนาดเท่ากัน 3 คอลัมน์ได้
  • หากใช้หมายเลข line จะต้องกำหนด grid-column ให้ .logo, .nav, .actions แต่ละตัว
  • หากใช้ชื่อพื้นที่ ให้แมปลูกแต่ละตัวไปที่ logo, nav, actions แล้วเปลี่ยนเฉพาะ grid-template-areas ของ parent ตาม viewport ก็พอ
.header {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-areas: "logo nav actions";
}

.logo {
  grid-area: logo;
}

.nav {
  grid-area: nav;
}

.actions {
  grid-area: actions;
}
  • ในขนาดเล็ก สามารถวางโลโก้และ action ไว้บรรทัดแรก และให้ navigation กินความกว้างเต็มบรรทัดได้
.header {
  grid-template-areas:
    "logo logo actions"
    "nav nav nav";
}
  • ตั้งแต่ 380px ขึ้นไป สามารถวางโลโก้ไว้ซ้าย และวาง navigation กับ action ไว้ขวาได้
@media (min-width: 380px) {
  .header {
    grid-template-areas:
      "logo nav nav"
      "logo actions actions";
  }

  .nav {
    justify-self: end;
  }
}
  • ตั้งแต่ 900px ขึ้นไป สามารถกลับไปใช้การจัดวางบรรทัดเดียวได้
@media (min-width: 900px) {
  .header {
    grid-template-areas: "logo nav actions";
  }
}
  • สตริงพื้นที่ทำหน้าที่เหมือน การแมป ที่แสดงการจัดวาง UI โดยตรงใน CSS

ตัวอย่างเลย์เอาต์เชิง editorial

  • ส่วนที่มีหัวข้อ ข้อความ และรูปภาพ สามารถใช้ grid-template-areas เพื่อเปลี่ยนการจัดวางตามขนาด viewport ได้ง่าย
.section {
  display: grid;
  grid-template-areas:
    ". title title"
    "thumb content content";
  gap: 1rem;
}
  • จุดทางซ้ายของหัวข้อคือ null cell token ที่แทนพื้นที่ว่าง
  • ในตัวอย่างส่วนสไตล์ time.com ใช้พื้นที่ feature, secondary, most-read พร้อมคอลัมน์ว่างสองข้าง
.featured-section {
  display: grid;
  grid-template-areas:
    ". feature most-read ."
    ". secondary most-read .";
  grid-template-columns: 1fr minmax(auto, 57.313rem) minmax(12rem, 18.75rem) 1fr;
  grid-template-rows: minmax(auto, 25rem) 1fr;
}
  • คอลัมน์ว่างสองข้างมักทำหน้าที่เป็นระยะห่างซ้ายขวา
  • ในเวอร์ชัน responsive บนหน้าจอเล็กจะซ้อน feature, secondary, most-read ในแนวตั้ง และตั้งแต่ 500px กับ 900px ขึ้นไปจะเปลี่ยนนิยามคอลัมน์และพื้นที่
  • grid-template-rows สามารถถูกแทนด้วยนิยามพื้นที่ได้ จึงไม่จำเป็นเสมอไป

คอมโพเนนต์โพสต์สไตล์ Threads

  • ขณะตรวจสอบ CSS ของ Threads app by Meta สามารถเห็นกรณีการใช้ CSS Grid ในคอมโพเนนต์โพสต์ได้
  • ตัวอย่างเดิมจัดวาง item ด้วย grid-template-columns, grid-template-rows และหมายเลข line
.postBody {
  grid-column-start: 2;
  grid-row-start: 2;
  grid-row-end: span 3;
}
  • โพสต์หลายรูปแบบสามารถแสดงด้วย grid-template-areas ได้ง่ายกว่า
.post {
  grid-template-areas:
    "avatar header"
    "avatar body"
    ". body"
    ". footer";
}

.post--reply {
  grid-template-rows: 40px max-content max-content;
  grid-template-areas:
    "avatar header"
    "body body"
    "body body"
    "footer footer";
}

.post--nested {
  grid-template-areas:
    "avatar header"
    "avatar body"
    "line body"
    "footer footer";
}
  • สามารถแยกแยะโพสต์แบบพื้นฐาน แบบตอบกลับ และแบบซ้อนกันได้จากสตริงพื้นที่เท่านั้น

item ที่ซ้อนทับกันและชื่อพื้นที่

  • ใน grid-template-areas ชื่อเดียวกันต้องเป็นสี่เหลี่ยมผืนผ้า ดังนั้นหากใช้ชื่อเดียวกันซ้ำในรูปทรงที่ไม่ใช่สี่เหลี่ยมผืนผ้า จะไม่ถูกต้อง
.layout {
  display: grid;
  grid-template-columns: 1fr 1fr fr;
  grid-template-areas:
    "card tag tag"
    "title title card";
}
  • ตัวอย่างข้างต้น invalid เพราะ card ไม่ได้ก่อตัวเป็นสี่เหลี่ยมผืนผ้า
  • ในการ์ดที่ซ้อนทับกัน สามารถกำหนดชื่อพื้นที่ใหม่ เช่น thumb-1, thumb-2 แล้วใช้ชื่อนั้นใน grid-column และ grid-row ได้
.card {
  display: grid;
  grid-template-columns: auto auto 1fr;
  grid-template-rows: auto auto;
  grid-template-areas:
    "thumb-1 tag"
    "title thumb-2";
}

.thumb {
  grid-column: thumb-1 / thumb-2;
  grid-row: thumb-1 / thumb-2;
}
  • tag และ title สามารถวางใน grid-area แต่ละตัว แล้วจัดแนวด้วย align-self, justify-self ได้
  • หากจำเป็นต้องจัดการ ลำดับการซ้อน ขององค์ประกอบลูก แต่ในตัวอย่างนี้ใช้เพียงลำดับใน source ก็พอ
  • ตัวอย่างการซ้อนทับนี้ได้รับแรงบันดาลใจจากหน้า Oddbird’s Cascading Layouts

:has() และเลย์เอาต์แบบมีเงื่อนไข

  • เมื่อรวม selector CSS :has() กับพื้นที่ Grid จะสามารถเปลี่ยนเลย์เอาต์ตามการมีอยู่ขององค์ประกอบบางตัวได้
  • สามารถใช้นิยามพื้นที่ต่างกันสำหรับกรณีที่ภายใน <figure> มี figcaption และไม่มีได้
figure {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-areas: "img img img";
  gap: 0.5rem;
}

img {
  grid-area: img;
}

figcaption {
  grid-area: caption;
}

.card:has(figcaption) {
  grid-template-areas:
    "img img caption"
    "img img .";
}

รองรับทิศทางหลายภาษาทั้ง LTR/RTL

  • CSS Grid ปรับเลย์เอาต์ตามทิศทางของหน้าเว็บว่าเป็น LTR หรือ RTL
  • named grid areas ก็จะตามทิศทางของหน้าเช่นกัน ดังนั้นในค่า RTL เลย์เอาต์จะถูกพลิก
  • สำหรับข้อมูลเกี่ยวกับการเขียนเลย์เอาต์ RTL สามารถดูคู่มือ RTL Styling 101 ได้

ความแตกต่างของการรองรับใน DevTools

  • Chrome, Safari และ Firefox ล้วนมี DevTools สำหรับพื้นที่ Grid
  • Chrome
    • วางชื่อพื้นที่ไว้ที่มุมซ้ายบน ทำให้พื้นที่อาจดูซ้อนกันได้
    • overlay สีอาจเปลี่ยนวิธีที่เห็นดีไซน์
  • Safari
    • เส้นขอบสีชมพูช่วยแยก item ได้ชัดเจน
    • สามารถดูชื่อ line ได้
    • วิธีแสดงชื่อ line ยังมีพื้นที่ให้ปรับปรุง เช่น การแสดงแบบซ้อนบรรทัด
  • Firefox
    • ชื่อพื้นที่มองเห็นได้ชัดเจนกว่า Chrome และ Safari
    • มีรายการ autocomplete เมื่อป้อนชื่อกำหนดเองอย่าง *-start, *-end
    • เมื่อแก้ไข grid-area ของ item ลูก จะมีรายการชื่อ line ที่เป็นไปได้ทั้งหมด

แหล่งข้อมูลอ้างอิง

1 ความคิดเห็น

 
GN⁺ 2024-08-17
ความคิดเห็นบน Hacker News
  • เดโมแอนิเมชันน่าสนใจทีเดียว แต่พอรู้ว่าแอนิเมชันนั้น ไม่ได้ทำด้วย CSS ก็รู้สึกเสียดาย
    หลังจากเรียน Flexbox แล้วก็คิดว่า “แค่นี้ก็พอแล้ว” เลยไม่ได้ศึกษา Grid แบบลึก ๆ ดูเหมือนจะมีเหตุผลให้ชอบ Grid อยู่ [0] แต่โดยรวมแล้วไม่เคยต้องทำงานที่ทำได้ด้วย Grid เท่านั้น และสำหรับตารางข้อมูลก็ใช้ <table> จริง ๆ
    [0] https://css-tricks.com/css-grid-replace-flexbox/

    • การได้เรียนเครื่องมือที่ครอบคลุมทุกอย่างที่ต้องการถือเป็นเรื่องดี
      เคยใช้ Grid แค่กับ แกลเลอรีภาพแบบ responsive อย่าง https://labs.jensimmons.com/2016/examples/image-gallery-grid... หรือการ์ดแบบ responsive อย่าง https://every-layout.dev/demos/grid-cards/ เท่านั้น grid-template-columns คุ้มที่จะเรียน และ grid-gap ก็สะดวก นอกนั้นรู้สึกว่า Flexbox จัดการได้เกือบหมด
      แต่ grid-template-areas ยังรู้สึกก้ำกึ่งอยู่ บทความยกเหตุผลว่าช่วยปรับเลย์เอาต์ตาม breakpoint หรือทำให้ “เมื่อสมาชิกทีมต้องเปลี่ยนเลย์เอาต์” ง่ายขึ้น แต่ก็อาจเป็นแค่ว่าผมไม่ใช่ผู้อ่านเป้าหมายก็ได้
    • เครื่องมือสนุก ๆ สำหรับเรียน Grid: https://cssgridgarden.com/
    • Flex เพียงพอในกรณีส่วนใหญ่ แต่ Grid ก็มีที่ทางของมัน เช่น เลย์เอาต์การ์ด 3 คอลัมน์ ที่ยุบลงเหลือหนึ่งการ์ดต่อแถวบนหน้าจอเล็ก, โครงสร้างหน้าที่มี sidebar เฉพาะ, หรือองค์ประกอบที่ต้องคงการจัดวางบางแบบไว้แม้ระหว่างปรับขนาด
      ใช้ทั้งสองอย่างตามความจำเป็นก็พอ และเมื่อรวมกันแล้วจะเป็นเครื่องมือจัดเลย์เอาต์ที่ทรงพลังมาก
    • “ไม่ครับ Flexbox ไม่ได้ ‘ดีพอแล้ว’”
      https://www.youtube.com/watch?v=MWWcZzossc8
  • เดี๋ยวนะ 1/3 ไม่ใช่เศษส่วน แต่เป็นช่วงตั้งแต่ 1 ถึง 3 งั้นเหรอ? ไม่เข้าใจว่าทำไมถึงเลือกไวยากรณ์แบบนั้น ทั้งที่ในงานเขียนโปรแกรมมีไวยากรณ์สำหรับช่วงที่สมเหตุสมผลและรู้จักกันดีอยู่มากมาย เช่น 1..3

    • สิ่งแรกที่ควรรู้เกี่ยวกับ CSS คือ CSS ใช้ภาษาของการจัดเลย์เอาต์สิ่งพิมพ์ ไม่ใช่ การแสดงออกแบบภาษาโปรแกรม
      ปัญหาจำนวนมากที่โปรแกรมเมอร์เจอกับ CSS ดูเหมือนจะมาจากความเข้าใจผิดนี้
    • ความสามารถของ Grid นั้นดี แต่ไวยากรณ์ค่อนข้างต่างจาก CSS ส่วนอื่น ๆ เลยทำให้สับสน ดูเหมือนร่องรอยว่ามุมนี้ถูกแยกไปทำต่างหาก หรือไม่ก็เข้าหาแบบ “คราวนี้มาทำให้ถูกต้องกันเถอะ”
    • ทั้งสองฝั่งของสแลชไม่ได้มีแค่ตัวเลขเท่านั้น แต่เป็นคำหลายคำก็ได้: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-column...
    • ลองนึกว่าต้องบอกโปรแกรมเมอร์ว่า !important ใน CSS ไม่ได้แปลว่า “ไม่สำคัญ” แต่แปลว่า “สำคัญ!” นั่นแหละ
  • ยังจับ Grid กับ Flexbox ได้ไม่ถนัดเลย กลยุทธ์จัดเลย์เอาต์ล่าสุดที่พอใช้ได้ดีหน่อยคือ float พอได้อ่านบทความนี้ก็มั่นใจขึ้นว่าจะลองใช้ CSS Grid ตอนออกแบบเลย์เอาต์ครั้งหน้า และบทความก็ทำออกมาดีด้วย

    • ถ้าเคยใช้ float มาแล้ว Grid กับ Flex จะง่ายกว่ามาก แค่กันเวลาสักวันสองวันมาลองทำเลย์เอาต์ไม่กี่แบบก็พอ ต่างจากยุคที่ต้องสู้กับเบราว์เซอร์เก่า ๆ สองอย่างนี้ทำงานได้ดีเฉย ๆ และจริง ๆ แล้วอาจน่าเบื่อด้วยซ้ำ
      มีบทความดี ๆ มากมาย แต่แค่อ่านสองบทความนี้ของ CSS-Tricks ก็เพียงพอแล้ว
      https://css-tricks.com/snippets/css/a-guide-to-flexbox/
      https://css-tricks.com/snippets/css/complete-guide-grid/
    • Grid ไม่เรียนก็ยังพออยู่ได้ในระดับหนึ่ง แต่ Flexbox แทบจะจำเป็น เพราะสะดวกกว่า float hacking แบบเก่ามาก และฝังอยู่ทั่ว CSS สมัยใหม่
      นอกจากบทความ CSS-Tricks ที่กล่าวไปแล้ว ยังแนะนำคู่มือ Flexbox ของ MDN[1] และเอกสารอ้างอิง “CSS flexible box layout”[2] ด้วย ช่วยให้เข้าใจแนวคิดเบื้องหลัง Flexbox รวมถึง properties และ shorthand properties ว่าทำงานจริงอย่างไรได้ลึกขึ้น
      [1]: https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layou...
      [2]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_flexibl...
    • Flexbox ให้ความรู้สึกเหมือนระบบกริดบน float ที่ทำออกมาอย่างถูกต้อง สามารถจัดวาง element ลูกได้ทั้งแนวตั้งหรือแนวนอน แต่ float ที่ใช้ clearfix hack นั้นในทางปฏิบัติแทบจะจัดวางได้แค่ทีละแถว
      อย่างไรก็ตาม Flexbox ก็ยังใกล้เคียงกับ เลย์เอาต์หนึ่งมิติ ที่ขึ้นบรรทัดใหม่ได้ ดังนั้นเคล็ดลับคือการซ้อนและวางทับกัน Grid มี template และให้ลูกโดยตรงครอบครองพื้นที่ที่กำหนดไว้ล่วงหน้า จึงค่อนข้าง static กว่า Flexbox และมีข้อจำกัดคือไม่ส่งผลต่อองค์ประกอบซ้อนภายใน แต่ดูเหมือนว่า subgrid จะมาเปลี่ยนส่วนนี้ได้
    • ถ้าเข้าใจ float แล้ว แค่นั้นก็ถือเป็นความสำเร็จที่พบไม่บ่อย ดังนั้นน่าจะใช้ Flex/Grid ได้อย่างสนุกทีเดียว
    • Grid มีฟีเจอร์มากมาย แต่ Flex นั้นเรียบง่ายพอและยังคงทรงพลังมาก
  • แหล่งข้อมูลที่เกี่ยวข้อง:
    Grid Garden https://cssgridgarden.com
    Flexbox Froggy https://flexboxfroggy.com

  • ถ้ามีเวอร์ชัน “ก่อนเริ่มต้น” ที่พื้นฐานยิ่งกว่าเอกสารนี้ก็คงดี ติดตั้งแต่ส่วนแนะนำจนไปต่อไม่ได้ โดยเฉพาะตรงที่ว่า “ถ้าจะจัดวางไอเท็มลูกภายใน Grid ต้องระบุหมายเลขเส้นของแต่ละไอเท็มด้วย grid-column” ตรงนี้ไม่เข้าใจว่า หมายเลขเส้น คืออะไร
    พยายามฝืนอ่านต่อโดยคิดว่าน่าจะเข้าใจจากบริบท แต่ก็มาติดอีกทันทีที่เจอนิพจน์อย่าง 1 / 3, 1 / 4

    • หมายเลขเส้นคือเส้นที่แบ่งระหว่างคอลัมน์ ถ้ามี 2 คอลัมน์ ก็จะมีเส้น 3 เส้น: ใน |a||b| เส้นสองเส้นตรงกลางจริง ๆ แล้วนับเป็นเส้นเดียว ดังนั้นรวมทั้งหมด 3 เส้น
      ดังนั้น 1/3 ไม่ใช่เศษส่วน แต่คือ ช่วงคอลัมน์ หมายถึง “เริ่มจากเส้นหมายเลข 1 และสิ้นสุดที่เส้นหมายเลข 3”
    • ถ้าเลื่อนลงไปอีกนิด จะมี live demo ให้ลองปรับเองและดูว่าเกิดอะไรขึ้น
      ชื่อ “หมายเลขเส้น” อาจไม่ค่อยดีนัก แต่จริง ๆ แล้วมันคือขอบของคอลัมน์ ดังนั้น 1/3 คือจากขอบหมายเลข 1 หรือซ้ายสุด ไปจนถึงขอบหมายเลข 3 และกินพื้นที่ครบทั้ง 2 คอลัมน์
  • สำหรับ CSS Grid ขอแนะนำ Jen Simmons Mondrian with auto flow อย่างยิ่ง ลองกด C และ D ที่ https://labs.jensimmons.com/2017/01-011.html แล้วปรับขนาดหน้าต่างดู มีวิดีโอ YouTube ให้ดูประกอบด้วย: https://www.youtube.com/watch?v=qNtJ5p3h2A4
    เจ๋งมากจริง ๆ
    สิ่งที่ยังอยากเข้าใจเกี่ยวกับ auto flow คือวิธีตรวจจับและเติมช่องว่าง เมื่อมีวัตถุขนาดต่าง ๆ กันแบบสุ่ม จะทำอย่างไรให้ auto flow ไม่เหลือช่องว่าง? หรือเราสามารถตรวจจับช่องว่างแล้วเพิ่มอะไรเข้าไปได้ไหม?

  • หวังว่านี่คงไม่ใช่คำถามโง่ ๆ แต่ทำไมถึงนิยามไวยากรณ์ด้วยสแลชแบบ 1/2, 3/4? ใช้แบบ 1-2 เพื่อหมายถึงจากคอลัมน์ 1 ถึงคอลัมน์ 2 หรือแบบ 1->2 ดูเป็นธรรมชาติกว่าไหม?

    • หมายเลขคอลัมน์อาจเป็นค่าติดลบได้ แล้วแบบไหนดีกว่ากัน: 1--1, 1->-1, 1/-1?
    • ลูกศรอาจเป็นไปได้ แต่มีเหตุผลที่ต้องมีช่องว่างทั้งสองฝั่ง ไม่ใช่ว่าจะใส่ได้แค่ตัวเลขเท่านั้น: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-column...
      ใน CSS มีการใช้ช่องว่างคั่นค่าอยู่แล้ว และถ้าคำนึงถึงสัญชาตญาณทั่วไปเวลาที่เห็นขีดกลาง แบบด้านล่างนี้ดีกว่ามาก
      grid-column: 4 somegridarea / 6;
      grid-column: span 3 / 6;
      grid-column: span somegridarea / span someothergridarea;
      ชัดเจนกว่าการเขียนแบบด้านล่างนี้มาก
      grid-column: 4 somegridarea-6;
      grid-column: span 3-6;
      grid-column: span 3->6;
      grid-column: span somegridarea-span someothergridarea;
      grid-column: span somegridarea->span someothergridarea;
  • ชอบ บทความบล็อกแบบ interactive แบบนี้มาก สำหรับ Grid ขอแนะนำอย่างยิ่งให้ลองปรับ grid area เองในเครื่องมืออย่าง https://grid.layoutit.com/
    ใช้เว็บนั้นวางแผนเลย์เอาต์ Grid มาหลายปีแล้ว ทำให้การปรับระยะห่างง่ายขึ้นมาก

  • นี่อาจเป็นครั้งแรกที่เข้าใจ CSS Grid จริง ๆ การแสดงหมายเลข ช่วยได้มาก และน่าจะกลับมาอ้างอิงบทความนี้บ่อย ๆ ต่อไป

    • ใน Firefox Developer Tools ก็สามารถแสดงหมายเลขนั้นเป็นค่าเริ่มต้นได้เหมือนกัน ส่วน Chrome ไม่แน่ใจ
  • ชอบ CSS Grid และแนวคิดเรื่องพื้นที่ แต่ยังมองว่าส่วนที่ยากที่สุดคือ การจัดการ responsive โดยเฉพาะระหว่างขนาดมือถือกับเดสก์ท็อป มักต้องอัปเดต grid-template-area และขนาดแถว/คอลัมน์ด้วย JavaScript ตามว่า UI element ไหนควรเปิดอยู่ หรือควรเป็นแบบเต็มหน้าจอ
    ยังไม่เจอโลกที่แก้ได้ด้วย minmax หรือ calc และหวังว่าจะมีใครรู้คำตอบ

    • https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_contain...
    • ในกรณีแบบนี้ วิธีที่ดีคือยังใช้ Grid เหมือนเดิม แต่ตั้งค่าแถว/คอลัมน์เป็น CSS variables อย่าง var(--foo) แทนค่าคงที่
      แบบนั้นใน JavaScript ก็แค่อัปเดตค่าตัวแปรนั้น แล้ว Grid จะนำค่านั้นไปใช้เอง
    • แปลกใจที่บทความไม่ได้เน้นว่า template areas ดีต่อ responsive แค่ไหน ถ้าใช้ media queries ก็สามารถกำหนดพื้นที่ Grid ที่ต่างกันในแต่ละหน้าจอ และย้ายแต่ละองค์ประกอบไปยังตำแหน่งที่ต้องการให้เหมาะกับขนาดหน้าจอนั้นได้ ถ้าต้องซ่อนองค์ประกอบในบางขนาด ก็ใส่ display: none ที่ขนาดนั้นได้เลย
      ตัวอย่างที่ง่ายมาก: https://codepen.io/trescenzi/pen/vYqpjvL
    • หลายกรณีแบบนั้นน่าจะแก้ได้ด้วย :has() หรือ subgrid แต่ยังไม่มีประสบการณ์ตรงมากนัก
    • เคยลองใช้ media queries หรือยัง?