2 poin oleh GN⁺ 2024-08-17 | 1 komentar | Bagikan ke WhatsApp
  • CSS Grid telah didukung luas di browser utama sejak Maret 2017, tetapi grid-template-areas masih jarang digunakan, padahal dapat merepresentasikan layout secara visual di dalam CSS tanpa menghitung nomor garis
  • grid-template-areas bekerja dengan menempatkan nama area dalam bentuk string dan menghubungkannya ke elemen anak lewat grid-area; nama yang sama harus selalu membentuk area persegi panjang
  • Named grid line adalah cara memberi nama pada garis, seperti content-start / content-end, dan pola *-start serta *-end dapat dimanfaatkan browser seperti area implisit
  • Untuk pembalikan kartu, header responsif, layout editorial, postingan bergaya Threads, kartu bertumpuk, dan layout kondisional dengan :has(), Anda dapat mengelola variasi penempatan hanya dengan mengubah string area pada elemen induk
  • Chrome, Safari, dan Firefox semuanya menyediakan DevTools untuk area Grid; Firefox sangat berguna karena menampilkan nama area dan memberi pelengkapan otomatis nama garis yang tersedia saat mengedit grid-area

Membuat layout lebih mudah dibaca dengan grid-template-areas

  • Pada CSS Grid tradisional, penempatan sering dilakukan dengan menentukan nomor garis secara langsung seperti grid-column: 1 / 3
  • Nomor garis tidak terlihat sampai diperiksa di DevTools, dan pada layout yang memiliki kolom sekaligus baris, sulit menghitung nomor yang benar di dalam kepala
  • grid-template-areas menamai setiap sel untuk penempatan, sehingga kode CSS itu sendiri tampak seperti peta layout
.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;
}
  • Elemen anak dipetakan ke area bernama melalui grid-area
  • Dalam contoh kartu, dengan mendefinisikan "featured featured article", area featured dapat menempati 2 kolom dan area article 1 kolom

Sintaks dan aturan yang wajib dipatuhi

  • grid-template-areas menerima satu atau lebih string area
    • Satu string membuat layout satu dimensi yang hanya memiliki kolom
    • Beberapa string membentuk layout multidimensi dengan baris dan kolom
  • Saat menggunakan beberapa string, menuliskannya di baris terpisah membuat layout lebih mudah dibaca
.element {
  display: grid;
  grid-template-columns: 200px 1fr;
  grid-template-areas:
    "aside main"
    "footer footer";
}
  • Setiap string merepresentasikan satu baris grid dan bisa dibayangkan seperti tabel
  • Area yang didefinisikan dengan nama yang sama harus berbentuk persegi panjang di dalam kode
/* invalid */
.layout {
  grid-template-areas:
    "header header"
    "sidebar main"
    "header footer";
}

/* valid */
.layout {
  grid-template-areas:
    "header header"
    "sidebar main"
    "sidebar footer";
}
  • Semua baris harus memiliki jumlah token area yang sama, dan meskipun suatu area tidak digunakan, selnya tetap harus didefinisikan
  • Sel kosong dapat ditulis dengan satu titik atau beberapa titik
.element {
  grid-template-areas:
    "aside main"
    "... footer";
}
  • Titik adalah null cell token dalam spesifikasi CSS Grid, yang menandakan sel grid kosong

Hubungan antara named grid line dan area

  • Dalam CSS Grid, jumlah garis selalu satu lebih banyak daripada jumlah kolom
    • Jika ada 3 kolom, akan ada 4 garis grid
  • Named grid line adalah cara memberi nama unik pada garis alih-alih hanya memakai angka bawaan
.layout {
  grid-template-columns:
    [full-start] 1fr
    [content-start] 2fr
    [content-end] 1fr [full-end];
}

.item {
  grid-column: content-start / content-end;
}
  • Meski garis diberi nama, garis bernomor tetap bisa digunakan
  • Ukuran track (track size) berarti ukuran kolom atau baris, dan nilai seperti 1fr 1fr adalah ukuran track
  • Pada named line, yang dinamai adalah garis di sekitar track
.layout {
  display: grid;
  grid-template-columns:
    [aside-start] 200px [aside-end main-start] 1fr [main-end];
}
  • Satu garis dapat memiliki beberapa nama; pada contoh di atas, aside-end dan main-start adalah garis yang sama
  • Jika Anda mendefinisikan nama *-start / *-end seperti aside-start dan aside-end, browser dapat mengizinkan penggunaan seperti grid-column: aside melalui nama garis implisit
  • Tidak semua garis harus diberi nama; Anda dapat menamai hanya garis yang penting
  • Saat menempatkan elemen, angka dan nama bisa dicampur seperti grid-column: 1 / content-end

