Bootstrap Blog Post Card Grid with Read-Time Sort — Free Snippet
Bootstrap Blog Post Card Grid with Read-Time Filter · Cards · Plain HTML, CSS & JS · Live preview
Copy & paste
Source Code
<div class="container py-5">
<div class="d-flex justify-content-between align-items-center flex-wrap gap-2 mb-4">
<h1 class="bsblog-title mb-0">From the blog</h1>
<select class="form-select form-select-sm" style="width:auto" id="bsblogSort">
<option value="newest">Newest first</option>
<option value="quickest">Quickest read</option>
</select>
</div>
<div class="row g-4" id="bsblogGrid">
<div class="col-md-4" data-date="2026-09-01" data-mins="8">
<div class="card h-100"><div class="bsblog-cover" style="--h:230"></div><div class="card-body">
<span class="badge bg-primary-subtle text-primary-emphasis mb-2">Engineering</span>
<h5 class="card-title">Scaling our API to 10x traffic</h5>
<p class="text-muted small">Sep 1 · 8 min read</p>
</div></div>
</div>
<div class="col-md-4" data-date="2026-08-20" data-mins="3">
<div class="card h-100"><div class="bsblog-cover" style="--h:20"></div><div class="card-body">
<span class="badge bg-success-subtle text-success-emphasis mb-2">Product</span>
<h5 class="card-title">Introducing dark mode</h5>
<p class="text-muted small">Aug 20 · 3 min read</p>
</div></div>
</div>
<div class="col-md-4" data-date="2026-08-28" data-mins="5">
<div class="card h-100"><div class="bsblog-cover" style="--h:150"></div><div class="card-body">
<span class="badge bg-warning-subtle text-warning-emphasis mb-2">Design</span>
<h5 class="card-title">Redesigning our onboarding flow</h5>
<p class="text-muted small">Aug 28 · 5 min read</p>
</div></div>
</div>
</div>
</div>.bsblog-title { font-weight: 800; letter-spacing: -0.01em; }
.bsblog-cover { height: 140px; border-radius: 8px 8px 0 0; background: linear-gradient(135deg, hsl(calc(var(--h)) 60% 85%), hsl(calc(var(--h) + 50) 60% 70%)); }const grid = document.getElementById('bsblogGrid');
const sort = document.getElementById('bsblogSort');
function applySort() {
const cols = Array.from(grid.children);
const key = sort.value;
cols.sort((a, b) => key === 'newest'
? new Date(b.dataset.date) - new Date(a.dataset.date)
: Number(a.dataset.mins) - Number(b.dataset.mins)
);
cols.forEach(col => grid.appendChild(col));
}
sort.addEventListener('change', applySort);Extend with AI
Take This Snippet Further With AI
The AI prompt for this one is for Patreon supporters ($3 a month, 7 days free), along with a site with no ads. Supporters enter the passcode once and it is remembered in this browser.
What's included
Features
About this UI Snippet
Bootstrap Blog Post Card Grid with Read-Time Sort — HTML, CSS & JavaScript

Each card in this grid carries its real metadata as data attributes — data-date and data-mins — so the sort dropdown can genuinely reorder them: Array.from(grid.children) reads every card, .sort() compares dates or read-time minutes depending on the selected option, and grid.appendChild(col) in the new order physically moves each card to its sorted position, since re-appending an element already in the DOM relocates it rather than duplicating it.
Built on real Bootstrap 5.3 cards and grid, with Bootstrap 5.3's newer "subtle" badge variants for the category tags — soft enough not to compete visually with the headline, which is exactly what a category label on a card should do.
Step by step
How to Use
- 1Load the snippetClick the snippet in the sidebar Library tab. The preview loads three post cards in their authored order.
- 2Select "Newest first"The cards reorder so the Sep 1 post leads, followed by Aug 28, then Aug 20.
- 3Select "Quickest read"The cards reorder again — the 3-minute post leads, then 5-minute, then 8-minute.
- 4Add a fourth postCopy a column block with its own data-date and data-mins — it participates in both sort orders automatically.
Real-world uses
Common Use Cases
Got questions?
Frequently Asked Questions
It genuinely reorders the underlying DOM elements — grid.appendChild(col) on an element already in the DOM moves it to the new position rather than creating a duplicate, so the real element order (and therefore tab order for keyboard users) changes too.
Each card's data-mins attribute holds its read-time in minutes; the sort compares those numbers directly rather than parsing the visible "X min read" text.
Yes — add a new <option> to the select, and a new comparator branch in applySort() reading each card's title text (e.g. via querySelector('.card-title').textContent) for the comparison.
No — each is a CSS gradient keyed off a --h hue variable, so the grid works immediately with no images. Swap in real cover photography by changing .bsblog-cover's background.
Yes — bg-success-subtle and its -emphasis text counterpart are newer Bootstrap 5.3 utility variants specifically designed for lower-contrast label use, versus the older solid bg-success style.