Pada bulan Mei, saya mengetahui bahawa Firefox menambah fungsi susun atur batu dalam grid CSS. Susun atur Masonry adalah sesuatu yang saya selalu mahu melaksanakan dari awal, tetapi saya tidak pernah tahu di mana untuk bermula. Oleh itu, saya secara semula jadi melihat demo dan kemudian saya mempunyai inspirasi apabila saya memahami bagaimana ciri CSS baru ini berfungsi.
Pada masa ini, sokongan adalah terhad kepada Firefox (dan, walaupun di sana, hanya jika bendera tertentu diaktifkan), tetapi ini masih memberi saya titik permulaan untuk pelaksanaan JavaScript yang dapat meliputi penyemak imbas yang kini tidak mempunyai sokongan.
Firefox melaksanakan susun atur batu dalam CSS dengan menetapkan grid-template-rows
(seperti yang ditunjukkan dalam contoh) atau grid-template-columns
kepada nilai masonry
.
Pendekatan saya adalah untuk memanfaatkan ciri ini untuk menyokong penyemak imbas (sekali lagi, ia hanya merujuk kepada Firefox buat masa ini) dan membuat skema sandaran JavaScript untuk penyemak imbas yang lain. Mari kita lihat bagaimana untuk mencapai ini menggunakan kes tertentu grid imej.
Pertama, aktifkan bendera
Untuk melakukan ini, kami melawat about:config
di Firefox dan cari "Masonry". Ini true
memaparkan layout.css.grid-template-masonry-value.enabled
false
Mari mulakan dengan beberapa markup
Struktur HTML adalah seperti berikut:
<img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/174364597525146.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="Penyelesaian batu ringan">
Sekarang, mari kita gunakan beberapa gaya
Pertama, kami menetapkan elemen peringkat teratas sebagai bekas grid CSS. Seterusnya, kami menentukan lebar maksimum untuk imej, contohnya 10em
. Kami juga mahu imej -imej ini menyusut ke mana -mana ruang yang tersedia untuk kotak kandungan grid, dan jika viewport menjadi terlalu sempit untuk menampung satu grid lajur 10em
, nilai sebenarnya ditetapkan adalah Min(10em, 100%)
. Oleh kerana reka bentuk responsif sangat penting pada masa kini, bukannya menggunakan bilangan lajur tetap, kami secara automatik menyesuaikan diri dengan banyak lajur lebar ini yang mungkin:
$ w: min (10em, 100%); .Grid-Masonry { paparan: grid; Grid-template-lajur: Ulang (Auto-Fit, $ W); > * {width: $ w; } }
Perhatikan bahawa kami menggunakan Min()
bukan min()
untuk mengelakkan konflik SASS.
Ok, ini grid!
Ia bukan grid yang sangat bagus, jadi mari kita memaksa kandungannya berpusat secara mendatar dan kemudian tambah jurang grid dan mengisi, sama dengan nilai jarak ( $s
). Kami juga menyediakan latar belakang untuk melihat lebih mudah.
$ s: .5em; /* Gaya grid batu*/ .Grid-Masonry { /* Sama seperti gaya sebelumnya*/ Justify-Content: Center; Grid-Gap: $ s; Padding: $ s; } /* Gaya pengindahan*/ html {latar belakang: #555; }
Selepas sedikit pengindahan grid, kami berpaling untuk melakukan perkara yang sama untuk projek grid (iaitu, imej). Mari gunakan penapis untuk menjadikannya kelihatan lebih seragam sambil menambah beberapa gaya tambahan dengan sudut dan bayang -bayang yang sedikit bulat.
img { Radius sempadan: 4px; box-shadow: 2px 2px 5px rgba (#000, .7); Penapis: Sepia (1); }
Sekarang, untuk penyemak imbas yang menyokong susun atur batu, kita hanya perlu mengisytiharkannya:
.Grid-Masonry { /* Sama seperti gaya sebelumnya*/ grid-template-baris: besar-besaran; }
Walaupun ini tidak berfungsi di kebanyakan pelayar, di Firefox dengan bendera dijelaskan sebelum ini ia menghasilkan hasil yang diharapkan.
Tetapi bagaimana dengan penyemak imbas lain? Inilah yang kita perlukan ...
Penyelesaian JavaScript Fallback
Untuk menyelamatkan kod JavaScript yang mesti dijalankan oleh pelayar, kami mula-mula memeriksa sama ada terdapat .grid--masonry
pada halaman, dan sama ada penyemak imbas telah memahami dan menggunakan nilai masonry
grid-template-rows
. Perhatikan bahawa ini adalah pendekatan yang biasa, dengan mengandaikan bahawa terdapat banyak jejaring tersebut pada halaman kami.
biarkan grid = [... document.QuerySelectorAll ('. Grid-Masonry')]; jika (grids.length && getComputStyle (grids [0]). GridTemplaterows! == 'Masonry') { Console.log ('Oops, susun atur batu tidak menyokong?'); } else { console.log ('terlalu baik, tiada operasi diperlukan!'); }
Jika ciri batu baru tidak disokong, maka kami akan mendapat jurang baris dan item mesh untuk setiap jejaring batu dan kemudian tetapkan bilangan lajur (setiap mesh pada mulanya 0).
biarkan grid = [... document.QuerySelectorAll ('. Grid-Masonry')]; jika (grids.length && getComputStyle (grids [0]). GridTemplaterows! == 'Masonry') { grid = grids.map (grid => ({ _EL: Grid, Gap: Parsefloat (GetComputedStyle (Grid) .GridRowGap), Item: [... grid.childNodes] .filter (c => c.NodeType === 1), NCOL: 0 })); grids.foreach (grid => console.log (`item grid: $ {grid.items.length}; grid jurang: $ {grid.gap} px`)); }
Perhatikan bahawa kita perlu memastikan bahawa nod kanak -kanak adalah nod elemen (ini bermakna nodeType
mereka adalah 1). Jika tidak, kita mungkin berakhir dengan nod teks yang terdiri daripada pulangan pengangkutan dalam pelbagai projek.
Sebelum meneruskan, kita perlu memastikan bahawa halaman itu dimuatkan dan unsur -unsur masih bergerak. Sebaik sahaja kami menangani masalah ini, kami mengambil setiap grid dan membaca bilangan lajur semasa. Jika ini berbeza dari nilai yang sudah kita miliki, maka kita akan mengemas kini nilai lama dan menyusun semula item grid.
jika (grids.length && getComputStyle (grids [0]). GridTemplaterows! == 'Masonry') { grid = grids.map (/* sama seperti sebelum*/); susun atur fungsi () { grids.foreach (grid => { /* Dapatkan nombor lajur saiz semula/dimuatkan*/ biarkan ncol = getComputStyle (grid._el) .gridTemplateColumns.split ('') .length; jika (grid.ncol! == ncol) { grid.ncol = ncol; console.log ('Resodrange Grid Item'); } }); } addEventListener ('beban', e => { susun atur (); /* Beban awal*/ addEventListener ('saiz semula', susun atur, palsu); }, palsu); }
Perhatikan bahawa memanggil fungsi layout()
adalah operasi yang perlu kita lakukan apabila kedua -dua pemuatan dan saiz semula awal.
Untuk menyusun semula item grid, langkah pertama adalah untuk mengeluarkan margin teratas dari semua item (ini boleh ditetapkan kepada nilai bukan sifar untuk mencapai kesan batu sebelum saiz semula semasa).
Jika viewport cukup sempit dan kami hanya mempunyai satu lajur, maka kami sudah selesai!
Jika tidak, kami akan melangkau item ncol
pertama dan gelung melalui selebihnya. Untuk setiap item yang dipertimbangkan, kami mengira kedudukan tepi bawah item di atas dan kedudukan semasa tepi atas. Ini membolehkan kita mengira berapa banyak pergerakan menegak diperlukan supaya kelebihannya terletak di dalam jurang grid di bawah pinggir bawah projek di atas.
/* Jika bilangan lajur telah berubah*/ jika (grid.ncol! == ncol) { /* Bilangan lajur dikemas kini*/ grid.ncol = ncol; /* Memulihkan kedudukan awal, tiada sempadan*/ grid.items.foreach (c => c.style.removeProperty ('margin-top')); /* Jika kita mempunyai lebih daripada satu lajur*/ jika (grid.ncol> 1) { grid.items.slice (ncol) .foreach ((c, i) => { Biarkan prev_fin = grid.items [i] .getBoundingClientRect (). Bawah, /* pinggir bawah projek di atas* / curr_ini = c.getBoundingClientRect (). atas; /* kelebihan projek semasa*/ c.style.margintop = `$ {prev_fin grid.gap - curr_ini} px`; }); } }
Sekarang kita mempunyai penyelesaian silang pelayar yang bekerja!
Beberapa penambahbaikan kecil
Struktur yang lebih realistik
Di dunia nyata, kita lebih cenderung untuk membungkus setiap imej dalam pautan ke imej bersaiz penuh supaya imej yang besar dapat dibuka di dalam kotak cahaya (atau kita menavigasi sebagai sandaran).
<a href="https://www.php.cn/link/849c1f472f609bb4a3bacafef177f541"> <img src="/static/imghwm/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/174364597550777.jpg?x-oss-process=image/resize,p_40" class="lazy" alt="Penyelesaian batu ringan"> </a>
Ini bermakna kita perlu menukar CSS sedikit juga. Walaupun kita tidak lagi perlu secara eksplisit menetapkan lebar item grid - kerana mereka kini pautan - kita perlu menetapkan align-self: start
, kerana tidak seperti imej, mereka secara lalai meregangkan untuk menutup seluruh ketinggian baris, yang mengganggu algoritma kita.
.Grid-Masonry> * {Align-Self: Start; } img { paparan: blok; /* Elakkan ruang tambahan yang pelik di bahagian bawah*/ Lebar: 100%; /* Sama seperti gaya sebelumnya*/ }
Jadikan elemen pertama merangkumi mesh
Kita juga boleh membuat projek pertama secara mendatar merangkumi seluruh mesh (yang bermaksud kita mungkin juga mengehadkan ketinggiannya dan memastikan imej tidak melimpah atau berubah):
.Grid-Masonry>: anak pertama { Grid -lajur: 1 / -1; Max-Height: 29VH; } img { Max-Height: mewarisi; Objek-Fit: Cover; /* Sama seperti gaya sebelumnya*/ }
Kami juga perlu menambah penapis lain apabila mendapat senarai item grid untuk mengecualikan item yang diregangkan ini:
grid = grids.map (grid => ({ _EL: Grid, Gap: Parsefloat (GetComputedStyle (Grid) .GridRowGap), Item: [... grid.childNodes] .filter (c => c.NodeType === 1 && getComputStyle (C) .GridColumnEnd! == -1 )) NCOL: 0 }));
Mengendalikan item grid dengan nisbah aspek berubah -ubah
Katakan kami mahu menggunakan penyelesaian ini untuk tujuan seperti blogging. Kami menyimpan JS yang sama dan CSS khusus yang hampir sama dengan batu-kami hanya menukar lebar maksimum lajur dan keluarkan had max-height
untuk item pertama.
Seperti yang dapat dilihat dari demonstrasi di bawah, penyelesaian kami berfungsi dengan sempurna dalam kes ini, dan kami mempunyai grid pos blog:
Anda juga boleh mengubah saiz paparan untuk melihat bagaimana ia berfungsi dalam kes ini.
Walau bagaimanapun, jika kita mahu lebar lajur mempunyai beberapa fleksibiliti, sebagai contoh:
$ w: Minmax (min (20EM, 100%), 1FR);
Kemudian kita akan menghadapi masalah semasa mengubah saiz:
Gabungan perubahan dalam item grid 'dan hakikat bahawa kandungan teks setiap item adalah berbeza cara bahawa apabila ambang tertentu dilebihi, kita mungkin mendapat bilangan baris teks yang berbeza untuk item grid (dan dengan itu menukar ketinggian), tetapi item lain tidak. Jika bilangan lajur tidak berubah, offset menegak tidak dikira semula dan kami berakhir dengan tumpang tindih atau jurang yang lebih besar.
Untuk menyelesaikan masalah ini, kita perlu mengira semula mengimbangi apabila ketinggian grid semasa sekurang -kurangnya satu perubahan item. Ini bermakna kita juga perlu menguji sama ada terdapat lebih daripada sifar item dalam grid semasa yang telah mengubah ketinggian mereka. Kemudian kita perlu menetapkan semula nilai ini pada akhir blok if
supaya kita tidak perlu menyusun semula item -item tersebut pada masa akan datang.
jika (grid.ncol! == ncol || grid.mod) { /* Sama seperti sebelum*/ grid.mod = 0; }
Ok, tapi bagaimana kita menukar nilai grid.mod
ini? Idea pertama saya ialah menggunakan ResizeObserver
:
jika (grids.length && getComputStyle (grids [0]). GridTemplaterows! == 'Masonry') { Biarkan O = ResizeObserver baru (entri => { entri.Foreach (entry => { grids.find (grid => grid._el === entry.target.parentElement) .mod = 1; }); }); /* Sama seperti sebelum*/ addEventListener ('beban', e => { /* Sama seperti sebelum*/ grids.foreach (grid => {grid.items.foreach (c => o.observe (c));}); }, palsu); }
Ini memungkinkan untuk menyusun semula item grid jika perlu, walaupun bilangan lajur grid tidak berubah. Tetapi ia juga menjadikannya tidak bermakna if
keadaan tidak tersedia!
Ini kerana ia mengubah grid.mod
kepada 1 apabila ketinggian atau lebar sekurang -kurangnya satu perubahan item. Ketinggian projek akan berubah disebabkan oleh teks reflow, yang disebabkan oleh perubahan lebar. Walau bagaimanapun, perubahan lebar akan berlaku setiap kali kita menyesuaikan saiz viewport, dan ia tidak semestinya mencetuskan perubahan ketinggian.
Itulah sebabnya saya akhirnya memutuskan untuk menyimpan ketinggian projek sebelumnya dan periksa sama ada mereka telah berubah apabila diubah saiz untuk menentukan sama ada grid.mod
kekal pada 0:
susun atur fungsi () { grids.foreach (grid => { grid.items.Foreach (c => { biarkan new_h = c.getBoundingClientRect (). Ketinggian; jika (new_h! == c.dataset.h) { c.dataset.h = new_h; grid.mod; } }); /* Sama seperti sebelum*/ }); }
Itu sahaja! Sekarang kita mempunyai penyelesaian ringan yang bagus. JavaScript yang dimampatkan adalah kurang daripada 800 bait, manakala gaya yang berkaitan dengan batu adalah kurang daripada 300 bait.
Tetapi, bagaimanapun, tetapi ...
Bagaimana sokongan penyemak imbas?
Nah, @supports
berlaku untuk mempunyai sokongan penyemak imbas yang lebih baik daripada mana-mana ciri CSS yang lebih baru yang digunakan di sini, jadi kami boleh meletakkan barangan yang baik di dalamnya dan menyediakan mesh asas bukan Masonry untuk penyemak imbas yang tidak disokong. Versi ini bersesuaian dengan IE9.
Ia mungkin kelihatan berbeza, tetapi ia kelihatan baik dan mempunyai fungsi yang sempurna. Menyokong penyemak imbas tidak bermaksud menyalin semua kesan visual untuknya. Ini bermakna halaman berfungsi dan tidak kelihatan rosak atau hodoh.
Bagaimana dengan keadaan tanpa JavaScript?
Nah, kita hanya boleh menggunakan gaya mewah jika elemen akar mempunyai kelas js
yang kami tambahkan melalui JavaScript! Jika tidak, kami akan mendapat grid asas dengan saiz yang sama untuk semua item.
Atas ialah kandungan terperinci Penyelesaian batu ringan. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kursor adat dengan CSS adalah hebat, tetapi kita boleh mengambil sesuatu ke peringkat seterusnya dengan JavaScript. Menggunakan JavaScript, kita boleh beralih antara negeri kursor, letakkan teks dinamik dalam kursor, gunakan animasi kompleks, dan gunakan penapis.

Animasi CSS interaktif dengan unsur -unsur yang menghilangkan satu sama lain kelihatan lebih masuk akal pada tahun 2025. Walaupun tidak perlu untuk melaksanakan pong dalam CSS, peningkatan fleksibiliti dan kuasa CSS mengukuhkan kecurigaan Lee '

Petua dan cara untuk menggunakan harta penapis latar belakang CSS ke antara muka pengguna gaya. Anda akan belajar bagaimana untuk meletakkan penapis latar belakang di antara pelbagai elemen, dan mengintegrasikannya dengan kesan grafik CSS yang lain untuk membuat reka bentuk yang rumit.

Nah, ternyata ciri-ciri animasi terbina dalam SVG ' s tidak pernah ditamatkan seperti yang dirancang. Pasti, CSS dan JavaScript lebih mampu membawa beban, tetapi ia baik untuk mengetahui bahawa SMIL tidak mati di dalam air seperti sebelumnya

Yay, let ' s melompat untuk teks-wrap: Pretty Landing dalam Pratonton Teknologi Safari! Tetapi berhati -hatilah bahawa ia ' s berbeza dari bagaimana ia berfungsi dalam pelayar kromium.

Kemas kini trik CSS ini menyoroti kemajuan yang ketara dalam almanak, penampilan podcast baru-baru ini, panduan kaunter CSS baru, dan penambahan beberapa penulis baru yang menyumbang kandungan berharga.

Kebanyakan masa, orang mempamerkan ciri-ciri Tailwind ' Apabila dipamerkan dengan cara ini, @apply tidak menjanjikan sama sekali. Jadi obvio

Menggunakan seperti idiot datang ke ketidakcocokan antara alat yang anda gunakan untuk menggunakan dan ganjaran dalam kerumitan dikurangkan berbanding kerumitan yang ditambah.


Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

Artikel Panas

Alat panas

Dreamweaver Mac版
Alat pembangunan web visual

VSCode Windows 64-bit Muat Turun
Editor IDE percuma dan berkuasa yang dilancarkan oleh Microsoft

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Pelayar Peperiksaan Selamat
Pelayar Peperiksaan Selamat ialah persekitaran pelayar selamat untuk mengambil peperiksaan dalam talian dengan selamat. Perisian ini menukar mana-mana komputer menjadi stesen kerja yang selamat. Ia mengawal akses kepada mana-mana utiliti dan menghalang pelajar daripada menggunakan sumber yang tidak dibenarkan.

Dreamweaver CS6
Alat pembangunan web visual