Mengelola variasi penempatan dari string area elemen induk

  • Dengan grid-template-areas, Anda bisa mengubah seluruh layout hanya dengan mengganti string area pada elemen induk, sementara nama grid-area pada elemen anak tetap sama
.aside {
  grid-area: aside;
}

.main {
  grid-area: main;
}

.footer {
  grid-area: footer;
}
  • Dengan mempertahankan nama aside, main, dan footer, lalu hanya mengubah string grid-template-areas, seluruh penempatan akan diperbarui secara otomatis
  • Kontrol layout menjadi terpusat pada definisi area milik elemen induk sehingga lebih mudah disesuaikan

Membalik arah kartu

  • Di Flexbox, arah kartu dapat dibalik dengan mudah menggunakan flex-direction: row-reverse
  • Di CSS Grid, jika memakai nomor garis, mengubah arah berarti harus mengubah definisi kolom dan nilai grid-column setiap elemen anak
  • Dengan area bernama, cukup tetapkan gambar dan konten kartu ke area masing-masing, lalu ubah urutan area pada elemen induk
.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";
}
  • Layout yang sama juga dapat ditulis dengan properti singkat grid-template
.card--flip {
  grid-template: "content image" / 1fr 150px;
}
  • Properti singkat ini opsional; ada juga yang menganggap properti lengkap lebih mudah dibaca

Layout header responsif

  • Header dengan area logo, navigasi, dan aksi dapat dimulai dengan 3 kolom berukuran sama
  • Jika memakai nomor garis, Anda perlu menentukan grid-column untuk .logo, .nav, dan .actions satu per satu
  • Dengan nama area, cukup petakan tiap elemen anak ke logo, nav, dan actions, lalu ubah hanya grid-template-areas pada elemen induk untuk tiap 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;
}
  • Pada ukuran kecil, logo dan aksi bisa ditempatkan di baris pertama, sementara navigasi mengambil seluruh lebar di bawahnya
.header {
  grid-template-areas:
    "logo logo actions"
    "nav nav nav";
}
  • Pada 380px ke atas, logo dapat diletakkan di kiri dan navigasi serta aksi di kanan
@media (min-width: 380px) {
  .header {
    grid-template-areas:
      "logo nav nav"
      "logo actions actions";
  }

  .nav {
    justify-self: end;
  }
}
  • Pada 900px ke atas, layout bisa kembali menjadi satu baris
@media (min-width: 900px) {
  .header {
    grid-template-areas: "logo nav actions";
  }
}
  • String area berfungsi seperti pemetaan yang langsung memperlihatkan susunan UI di dalam CSS

Contoh layout editorial

  • Bagian yang berisi judul, teks, dan gambar dapat dengan mudah diubah penempatannya untuk berbagai ukuran viewport menggunakan grid-template-areas
.section {
  display: grid;
  grid-template-areas:
    ". title title"
    "thumb content content";
  gap: 1rem;
}
  • Titik di sebelah kiri judul adalah null cell token yang menandakan ruang kosong
  • Pada contoh bagian bergaya time.com, area feature, secondary, most-read, serta kolom kosong di kedua sisi digunakan bersama
.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;
}
  • Kolom kosong di kiri dan kanan terutama berfungsi sebagai jarak horizontal
  • Pada versi responsif, feature, secondary, dan most-read ditumpuk vertikal di layar kecil, lalu definisi kolom dan area diubah lagi pada 500px dan 900px ke atas
  • grid-template-rows dapat digantikan oleh definisi area, jadi tidak selalu diperlukan

Komponen postingan bergaya Threads

  • Saat meninjau CSS dari Threads app by Meta, kita bisa melihat contoh penggunaan CSS Grid pada komponen postingan
  • Contoh aslinya menempatkan item menggunakan grid-template-columns, grid-template-rows, dan nomor garis
.postBody {
  grid-column-start: 2;
  grid-row-start: 2;
  grid-row-end: span 3;
}
  • Beberapa variasi postingan dapat diekspresikan lebih mudah dengan 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";
}
  • Variasi postingan default, balasan, dan nested dapat dibedakan hanya dengan melihat string areanya

