Układ Masonry w Bootstrap 5.3 z wykorzystaniem komponentów Card
Czym jest układ Masonry?
Układ Masonry to technika rozmieszczania elementów w siatce o nieregularnych wysokościach, przypominająca ułożenie cegieł w murze. Jest często wykorzystywana w galeriach obrazów, blogach i innych aplikacjach internetowych prezentujących dynamiczne treści.
Wsparcie Masonry w Bootstrap 5.3
Bootstrap 5.3 nie zawiera wbudowanego wsparcia dla układu Masonry, ale możemy łatwo dodać go za pomocą biblioteki Masonry.js
.
Przykładowy kod
Oto przykład implementacji układu Masonry w Bootstrap 5.3 z użyciem komponentów Card
:
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Masonry w Bootstrap 5.3</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://unpkg.com/masonry-layout@4/dist/masonry.pkgd.min.js"></script>
</head>
<body>
<div class="container mt-4">
<div class="row" data-masonry='{"percentPosition": true }'>
<div class="col-md-6 mb-4">
<div class="card">
<img src="https://placehold.co/300x200" class="card-img-top" alt="Obraz">
<div class="card-body">
<h5 class="card-title">Tytuł 1</h5>
<p class="card-text">Krótki opis karty.</p>
</div>
</div>
</div>
<div class="col-md-6 mb-4">
<div class="card">
<img src="https://placehold.co/300x250" class="card-img-top" alt="Obraz">
<div class="card-body">
<h5 class="card-title">Tytuł 2</h5>
<p class="card-text">Inny opis karty.</p>
</div>
</div>
</div>
<div class="col-md-6 mb-4">
<div class="card">
<img src="https://placehold.co/300x180" class="card-img-top" alt="Obraz">
<div class="card-body">
<h5 class="card-title">Tytuł 3</h5>
<p class="card-text">Jeszcze inny opis.</p>
</div>
</div>
</div>
<div class="col-md-6 mb-4">
<div class="card">
<img src="https://placehold.co/300x250" class="card-img-top" alt="Obraz">
<div class="card-body">
<h5 class="card-title">Tytuł 2</h5>
<p class="card-text">Inny opis karty.</p>
</div>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
var msnry = new Masonry('.row', {
itemSelector: '.col-md-6',
percentPosition: true
});
});
</script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
Omówienie kodu
- Struktura HTML: Użyto klasy
row
dla kontenera kart orazcol-md-6
dla responsywnego układu kolumn. - Masonry.js: Biblioteka układu Masonry jest dodana poprzez CDN i inicjalizowana w skrypcie.
- Karty Bootstrap: Każda karta ma nieregularne wysokości obrazków, co demonstruje dynamiczny układ Masonry.
- Stylizacja: Klasa
mb-4
zapewnia margines dolny między kartami.
Obsługa Masonry na stronie z Vue.js
W przypadku stron z treścią ładowaną dynamicznie za pomocą żądań asynchronicznych sporawa nie jest już taka prosta jak wyżej. Poniższy kod przedstawia jak zastosować Masonry w kodzie z Vue.js.
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Masonry w Bootstrap 5.3 Vue 2.7</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script src="https://unpkg.com/masonry-layout@4/dist/masonry.pkgd.min.js"></script>
</head>
<body>
<div class="container mt-4" id="app">
<div class="row" data-masonry='{"percentPosition": true }'>
<div class="col-md-6 mb-4" v-for="item in items">
<div class="card">
<img :src="item.image" class="card-img-top" alt="Obraz">
<div class="card-body">
<h5 class="card-title">{{ item.title }}</h5>
<p class="card-text">{{ item.text }}</p>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.imagesloaded/4.1.4/imagesloaded.pkgd.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/masonry-layout@4.2.2/dist/masonry.pkgd.min.js" integrity="sha384-GNFwBvfVxBkLMJpYMOABq3c+d3KnQxudP/mGPkzpZSTYykLBNsZEnG2D9G/X/+7D" crossorigin="anonymous"></script>
<script>
var vm = new Vue({
el: '#app',
updated() {
var row = document.querySelector('.row[data-masonry]');
if (row) {
imagesLoaded(row, function() {
new Masonry(row, {
itemSelector: '.col-md-6',
percentPosition: true
});
});
}
},
data: {
items: []
}
});
setTimeout(function() {
vm.items = [
{image: 'https://placehold.co/300x200', title: 'Tytuł 1', text: 'Krótki opis'},
{image: 'https://placehold.co/300x250', title: 'Tytuł 2', text: 'Dłuższy opis, który normalnie powodowałby różnicę wysokości.'},
{image: 'https://placehold.co/300x180', title: 'Tytuł 3', text: 'Krótki opis'},
{image: 'https://placehold.co/300x250', title: 'Tytuł 4', text: 'Dłuższy opis, który normalnie powodowałby różnicę wysokości.'}
];
}, 500);
</script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
Obsługa Masonry na stronie z Knockout.js
Podobie jak w przypadku Vue.js aby obsłużyć Masonry trzeba użyć podobnego podejścia, ładując dodatkową bibliotekę imagesloaded
i obsłużyć Masonry w JavaScript.
<!DOCTYPE html>
<html lang="pl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Masonry w Bootstrap 5.3 Knockout 3.5</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.5.0/knockout-min.js"></script>
<script src="https://unpkg.com/masonry-layout@4/dist/masonry.pkgd.min.js"></script>
</head>
<body>
<div class="container mt-4" id="app">
<div class="row" data-masonry='{"percentPosition": true }' data-bind="foreach: items">
<div class="col-md-6 mb-4">
<div class="card">
<img data-bind="attr: {src: image}" class="card-img-top" alt="Obraz">
<div class="card-body">
<h5 class="card-title" data-bind="text: title"></h5>
<p class="card-text" data-bind="text: text"></p>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.imagesloaded/4.1.4/imagesloaded.pkgd.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/masonry-layout@4.2.2/dist/masonry.pkgd.min.js" integrity="sha384-GNFwBvfVxBkLMJpYMOABq3c+d3KnQxudP/mGPkzpZSTYykLBNsZEnG2D9G/X/+7D" crossorigin="anonymous"></script>
<script>
var vm = {
items: ko.observableArray()
};
ko.applyBindings(vm);
setTimeout(function() {
vm.items([
{image: 'https://placehold.co/300x200', title: 'Tytuł 1', text: 'Krótki opis'},
{image: 'https://placehold.co/300x250', title: 'Tytuł 2', text: 'Dłuższy opis, który normalnie powodowałby różnicę wysokości.'},
{image: 'https://placehold.co/300x180', title: 'Tytuł 3', text: 'Krótki opis'},
{image: 'https://placehold.co/300x250', title: 'Tytuł 4', text: 'Dłuższy opis, który normalnie powodowałby różnicę wysokości.'}
]);
var row = document.querySelector('.row[data-masonry]');
if (row) {
imagesLoaded(row, function() {
new Masonry(row, {
itemSelector: '.col-md-6',
percentPosition: true
});
});
}
}, 500);
</script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
</body>
</html>
Dzięki temu układowi uzyskujemy estetyczne i responsywne rozmieszczenie kart w siatce o nieregularnych wysokościach. Można go dostosować do własnych potrzeb, np. zmieniając liczby kolumn czy rozmiary obrazów.