Jadual Kandungan
Pertama, aktifkan bendera
Mari mulakan dengan beberapa markup
Sekarang, mari kita gunakan beberapa gaya
Penyelesaian JavaScript Fallback
Beberapa penambahbaikan kecil
Struktur yang lebih realistik
Jadikan elemen pertama merangkumi mesh
Mengendalikan item grid dengan nisbah aspek berubah -ubah
Tetapi, bagaimanapun, tetapi ...
Bagaimana sokongan penyemak imbas?
Bagaimana dengan keadaan tanpa JavaScript?
Rumah hujung hadapan web tutorial css Penyelesaian batu ringan

Penyelesaian batu ringan

Apr 03, 2025 am 10:06 AM

Penyelesaian batu ringan

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/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/174364597525146.jpg" class="lazy" alt="Penyelesaian batu ringan">
Salin selepas log masuk

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; }
}
Salin selepas log masuk

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; }
Salin selepas log masuk

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);
}
Salin selepas log masuk

Sekarang, untuk penyemak imbas yang menyokong susun atur batu, kita hanya perlu mengisytiharkannya:

 .Grid-Masonry {
  /* Sama seperti gaya sebelumnya*/
  grid-template-baris: besar-besaran;
}
Salin selepas log masuk

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!');
}
Salin selepas log masuk

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`));
}
Salin selepas log masuk

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);
}
Salin selepas log masuk

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`;
    });
  }
}
Salin selepas log masuk

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/imghw/default1.png" data-src="https://img.php.cn/upload/article/000/000/000/174364597550777.jpg" class="lazy" alt="Penyelesaian batu ringan">
</a>
Salin selepas log masuk

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*/
}
Salin selepas log masuk

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*/
}
Salin selepas log masuk

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
}));
Salin selepas log masuk

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);
Salin selepas log masuk

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;
}
Salin selepas log masuk

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);
}
Salin selepas log masuk

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*/
  });
}
Salin selepas log masuk

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!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

Video Face Swap

Video Face Swap

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

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Vue 3 Vue 3 Apr 02, 2025 pm 06:32 PM

Ia &#039; s! Tahniah kepada pasukan Vue untuk menyelesaikannya, saya tahu ia adalah usaha besar dan lama datang. Semua dokumen baru juga.

Bolehkah anda mendapatkan nilai harta CSS yang sah dari penyemak imbas? Bolehkah anda mendapatkan nilai harta CSS yang sah dari penyemak imbas? Apr 02, 2025 pm 06:17 PM

Saya mempunyai seseorang yang menulis dengan soalan yang sangat legit ini. Lea hanya blog tentang bagaimana anda boleh mendapatkan sifat CSS yang sah dari penyemak imbas. That &#039; s seperti ini.

Sedikit di CI/CD Sedikit di CI/CD Apr 02, 2025 pm 06:21 PM

Saya &#039;

Kad yang disusun dengan kedudukan melekit dan sasaran sass Kad yang disusun dengan kedudukan melekit dan sasaran sass Apr 03, 2025 am 10:30 AM

Pada hari yang lain, saya melihat sedikit ini sangat indah dari laman web Corey Ginnivan di mana koleksi kad timbunan di atas satu sama lain semasa anda menatal.

Menggunakan Markdown dan Penyetempatan di Editor Blok WordPress Menggunakan Markdown dan Penyetempatan di Editor Blok WordPress Apr 02, 2025 am 04:27 AM

Jika kita perlu menunjukkan dokumentasi kepada pengguna secara langsung dalam editor WordPress, apakah cara terbaik untuk melakukannya?

Membandingkan penyemak imbas untuk reka bentuk responsif Membandingkan penyemak imbas untuk reka bentuk responsif Apr 02, 2025 pm 06:25 PM

Terdapat beberapa aplikasi desktop ini di mana matlamat menunjukkan laman web anda pada dimensi yang berbeza pada masa yang sama. Oleh itu, anda boleh menulis

Cara menggunakan grid CSS untuk tajuk dan kaki melekit Cara menggunakan grid CSS untuk tajuk dan kaki melekit Apr 02, 2025 pm 06:29 PM

CSS Grid adalah koleksi sifat yang direka untuk menjadikan susun atur lebih mudah daripada yang pernah berlaku. Seperti apa -apa, ada sedikit keluk pembelajaran, tetapi grid adalah

Fon Font Google Fon Fon Font Google Fon Apr 09, 2025 am 10:42 AM

Saya melihat Font Google melancarkan reka bentuk baru (tweet). Berbanding dengan reka bentuk besar yang terakhir, ini terasa lebih berulang. Saya hampir tidak dapat memberitahu perbezaannya

See all articles