Item bertumpuk dan nama area

  • Dalam grid-template-areas, nama yang sama harus berbentuk persegi panjang, jadi mengulang nama yang sama dalam bentuk non-persegi panjang tidak valid
.layout {
  display: grid;
  grid-template-columns: 1fr 1fr fr;
  grid-template-areas:
    "card tag tag"
    "title title card";
}
  • Contoh di atas invalid karena card tidak membentuk persegi panjang
  • Pada kartu bertumpuk, Anda dapat mendefinisikan nama area baru seperti thumb-1 dan thumb-2, lalu menggunakannya di grid-column dan 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 dan judul masing-masing dapat ditempatkan dengan grid-area, lalu disejajarkan menggunakan align-self dan justify-self
  • Jika perlu, Anda harus mengatur urutan tumpukan elemen anak, tetapi pada contoh ini urutan sumber saja sudah cukup
  • Contoh tumpang tindih ini terinspirasi dari halaman Oddbird’s Cascading Layouts

:has() dan layout kondisional

  • Dengan menggabungkan selektor CSS :has() dan area Grid, Anda dapat mengubah layout berdasarkan ada atau tidaknya elemen tertentu
  • Definisi area yang berbeda dapat diterapkan pada <figure> ketika di dalamnya ada figcaption dan ketika tidak ada
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 .";
}

Dukungan arah multibahasa LTR/RTL

  • CSS Grid menyesuaikan layout berdasarkan apakah arah halaman adalah LTR atau RTL
  • Named grid area juga mengikuti arah halaman, sehingga layout akan terbalik dalam pengaturan RTL
  • Untuk penulisan layout RTL, Anda dapat melihat panduan RTL Styling 101

Perbedaan dukungan DevTools

  • Chrome, Safari, dan Firefox semuanya menyediakan DevTools untuk area Grid
  • Chrome
    • Menempatkan nama area di kiri atas sehingga area bisa tampak saling menumpuk
    • Overlay warna dapat mengubah cara desain terlihat
  • Safari
    • Outline merah muda membantu membedakan item dengan jelas
    • Dapat menampilkan nama garis
    • Cara menampilkan nama garis masih bisa ditingkatkan, misalnya dengan menumpuk tampilannya per baris
  • Firefox
    • Nama area terlihat lebih jelas dibanding Chrome dan Safari
    • Menyediakan daftar pelengkapan otomatis saat memasukkan nama kustom seperti *-start dan *-end
    • Saat mengedit grid-area pada item anak, Firefox menampilkan daftar semua nama garis yang tersedia

Referensi

