cari
Rumahhujung hadapan webtutorial cssPenyelesaian 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/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!

Kenyataan
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
Gaya CSS peringkat seterusnya untuk kursorGaya CSS peringkat seterusnya untuk kursorApr 23, 2025 am 11:04 AM

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.

Dunia bertembung: Pengesanan Perlanggaran Kerangka Key menggunakan pertanyaan gayaDunia bertembung: Pengesanan Perlanggaran Kerangka Key menggunakan pertanyaan gayaApr 23, 2025 am 10:42 AM

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 '

Menggunakan penapis latar belakang CSS untuk kesan UIMenggunakan penapis latar belakang CSS untuk kesan UIApr 23, 2025 am 10:20 AM

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.

SMIL ON?SMIL ON?Apr 23, 2025 am 09:57 AM

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

'Cantik' berada di mata penonton'Cantik' berada di mata penontonApr 23, 2025 am 09:40 AM

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.

CSS-Tricks Chronicles XLIIICSS-Tricks Chronicles XLIIIApr 23, 2025 am 09:35 AM

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.

Ciri tailwind ' s @ply lebih baik daripada bunyiCiri tailwind ' s @ply lebih baik daripada bunyiApr 23, 2025 am 09:23 AM

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

Rasa seperti saya tidak mempunyai pelepasan: perjalanan ke arah penyebaran yang warasRasa seperti saya tidak mempunyai pelepasan: perjalanan ke arah penyebaran yang warasApr 23, 2025 am 09:19 AM

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

See all articles

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

Dreamweaver Mac版

Dreamweaver Mac版

Alat pembangunan web visual

VSCode Windows 64-bit Muat Turun

VSCode Windows 64-bit Muat Turun

Editor IDE percuma dan berkuasa yang dilancarkan oleh Microsoft

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Pelayar Peperiksaan Selamat

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

Dreamweaver CS6

Alat pembangunan web visual