[CSS] Jak stworzyć 2 kolumny elementów ułożonych jak w mozaice?
W dzisiejszym artykule mam zamiar zaprezentować ciekawy sposób na zbudowanie 2-kolumnowego layoutu w którym elementy będą zajmowały dostępne miejsce bez pozostawiania wolnych przestrzeni. Dzięki temu otrzymamy coś w rodzaju mozaiki w dwóch kolumnach, która będzie się dostosowywała do wielkości elementów wewnątrz.
Swego czasu już pisałem o tym czym jest flexbox, dlatego tym, którzy nie do końca się orientują w tym temacie proponuję tam zajrzeć.
Kod HTML - flexbox
W celu osiągnięcia wymaganego efektu musimy najpierw sobie przygotować kod HTML, który będzie odwzorowywał listę elementów. Nie będzie to nic skomplikowanego, będzie to po prostu kontener z elementami w środku - czytaj: divy w divie 😉 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | <div class="container"> <div class="box"> <img src="http://placehold.it/400x300" alt=""> <p>Minions ipsum me want bananaaa! Para tú hahaha tank yuuu! Ti aamoo! Hana dul sae. Underweaaar bee do bee do bee do aaaaaah hahaha me want bananaaa! Chasy daa daa chasy uuuhhh chasy. Butt me want bananaaa! Bananaaaa la bodaaa tulaliloo uuuhhh poulet tikka masala chasy. Potatoooo tulaliloo jeje bee do bee do bee do po kass butt hana dul sae hahaha. Bappleees poulet tikka masala hahaha poopayee bappleees tulaliloo hana dul sae poopayee. Tatata bala tu wiiiii aaaaaah para tú. Wiiiii pepete me want bananaaa! Baboiii tank yuuu! Uuuhhh gelatooo poulet tikka masala butt hana dul sae. Bappleees pepete poopayee hahaha jiji tank yuuu!</p> </div> <div class="box"> <img src="http://placehold.it/400x130" alt=""> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolores laboriosam numquam optio tenetur delectus animi incidunt aperiam, tempora non totam rerum iste officia doloremque asperiores praesentium suscipit reprehenderit, repellendus, libero.</p> </div> <div class="box"> <img src="http://placehold.it/400x270" alt=""> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolores laboriosam numquam optio tenetur delectus animi incidunt aperiam, tempora non totam rerum iste officia doloremque asperiores praesentium suscipit reprehenderit, repellendus, libero.</p> </div> <div class="box"> <img src="http://placehold.it/400x250" alt=""> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolores laboriosam numquam optio tenetur delectus animi incidunt aperiam, tempora non totam rerum iste officia doloremque asperiores praesentium suscipit reprehenderit, repellendus, libero.</p> </div> <div class="box"> <img src="http://placehold.it/400x180" alt=""> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolores laboriosam numquam optio tenetur delectus animi incidunt aperiam, tempora non totam rerum iste officia doloremque asperiores praesentium suscipit reprehenderit, repellendus, libero.</p> </div> <div class="box"> <img src="http://placehold.it/400x300" alt=""> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolores laboriosam numquam optio tenetur delectus animi incidunt aperiam, tempora non totam rerum iste officia doloremque asperiores praesentium suscipit reprehenderit, repellendus, libero.</p> </div> <div class="box"> <img src="http://placehold.it/400x150" alt=""> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolores laboriosam numquam optio tenetur delectus animi incidunt aperiam, tempora non totam rerum iste officia doloremque asperiores praesentium suscipit reprehenderit, repellendus, libero.</p> </div> <div class="box"> <img src="http://placehold.it/400x290" alt=""> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolores laboriosam numquam optio tenetur delectus animi incidunt aperiam, tempora non totam rerum iste officia doloremque asperiores praesentium suscipit reprehenderit, repellendus, libero.</p> </div> <div class="box"> <img src="http://placehold.it/400x350" alt=""> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolores laboriosam numquam optio tenetur delectus animi incidunt aperiam, tempora non totam rerum iste officia doloremque asperiores praesentium suscipit reprehenderit, repellendus, libero.</p> </div> <div class="box"> <img src="http://placehold.it/400x430" alt=""> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolores laboriosam numquam optio tenetur delectus animi incidunt aperiam, tempora non totam rerum iste officia doloremque asperiores praesentium suscipit reprehenderit, repellendus, libero.</p> </div> <div class="box"> <img src="http://placehold.it/400x460" alt=""> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolores laboriosam numquam optio tenetur delectus animi incidunt aperiam, tempora non totam rerum iste officia doloremque asperiores praesentium suscipit reprehenderit, repellendus, libero.</p> </div> <div class="box"> <img src="http://placehold.it/400x256" alt=""> <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolores laboriosam numquam optio tenetur delectus animi incidunt aperiam, tempora non totam rerum iste officia doloremque asperiores praesentium suscipit reprehenderit, repellendus, libero.</p> </div> </div> |
Powyższa struktura jest bardzo powtarzalna. W każdym elemencie z klasą .box
zamieściłem obrazek o różnej wysokości oraz tekst typu lorem ipsum.
Kod CSS - flexbox
Pora na trochę kodu CSS. Aby osiągnąć zamierzony przez nas efekt musimy dodać następujące reguły:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | * { box-sizing: border-box; } .container { display: flex; flex-direction: column; flex-wrap: wrap; } .box { width: calc(50% - 1rem); padding: 1rem; margin: 0 .5rem 1rem; background: #eee; } .box img { display: block; width: 100%; max-width: 100%; } |
Efekt został osiągnięty dzięku temu, że do elementu .container
dodano regułę uruchamiającą tryb flexbox: display: flex;
. Inne reguły takie jak: flex-direction: column;
oraz flex-wrap: wrap;
sprawiają, że elementy będą się układały w kolumnie oraz będą zajmowały dostępne miejsce w kontenerze (ich ułożenie będzie się zawijać).
W związku z tym, że elementy z klasą .box
mają szerokość połowie szerokości kontenera, to zostawiają one miejsce z boku, które jest zajmowane przez inne elementy z klasą .box
.
Lecz to nie wszystko! - Potrzebny jest kod JS
Niestety, aby kontener mógł dynamicznie reagować na zmienną liczbę elementów wewnątrz lub na zmianę szerokości ekranu, tak aby elementy .box
zawsze układały się w dwóch kolumnach, należy dopisać kod JS, który będzie obliczał wysokość elementu z klasą .container
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | (function () { 'use strict'; var container = document.querySelector('.container'), boxes = Array.prototype.slice.call(container.querySelectorAll('.box')), setFlexboxHeight = function () { // lepiej ustawić wartość ratio na trochę więcej niż 50%, // dzięki temu jest mniejsze prawdopodobieństwo, że elementy się nie zmieszczą // w kontenerze var ratio = 0.55, boxesHeight = 0, boxMaxHeight = 0; // aby wykonać pomiar, należy tymczasowo ustawić wysokość kontenera na `auto` container.style.height = 'auto'; // szukamy najwyższego elementu w kontenerze // oraz budujemy sumę wysokości wszystkich elementów boxes.forEach(function (box) { boxMaxHeight = box.clientHeight > boxMaxHeight ? box.clientHeight : boxMaxHeight; boxesHeight += box.clientHeight; }); container.style.height = (boxesHeight * ratio) + 'px'; // jeśli elementy ułożyły się tak, że nie mieszczą się w kontenerze // powodując widoczny scrollbar to zwiększ wysokość kontenera poprzez // powiększenie wysokości kontenera elementów o wysokość najwyższego elementu. if (container.offsetWidth < container.scrollWidth) { container.style.height = (boxesHeight * ratio) + boxMaxHeight + 'px'; } }; // uruchamiamy pomiar wysokości w dwóch sytuacjach: // - po załadowaniu wszystkich elementów na stronie, // - po zmianie wielkości okna przeglądarki window.addEventListener('load', setFlexboxHeight); window.addEventListener('resize', setFlexboxHeight); })(); |
Dokładny opis kodu został zawarty w komentarzach do kodu, dlatego warto sobie go przejrzeć.
Powyższy kod przelicza wysokość kontenera elementów w dwóch momentach:
- Po załadowaniu wszystkich elementów na stronie,
- Oraz po zmianie wielkości okna przeglądarki.
Wysokość kontenera jest sumą wysokości elementów w środku. Jeśli po podzieleniu wysokości na pół okaże się, że elementy w środku się nie mieszczą w kontenerze i wychodzą z niego, to do wysokości kontenera - .container
, doliczam wysokość najwyższego elementu z klasą .box
. Dzięki temu rozwiązanie działa prawie w 100% przypadków.
Podsumowanie
Mam nadzieję, że zaprezentowane rozwiązanie będzie przydatne w Twoim projekcie. Od siebie dodam, że mając taki układ 2-kolumnowy jesteśmy w stanie utworzyć bardzo ciekawą galerię zdjęć bądź projektów zrealizowanych przez nas. Zapraszam do korzystania i komentowania rozwiązania.