1 komentar

 
GN⁺ 2024-08-17
Opini Hacker News
  • Demo animasinya cukup menarik, tetapi ternyata animasi itu bukan dibuat dengan CSS, jadi agak mengecewakan
    Setelah belajar Flexbox, saya merasa “ini sudah cukup”, dan tidak mempelajari Grid secara mendalam. Sepertinya ada alasan untuk lebih memilih Grid [0], tetapi secara umum saya belum pernah membutuhkan pekerjaan yang hanya bisa dilakukan dengan Grid, dan untuk tabel data saya menggunakan <table> sungguhan
    [0] https://css-tricks.com/css-grid-replace-flexbox/

    • Bagus kalau sudah mempelajari alat yang mencakup semua kebutuhan
      Grid hanya pernah saya pakai untuk galeri gambar responsif seperti https://labs.jensimmons.com/2016/examples/image-gallery-grid... atau kartu responsif seperti https://every-layout.dev/demos/grid-cards/. grid-template-columns layak dipelajari dan grid-gap praktis. Di luar itu, rasanya Flexbox menangani hampir semuanya
      Namun grid-template-areas masih terasa agak ambigu. Artikel itu memberi alasan seperti penyesuaian layout per breakpoint atau kemudahan “saat anggota tim harus mengubah layout”, tetapi mungkin memang saya bukan pembaca sasarannya
    • Alat menarik untuk belajar Grid: https://cssgridgarden.com/
    • Flex cukup untuk sebagian besar kasus, tetapi Grid juga punya tempatnya. Misalnya layout kartu 3 kolom yang menyusut menjadi satu kartu per baris di layar kecil, struktur halaman dengan sidebar khusus, atau elemen yang harus mempertahankan penempatan tertentu saat ukurannya diubah
      Gunakan keduanya sesuai kebutuhan; jika digabungkan, keduanya menjadi alat layout yang sangat kuat
    • “Tidak, Flexbox tidak ‘cukup baik’”
      https://www.youtube.com/watch?v=MWWcZzossc8
  • Tunggu, 1/3 itu bukan pecahan, melainkan rentang dari 1 sampai 3? Saya tidak mengerti mengapa memilih sintaks seperti itu. Dalam pemrograman ada banyak sintaks yang masuk akal dan sudah dikenal untuk menyatakan rentang, misalnya 1..3

    • Hal pertama yang perlu diketahui tentang CSS adalah bahwa CSS memakai bahasa layout cetak, bukan ekspresi bahasa pemrograman
      Banyak masalah yang dialami programmer dengan CSS tampaknya berawal dari kesalahpahaman ini
    • Fitur Grid bagus, tetapi sintaksnya cukup berbeda dari CSS lain sehingga membingungkan. Rasanya seperti bagian sudut ini dibuat terpisah, atau ada jejak pendekatan “kali ini kita lakukan dengan benar”
    • Di kedua sisi slash tidak hanya bisa ada angka, tetapi juga beberapa kata: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-column...
    • Bayangkan memberi tahu programmer bahwa di CSS, !important bukan berarti “tidak penting”, melainkan “penting!”
  • Saya belum benar-benar menguasai Grid maupun Flexbox. Strategi layout terakhir yang setidaknya cukup saya kuasai adalah float. Setelah membaca artikel ini, saya jadi lebih percaya diri untuk mencoba CSS Grid saat merancang layout berikutnya, dan artikelnya juga dibuat dengan baik

    • Kalau pernah menangani float, Grid dan Flex akan jauh lebih mudah. Luangkan satu atau dua hari untuk membuat beberapa layout. Berbeda dengan bergulat dengan browser lama, keduanya berjalan begitu saja, bahkan sebenarnya agak membosankan
      Ada banyak artikel bagus, tetapi dua artikel CSS-Tricks ini saja sudah cukup bagi saya
      https://css-tricks.com/snippets/css/a-guide-to-flexbox/
      https://css-tricks.com/snippets/css/complete-guide-grid/
    • Tanpa belajar Grid pun masih bisa bertahan sampai batas tertentu, tetapi Flexbox hampir wajib. Karena jauh lebih nyaman daripada hack float lama dan menjadi dasar di banyak bagian CSS modern
      Selain artikel CSS-Tricks yang sudah disebutkan, saya juga merekomendasikan panduan Flexbox MDN[1] dan referensi “CSS flexible box layout”[2]. Keduanya membantu memahami lebih dalam konsep di balik Flexbox serta bagaimana properti dan shorthand-nya benar-benar bekerja
      [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 terasa seperti versi yang benar dari sistem grid berbasis float. Elemen anak bisa ditempatkan secara vertikal maupun horizontal, tetapi float yang memakai hack clearfix pada dasarnya hanya bisa melakukan penempatan per baris
      Namun Flexbox juga lebih mirip layout satu dimensi yang bisa membungkus baris, sehingga triknya adalah menumpuk dan menyarangkannya. Grid memiliki template dan anak langsung menempati area yang sudah ditentukan sebelumnya, sehingga lebih statis daripada Flexbox, dengan keterbatasan tidak memengaruhi elemen bersarang di dalamnya. Meski begitu, subgrid tampaknya akan mengubah bagian itu
    • Jika Anda memahami float, itu saja sudah pencapaian yang jarang, jadi Flex/Grid kemungkinan akan cukup menyenangkan untuk digunakan
    • Grid punya banyak fitur, tetapi Flex cukup sederhana sekaligus tetap sangat kuat
  • Materi terkait:
    Grid Garden https://cssgridgarden.com
    Flexbox Froggy https://flexboxfroggy.com

  • Akan bagus kalau ada versi yang lebih mendasar lagi daripada dokumen ini, semacam versi “sebelum pengantar”. Saya sudah mentok sejak bagian pengantar dan tidak bisa lanjut. Terutama pada bagian “Untuk menempatkan item anak di dalam Grid, Anda harus menentukan nomor garis tiap item dengan grid-column”, saya tidak paham apa yang dimaksud nomor garis di sini
    Saya coba terus karena mungkin bisa dipahami dari konteks, tapi langsung mentok lagi pada ekspresi seperti 1 / 3, 1 / 4

    • Nomor garis adalah garis yang membagi antar kolom. Jika ada 2 kolom, ada 3 garis: pada |a||b|, dua garis di tengah sebenarnya dihitung sebagai satu, jadi totalnya 3
      Jadi 1/3 bukan pecahan, melainkan rentang kolom, yang berarti “mulai dari garis nomor 1 dan berakhir di garis nomor 3”
    • Kalau menggulir sedikit ke bawah, ada demo langsung yang bisa Anda utak-atik untuk melihat apa yang terjadi
      Nama “nomor garis” memang kurang bagus, tetapi sebenarnya itu adalah tepi kolom. Jadi 1/3 berjalan dari tepi nomor 1, yaitu paling kiri, hingga tepi nomor 3, dan menempati seluruh 2 kolom
  • Untuk CSS Grid, saya sangat merekomendasikan Jen Simmons Mondrian with auto flow. Coba tekan C dan D di https://labs.jensimmons.com/2017/01-011.html, lalu ubah ukuran jendelanya. Ada juga video YouTube untuk ditonton bersama: https://www.youtube.com/watch?v=qNtJ5p3h2A4
    Benar-benar keren
    Yang masih ingin saya pahami dari auto flow adalah cara mendeteksi dan mengisi ruang kosong. Ketika ada objek dengan ukuran acak yang berbeda-beda, bagaimana agar auto flow tidak meninggalkan ruang kosong? Atau bisakah kita mendeteksi ruang kosong lalu menambahkan sesuatu?

  • Semoga ini bukan pertanyaan bodoh, tapi kenapa sintaksnya didefinisikan dengan garis miring seperti 1/2, 3/4? Bukankah bentuk seperti 1-2, dari kolom 1 sampai kolom 2, atau semacam 1->2 terasa lebih natural?

    • Nomor kolom bisa bernilai negatif. Kalau begitu, mana yang lebih baik: 1--1, 1->-1, atau 1/-1?
    • Panah mungkin saja bisa, tetapi ada alasan mengapa ada spasi di kedua sisi. Nilainya tidak selalu hanya angka: https://developer.mozilla.org/en-US/docs/Web/CSS/grid-column...
      Di CSS, nilai sudah dipisahkan dengan spasi, dan jika mempertimbangkan intuisi umum kita saat melihat tanda hubung, bentuk di bawah ini jauh lebih baik
      grid-column: 4 somegridarea / 6;
      grid-column: span 3 / 6;
      grid-column: span somegridarea / span someothergridarea;
      Jauh lebih jelas daripada menulis seperti ini
      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;
  • Saya sangat menyukai tulisan blog interaktif seperti ini. Untuk Grid, saya sangat menyarankan mencoba langsung grid area di alat seperti https://grid.layoutit.com/
    Saya sudah bertahun-tahun memakai situs itu untuk merancang layout Grid, dan penyesuaian jarak menjadi jauh lebih mudah

  • Mungkin ini pertama kalinya saya benar-benar memahami CSS Grid. Penomoran sangat membantu, dan tulisan ini akan sering saya jadikan referensi ke depannya

    • Di Firefox Developer Tools juga nomor itu bisa ditampilkan secara default. Untuk Chrome saya kurang yakin
  • Saya suka CSS Grid dan konsep area, tetapi menurut saya bagian tersulit tetap mengelola responsivitas, terutama antara ukuran mobile dan desktop. Bergantung pada elemen UI mana yang harus terbuka atau harus layar penuh, sering kali grid-template-area serta ukuran baris/kolom perlu diperbarui dengan JavaScript
    Saya belum menemukan dunia yang bisa menyelesaikannya dengan minmax atau calc, dan semoga ada yang tahu jawabannya

    • https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_contain...
    • Untuk kasus seperti ini, sebaiknya tetap gunakan Grid, tetapi jadikan nilai baris/kolom sebagai CSS variable seperti var(--foo) alih-alih nilai tetap
      Dengan begitu, JavaScript cukup memperbarui nilai variabel tersebut, dan Grid akan mencerminkannya
    • Saya agak heran tulisan ini tidak menekankan seberapa bagus template area untuk responsivitas. Dengan media query, Anda bisa mendefinisikan area Grid yang berbeda untuk tiap ukuran layar, lalu memindahkan setiap elemen ke posisi yang diinginkan sesuai ukuran layar tersebut. Jika sebuah elemen perlu disembunyikan pada ukuran tertentu, beri display: none pada ukuran itu
      Contoh yang sangat sederhana: https://codepen.io/trescenzi/pen/vYqpjvL
    • Saya rasa banyak kasus seperti itu bisa diselesaikan dengan :has() atau subgrid, tetapi saya belum punya banyak pengalaman langsung
    • Sudah mencoba media query?