Grid heksagonal responsif menggunakan CSS modern – Beragampengetahuan
Lima tahun lalu, saya menerbitkan artikel tentang cara membuat grid heksagonal responsif. Ini adalah satu-satunya teknik yang tidak memerlukan kueri media atau JavaScript. Ia bekerja dengan sejumlah proyek, memungkinkan Anda mengontrol ukuran dan kesenjangan dengan mudah menggunakan variabel CSS.
saya menggunakan float, inline-blocklingkungan font-size setara 0dll. Di tahun 2026, ini mungkin terdengar agak kuno dan ketinggalan jaman. Hal ini tidak terjadi karena pendekatan ini berfungsi dengan baik dan didukung dengan baik, namun dapatkah kita melakukan yang lebih baik dengan menggunakan fitur-fitur modern? Banyak hal telah berubah dalam lima tahun dan kita dapat meningkatkan implementasi di atas dan membuatnya tidak terlalu rumit!
Chrome hanya didukung karena teknologi ini menggunakan fitur-fitur yang baru dirilis termasuk corner-shape, sibling-index()dan pembagian satuan.
Kode CSS lebih pendek dan berisi lebih sedikit angka ajaib dibandingkan saat terakhir saya menangani masalah ini. Anda juga akan menemukan beberapa perhitungan rumit yang akan kita bedah bersama.
Sebelum mendalami demo baru ini, saya sangat menyarankan Anda membaca artikel saya sebelumnya. Hal ini tidak wajib, namun memungkinkan Anda membandingkan kedua pendekatan tersebut dan melihat seberapa jauh (dan seberapa cepat) CSS telah berkembang selama lima tahun terakhir dengan diperkenalkannya fitur-fitur baru yang membuat hal-hal sulit seperti ini menjadi lebih mudah.
Contents
segi enam
Mari kita mulai dengan segi enam, yang merupakan elemen utama grid. Sebelumnya, saya harus mengandalkan clip-path: polygon() Buat itu:
.hexagon {
--s: 100px;
width: var(--s);
height: calc(var(--s) * 1.1547);
clip-path: polygon(0% 25%, 0% 75%, 50% 100%, 100% 75%, 100% 25%, 50% 0%);
}
Tapi sekarang, kita bisa mengandalkan hal baru corner-shape Dan border-radius milik:
.hexagon {
width: 100px;
aspect-ratio: cos(30deg);
border-radius: 50% / 25%;
corner-shape: bevel;
}
Ini lebih mudah daripada yang biasa kita lakukan untuk membuat elemen miring, dan sebagai bonus, kita dapat menambahkan batas pada bentuk tanpa ada solusi lain!
ini corner-shape Properti adalah fitur modern pertama yang menjadi sandaran kita. Itu membuat menggambar bentuk CSS lebih mudah daripada metode tradisional, seperti menggunakan clip-path. Anda masih dapat terus menggunakan clip-path pendekatan, tentu saja, untuk dukungan yang lebih baik (jika Anda tidak memerlukan batas pada elemen), tetapi inilah implementasi yang lebih modern:
.hexagon {
width: 100px;
aspect-ratio: cos(30deg);
clip-path: polygon(-50% 50%,50% 100%,150% 50%,50% 0);
}
Ada lebih sedikit titik di dalam poligon, kita ganti angka ajaibnya 1.1547 dengan a aspect-ratio pernyataan. Saya tidak akan menghabiskan lebih banyak waktu pada kode bentuk, tetapi jika Anda ingin penjelasan detail dengan lebih banyak contoh, berikut dua artikel yang saya tulis:
jaringan responsif
Sekarang kita sudah punya bentuknya, mari buat gridnya. Ini disebut “grid” tapi saya akan menggunakan konfigurasi flexbox:
<div class="container">
<div></div>
<div></div>
<div></div>
<div></div>
<!-- etc. -->
</div>
.container {
--s: 120px; /* size */
--g: 10px; /* gap */
display: flex;
gap: var(--g);
flex-wrap: wrap;
}
.container > * {
width: var(--s);
aspect-ratio: cos(30deg);
border-radius: 50% / 25%;
corner-shape: bevel;
}
Tidak ada yang istimewa sejauh ini. Dari sana, kami menambahkan margin bawah ke semua item untuk membuat tumpang tindih antar baris:
.container > * {
margin-bottom: calc(var(--s)/(-4*cos(30deg)));
}
Langkah terakhir adalah menambahkan margin kiri pada item pertama dari baris bernomor genap (yaitu baris kedua, keempat, keenam, dan seterusnya). Margin ini akan menciptakan offset antar baris untuk mencapai grid yang sempurna.
Begini, kedengarannya sederhana, tetapi ini adalah bagian tersulit dan memerlukan perhitungan yang rumit. Gridnya responsif, jadi item “pertama” yang kita cari bisa berupa item apa saja, tergantung ukuran container, ukuran item, gap, dll.
Mari kita mulai dengan sebuah gambar:

Tergantung pada daya tanggapnya, grid kita dapat memiliki dua sisi. Kita dapat memiliki jumlah item yang sama di semua baris (Kisi 1 pada gambar di atas), atau kita dapat memiliki selisih satu item di antara dua baris berturut-turut (Kisi 2). ini N Dan M Variabel mewakili jumlah item dalam baris. Di grid 1 kita punya N = Mdi grid 2 kita punya M = N - 1.
Di Grid 1, item margin kiri adalah 6, 16, 26, dst., dan di Grid 2, item margin kiri adalah 7, 18, 29, dst. Mari kita coba mengidentifikasi logika di balik angka-angka ini.
Item pertama di kedua grid (6 atau 7) adalah item pertama di baris kedua, jadi item tersebut N + 1. Item kedua (16 atau 18) adalah item pertama pada baris ketiga, jadi item tersebut N + M + N + 1. Item ketiga (26 atau 29) adalah item N + M + N + M + N + 1. Jika diperhatikan lebih dekat, Anda dapat melihat pola yang dapat kita ekspresikan dengan menggunakan rumus berikut:
N*i + M*(i - 1) + 1
…Di mana i adalah bilangan bulat positif (tidak termasuk nol). Item yang kita cari dapat ditemukan dengan menggunakan pseudocode berikut:
for(i = 0; i< ?? ;i++) {
index = N*i + M*(i - 1) + 1
Add margin to items[index]
}
Namun, kami tidak memiliki loop di CSS, jadi kami harus melakukan sesuatu yang berbeda. Kita bisa mendapatkan indeks setiap item menggunakan metode baru sibling-index() Fungsi. Logikanya adalah untuk menguji apakah indeks cocok dengan rumus sebelumnya.
Daripada menulis:
index = N*i + M*(i - 1) + 1
…mari kita berekspresi i Gunakan indeks:
i = (index - 1 + M)/(N + M)
kita tahu i adalah bilangan bulat positif (tidak termasuk nol), jadi untuk setiap item kita mendapatkan indeksnya dan menguji apakah (index - 1 + M)/(N + M) adalah bilangan bulat positif. Sebelum itu mari kita hitung dulu jumlah itemnya. N Dan M.
Menghitung jumlah item pada setiap baris sama dengan menghitung berapa banyak item yang dapat ditampung dalam baris tersebut.
N = round(down,container_size / item_size);
Bagilah ukuran wadah dengan ukuran barang untuk mendapatkan nomor. jika kita round()`Membulatkannya ke bilangan bulat terdekat, kita mendapatkan jumlah item per baris. Namun terdapat kesenjangan antar proyek, jadi kita perlu memperhitungkannya dalam rumus:
N = round(down, (container_size + gap)/ (item_size + gap));
kita melakukan hal yang sama Mtapi kali ini kita juga perlu mempertimbangkan margin kiri yang diterapkan pada item pertama di baris:
M = round(down, (container_size + gap - margin_left)/ (item_size + gap));
Mari kita lihat lebih dekat dan tentukan nilai margin ini pada gambar di bawah ini:

Ini sama dengan setengah ukuran benda, ditambah setengah jaraknya:
M = round(down, (container_size + gap - (item_size + gap)/2)/(item_size + gap));
M = round(down, (container_size - (item_size - gap)/2)/(item_size + gap));
Dimensi dan jarak bebas item menggunakan definisi berikut --s Dan --g variabel, tapi bagaimana dengan ukuran wadahnya? Kita dapat mengandalkan unit kueri kontainer dan menggunakannya 100cqw.
Mari kita tulis apa yang kita miliki sejauh ini menggunakan CSS:
.container {
--s: 120px; /* size */
--g: 10px; /* gap */
container-type: inline-size; /* we make it a container to use 100cqw */
}
.container > * {
--_n: round(down,(100cqw + var(--g))/(var(--s) + var(--g)));
--_m: round(down,(100cqw - (var(--s) - var(--g))/2)/(var(--s) + var(--g)));
--_i: calc((sibling-index() - 1 + var(--_m))/(var(--_n) + var(--_m)));
margin-left: ???; /* We're getting there! */
}
bisa kita gunakan mod(var(--_i),1) Uji apakah --_i adalah bilangan bulat. Jika bilangan bulat, hasilnya sama dengan 0. Jika tidak, hasilnya sama dengan nilai antara 0 dan 1.
Kita dapat memperkenalkan variabel lain dan menggunakan variabel baru if() Fungsi!
.container {
--s: 120px; /* size */
--g: 10px; /* gap */
container-type: inline-size; /* we make it a container to use 100cqw */
}
.container > * {
--_n: round(down,(100cqw + var(--g))/(var(--s) + var(--g)));
--_m: round(down,(100cqw - (var(--s) - var(--g))/2)/(var(--s) + var(--g)));
--_i: calc((sibling-index() - 1 + var(--_m))/(var(--_n) + var(--_m)));
--_c: mod(var(--_i),1);
margin-left: if(style(--_c: 0) calc((var(--s) + var(--g))/2) else 0;);
}
Tiantian!
Perhatikan bahwa Anda perlu mendaftarkan variabel ini --_c Penggunaan variabel @property untuk dapat membandingkan (saya sebutkan di “Cara menggunakan yang benar if()dalam CSS”).
Ini adalah kasus penggunaan yang bagus if()namun kita dapat melakukannya secara berbeda:
--_c: round(down, 1 - mod(var(--_i), 1));
ini mod() Fungsi tersebut memberi kita nilai antara 0 dan 1, dimana 0 adalah nilai yang kita inginkan. -1*mod() Beri kami nilai antara -1 dan 0. 1 - mod() Beri kami nilai antara 0 dan 1, tapi kali ini 1 yang kami perlukan. Kami melamar round() Perhitungan dilakukan dan hasilnya adalah 0 atau 1. --_c Variabel tersebut sekarang menjadi variabel boolean dan kita dapat menggunakannya secara langsung dalam perhitungan kita.
margin-left: calc(var(--_c) * (var(--s) + var(--g))/2);
jika --_c Sama dengan 1, kita mendapat margin. Jika tidak, marginnya sama dengan 0. Kali ini Anda tidak perlu mendaftarkan variabel menggunakan @property. Saya pribadi lebih suka pendekatan ini karena memerlukan lebih sedikit kode, namun if() Caranya juga menarik.
Haruskah saya mengingat semua rumus ini? Itu keterlaluan!
Tidak, kamu tidak melakukannya. Saya sudah mencoba memberikan penjelasan rinci di balik matematika, tapi tidak perlu memahaminya untuk menggunakan grid. Yang harus Anda lakukan adalah memperbarui variabel yang mengontrol dimensi dan kesenjangan. Tidak perlu menyentuh bagian yang mengatur margin kiri. Kita bahkan akan mempelajari cara kerja struktur kode yang sama dengan lebih banyak bentuk!
Lebih banyak contoh
Kasus penggunaan yang umum adalah segi enam, tetapi bagaimana dengan bentuk lainnya? Misalnya, kita dapat melihat belah ketupat, dan untuk melakukan ini kita hanya perlu menyesuaikan kode yang mengontrol bentuknya.
dengan demikian:
.container > * {
aspect-ratio: cos(30deg);
border-radius: 50% / 25%;
corner-shape: bevel;
margin-bottom: calc(var(--s)/(-4*cos(30deg)));
}
…untuk ini:
.container > * {
aspect-ratio: 1;
border-radius: 50%;
corner-shape: bevel;
margin-bottom: calc(var(--s)/-2);
}
Diamond Grid Responsif – Mudah! Mari kita coba dengan segi delapan:
.container > * {
aspect-ratio: 1;
border-radius: calc(100%/(2 + sqrt(2)));
corner-shape: bevel;
margin-bottom: calc(var(--s)/(-1*(2 + sqrt(2))));
}
hampir! Untuk segi delapan, kita perlu menyesuaikan gap Karena kita memerlukan lebih banyak ruang horizontal antar item:
.container {
--g: calc(10px + var(--s)/(sqrt(2) + 1));
gap: 10px var(--g);
}
variabel --g termasuk bagian dari ukuran var(--s)/(sqrt(2) + 1) dan digunakan sebagai spasi baris, sedangkan spasi kolom tetap tidak berubah (10px).
Dari sana, kita juga bisa mendapatkan jenis jaring heksagonal lainnya:
Mengapa tidak menggunakan grid melingkar juga? Ini dia:
Seperti yang Anda lihat, kami belum menyentuh perhitungan rumit dalam mengatur margin kiri dalam contoh berikut. Yang harus kita lakukan hanyalah dan border-radius Dan aspect-ratio Properti untuk mengontrol bentuk dan menyesuaikan margin bawah untuk memperbaiki tumpang tindih. Dalam beberapa kasus kita perlu menyesuaikan kesenjangan horizontal.
sebagai kesimpulan
Saya akan mengakhiri artikel ini dengan demonstrasi lain sebagai pekerjaan rumah kecil untuk Anda:
Kali ini, pergeseran diterapkan pada baris ganjil, bukan baris genap. Saya akan membiarkan Anda membedah kodenya sebagai latihan kecil. Mencoba mengidentifikasi perubahan yang saya buat dan apa logika di baliknya (petunjuk: Coba ulangi langkah perhitungan dengan konfigurasi baru ini. )
rencana pengembangan website
metode pengembangan website
jelaskan beberapa rencana untuk pengembangan website, proses pengembangan website, kekuatan dan kelemahan bisnis pengembangan website
, jasa pengembangan website, tahap pengembangan website, biaya pengembangan website
#Grid #heksagonal #responsif #menggunakan #CSS #modern