Loading…
<!DOCTYPE html>
<html>
<head>
<title>Modular Blog UI Component Set</title>
</head>
<body>
<section class="blog-components-demo py-5" aria-labelledby="blogKitTitle">
<div class="container">
<div class="blog-kit-header mb-4">
<p class="blog-kit-kicker mb-2">Reusable Blog Components</p>
<h1 id="blogKitTitle" class="display-6 fw-bold mb-3">Modular Blog UI Component Set</h1>
<p class="lead mb-0">Copy these responsive Bootstrap-friendly components into a blog index, article page, sidebar, or content hub.</p>
</div>
<div class="blog-toolbox card border-0 shadow-sm mb-4">
<div class="card-body">
<div class="row g-3 align-items-end">
<div class="col-12 col-lg-5">
<label for="blogSearch" class="form-label fw-semibold">Search components</label>
<div class="input-group">
<span class="input-group-text" aria-hidden="true"><i class="fa-solid fa-magnifying-glass"></i></span>
<input id="blogSearch" type="search" class="form-control" placeholder="Search by topic or title">
</div>
</div>
<div class="col-12 col-lg-7">
<p class="form-label fw-semibold mb-2">Filter by topic</p>
<div class="blog-filter-group" role="group" aria-label="Filter blog posts by topic">
<button class="blog-tag-filter active" type="button" data-filter="all" aria-pressed="true">All</button>
<button class="blog-tag-filter" type="button" data-filter="seo" aria-pressed="false">SEO</button>
<button class="blog-tag-filter" type="button" data-filter="content" aria-pressed="false">Content</button>
<button class="blog-tag-filter" type="button" data-filter="email" aria-pressed="false">Email</button>
<button class="blog-tag-filter" type="button" data-filter="analytics" aria-pressed="false">Analytics</button>
</div>
</div>
</div>
<p class="blog-results-text small text-muted mt-3 mb-0" aria-live="polite">Showing all blog components.</p>
</div>
</div>
<div class="row g-4 align-items-start">
<main class="col-12 col-lg-8">
<article class="blog-featured-card card border-0 shadow-sm mb-4 blog-post-item" data-category="content" data-search="content marketing strategy featured guide leads growth">
<div class="row g-0 align-items-stretch">
<div class="col-md-5">
<div class="blog-visual blog-visual-featured" role="img" aria-label="Abstract featured blog illustration">
<i class="fa-solid fa-pen-nib" aria-hidden="true"></i>
<span>Featured</span>
</div>
</div>
<div class="col-md-7">
<div class="card-body h-100 d-flex flex-column">
<span class="blog-pill mb-2">Featured Guide</span>
<h2 class="h3 card-title">How to Plan a Content Strategy That Converts</h2>
<p class="card-text flex-grow-1">Use this featured post component to highlight your most important article, tutorial, or campaign announcement.</p>
<div class="blog-meta mb-3">
<span><i class="fa-regular fa-calendar me-1" aria-hidden="true"></i>May 18, 2026</span>
<span><i class="fa-regular fa-user me-1" aria-hidden="true"></i>Jane Carter</span>
<span><i class="fa-regular fa-clock me-1" aria-hidden="true"></i>8 min read</span>
</div>
<a href="#" class="btn btn-primary align-self-start">Read featured post</a>
</div>
</div>
</div>
</article>
<div class="row g-4 blog-post-grid">
<div class="col-12 col-md-6 blog-post-item" data-category="seo" data-search="seo search optimization keywords ranking">
<article class="card h-100 border-0 shadow-sm blog-post-card">
<div class="blog-visual blog-visual-seo" role="img" aria-label="Abstract SEO blog illustration">
<i class="fa-solid fa-chart-line" aria-hidden="true"></i>
</div>
<div class="card-body d-flex flex-column">
<span class="blog-pill">SEO</span>
<h2 class="h5 card-title mt-2">SEO Checklist Before Publishing a Blog Post</h2>
<p class="card-text flex-grow-1">Check titles, headings, meta descriptions, links, and search intent before every article goes live.</p>
<div class="blog-meta mb-3"><span>5 min read</span><span>Beginner</span></div>
<a href="#" class="btn btn-outline-primary mt-auto">Read more</a>
</div>
</article>
</div>
<div class="col-12 col-md-6 blog-post-item" data-category="email" data-search="email newsletter subscribers engagement open rate">
<article class="card h-100 border-0 shadow-sm blog-post-card">
<div class="blog-visual blog-visual-email" role="img" aria-label="Abstract email marketing blog illustration">
<i class="fa-solid fa-envelope-open-text" aria-hidden="true"></i>
</div>
<div class="card-body d-flex flex-column">
<span class="blog-pill">Email</span>
<h2 class="h5 card-title mt-2">Newsletter Blocks That Keep Readers Engaged</h2>
<p class="card-text flex-grow-1">Use short lessons, curated links, and useful examples to build a newsletter readers look forward to.</p>
<div class="blog-meta mb-3"><span>6 min read</span><span>Growth</span></div>
<a href="#" class="btn btn-outline-primary mt-auto">Read more</a>
</div>
</article>
</div>
<div class="col-12 col-md-6 blog-post-item" data-category="analytics" data-search="analytics metrics reporting page views conversions">
<article class="card h-100 border-0 shadow-sm blog-post-card">
<div class="blog-visual blog-visual-analytics" role="img" aria-label="Abstract analytics blog illustration">
<i class="fa-solid fa-chart-pie" aria-hidden="true"></i>
</div>
<div class="card-body d-flex flex-column">
<span class="blog-pill">Analytics</span>
<h2 class="h5 card-title mt-2">Blog Metrics Worth Reviewing Monthly</h2>
<p class="card-text flex-grow-1">Track engagement, conversions, traffic quality, and newsletter growth instead of vanity metrics.</p>
<div class="blog-meta mb-3"><span>4 min read</span><span>Reporting</span></div>
<a href="#" class="btn btn-outline-primary mt-auto">Read more</a>
</div>
</article>
</div>
<div class="col-12 col-md-6 blog-post-item" data-category="content" data-search="content repurposing workflow social media blog assets">
<article class="card h-100 border-0 shadow-sm blog-post-card">
<div class="blog-visual blog-visual-content" role="img" aria-label="Abstract content workflow blog illustration">
<i class="fa-solid fa-layer-group" aria-hidden="true"></i>
</div>
<div class="card-body d-flex flex-column">
<span class="blog-pill">Content</span>
<h2 class="h5 card-title mt-2">Repurpose One Article into Multiple Assets</h2>
<p class="card-text flex-grow-1">Turn one useful article into social posts, email sections, short scripts, and lead magnets.</p>
<div class="blog-meta mb-3"><span>7 min read</span><span>Workflow</span></div>
<a href="#" class="btn btn-outline-primary mt-auto">Read more</a>
</div>
</article>
</div>
</div>
<nav class="blog-pagination mt-4" aria-label="Blog pagination">
<ul class="pagination justify-content-center mb-0">
<li class="page-item disabled"><a class="page-link" href="#" tabindex="-1" aria-disabled="true">Previous</a></li>
<li class="page-item active" aria-current="page"><a class="page-link" href="#">1</a></li>
<li class="page-item"><a class="page-link" href="#">2</a></li>
<li class="page-item"><a class="page-link" href="#">3</a></li>
<li class="page-item"><a class="page-link" href="#">Next</a></li>
</ul>
</nav>
</main>
<aside class="col-12 col-lg-4" aria-label="Blog sidebar components">
<div class="blog-sidebar-stack">
<section class="card border-0 shadow-sm blog-widget">
<div class="card-body">
<h2 class="h5"><i class="fa-solid fa-magnifying-glass me-2" aria-hidden="true"></i>Search Widget</h2>
<label for="sidebarSearch" class="form-label">Search posts</label>
<input id="sidebarSearch" type="search" class="form-control" placeholder="Type a keyword">
</div>
</section>
<section class="card border-0 shadow-sm blog-widget">
<div class="card-body">
<h2 class="h5"><i class="fa-solid fa-clock me-2" aria-hidden="true"></i>Recent Posts</h2>
<ul class="blog-link-list mb-0">
<li><a href="#">SEO trends worth testing this quarter</a></li>
<li><a href="#">Building a stronger brand voice</a></li>
<li><a href="#">Email newsletter ideas for creators</a></li>
</ul>
</div>
</section>
<section class="card border-0 shadow-sm blog-widget">
<div class="card-body">
<h2 class="h5"><i class="fa-solid fa-tags me-2" aria-hidden="true"></i>Tag Cloud</h2>
<div class="blog-tag-cloud" aria-label="Popular blog tags">
<a href="#">Marketing</a>
<a href="#">SEO</a>
<a href="#">Content</a>
<a href="#">Email</a>
<a href="#">Analytics</a>
<a href="#">Growth</a>
</div>
</div>
</section>
</div>
</aside>
</div>
<section class="blog-comments card border-0 shadow-sm mt-5" aria-labelledby="commentsTitle">
<div class="card-body p-4">
<h2 id="commentsTitle" class="h4 mb-4"><i class="fa-solid fa-comments me-2" aria-hidden="true"></i>Comment List Component</h2>
<ul class="list-unstyled mb-0">
<li class="blog-comment">
<div class="d-flex flex-column flex-sm-row justify-content-between gap-2">
<strong>Alex Smith</strong>
<small class="text-muted">April 23, 2026</small>
</div>
<p class="mb-2">Great insights. I especially like the tip about repurposing long-form content.</p>
<button class="btn btn-sm btn-outline-secondary blog-reply-toggle" type="button" aria-expanded="false" aria-controls="replyBox1" data-target="replyBox1">
<i class="fa-solid fa-reply me-1" aria-hidden="true"></i>Reply
</button>
<div class="blog-reply-box mt-3" id="replyBox1" hidden>
<label for="replyText1" class="form-label">Write a reply</label>
<textarea id="replyText1" class="form-control mb-2" rows="2" placeholder="Write your reply"></textarea>
<button class="btn btn-primary btn-sm" type="button">Send reply</button>
</div>
</li>
<li class="blog-comment">
<div class="d-flex flex-column flex-sm-row justify-content-between gap-2">
<strong>Maria Lopez</strong>
<small class="text-muted">April 24, 2026</small>
</div>
<p class="mb-2">Can you share more examples for measuring content marketing ROI?</p>
<button class="btn btn-sm btn-outline-secondary blog-reply-toggle" type="button" aria-expanded="false" aria-controls="replyBox2" data-target="replyBox2">
<i class="fa-solid fa-reply me-1" aria-hidden="true"></i>Reply
</button>
<div class="blog-reply-box mt-3" id="replyBox2" hidden>
<label for="replyText2" class="form-label">Write a reply</label>
<textarea id="replyText2" class="form-control mb-2" rows="2" placeholder="Write your reply"></textarea>
<button class="btn btn-primary btn-sm" type="button">Send reply</button>
</div>
</li>
</ul>
</div>
</section>
</div>
</section>
</body>
</html>.blog-components-demo {
--blog-primary: #4f46e5;
--blog-primary-dark: #3730a3;
--blog-accent: #06b6d4;
--blog-bg: #f8fafc;
--blog-soft: #eef2ff;
--blog-text: #172033;
--blog-muted: #667085;
--blog-border: #e5e7eb;
background: radial-gradient(circle at top left, rgba(79, 70, 229, 0.1), transparent 32%), linear-gradient(180deg, #ffffff 0%, var(--blog-bg) 100%);
color: var(--blog-text);
}
.blog-components-demo a:focus,
.blog-components-demo button:focus,
.blog-components-demo input:focus,
.blog-components-demo textarea:focus {
outline: 3px solid rgba(79, 70, 229, 0.3);
outline-offset: 3px;
}
.blog-kit-header {
max-width: 780px;
}
.blog-kit-kicker {
color: var(--blog-primary);
font-size: 0.78rem;
font-weight: 800;
letter-spacing: 0.12em;
text-transform: uppercase;
}
.blog-kit-header .lead {
color: var(--blog-muted);
}
.blog-toolbox,
.blog-featured-card,
.blog-post-card,
.blog-widget,
.blog-comments {
border-radius: 1.25rem;
overflow: hidden;
}
.blog-filter-group {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.blog-tag-filter {
border: 1px solid var(--blog-border);
border-radius: 999px;
padding: 0.45rem 0.9rem;
color: var(--blog-text);
background: #ffffff;
font-weight: 700;
transition: color 0.2s ease, background-color 0.2s ease, border-color 0.2s ease;
}
.blog-tag-filter:hover,
.blog-tag-filter.active {
color: #ffffff;
border-color: var(--blog-primary);
background: var(--blog-primary);
}
.blog-visual {
min-height: 210px;
display: grid;
place-items: center;
gap: 0.75rem;
color: #ffffff;
text-align: center;
}
.blog-visual i {
font-size: 2.8rem;
}
.blog-visual span {
font-weight: 800;
letter-spacing: 0.04em;
text-transform: uppercase;
}
.blog-visual-featured {
height: 100%;
background: linear-gradient(135deg, #4f46e5, #06b6d4);
}
.blog-visual-seo {
background: linear-gradient(135deg, #1d4ed8, #60a5fa);
}
.blog-visual-email {
background: linear-gradient(135deg, #be185d, #f9a8d4);
}
.blog-visual-analytics {
background: linear-gradient(135deg, #0891b2, #67e8f9);
}
.blog-visual-content {
background: linear-gradient(135deg, #b45309, #fbbf24);
}
.blog-pill {
display: inline-flex;
align-self: flex-start;
border-radius: 999px;
padding: 0.35rem 0.7rem;
color: var(--blog-primary);
background: var(--blog-soft);
font-size: 0.75rem;
font-weight: 800;
letter-spacing: 0.04em;
text-transform: uppercase;
}
.blog-meta {
display: flex;
flex-wrap: wrap;
gap: 0.75rem;
color: var(--blog-muted);
font-size: 0.875rem;
font-weight: 600;
}
.blog-components-demo .btn-primary {
border-color: var(--blog-primary);
background-color: var(--blog-primary);
}
.blog-components-demo .btn-primary:hover {
border-color: var(--blog-primary-dark);
background-color: var(--blog-primary-dark);
}
.blog-components-demo .btn-outline-primary {
color: var(--blog-primary);
border-color: var(--blog-primary);
}
.blog-components-demo .btn-outline-primary:hover {
color: #ffffff;
border-color: var(--blog-primary);
background-color: var(--blog-primary);
}
.blog-post-card {
transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.blog-post-card:hover {
transform: translateY(-4px);
box-shadow: 0 1rem 2.5rem rgba(30, 41, 59, 0.14) !important;
}
.blog-sidebar-stack {
display: grid;
gap: 1rem;
}
.blog-link-list {
list-style: none;
padding: 0;
}
.blog-link-list li + li {
margin-top: 0.75rem;
}
.blog-link-list a {
color: var(--blog-text);
font-weight: 600;
text-decoration: none;
}
.blog-link-list a:hover {
color: var(--blog-primary);
}
.blog-tag-cloud {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.blog-tag-cloud a {
display: inline-flex;
border-radius: 999px;
padding: 0.4rem 0.7rem;
color: var(--blog-primary);
background: var(--blog-soft);
font-size: 0.85rem;
font-weight: 700;
text-decoration: none;
}
.blog-pagination .page-link {
color: var(--blog-primary);
}
.blog-pagination .page-item.active .page-link {
border-color: var(--blog-primary);
background-color: var(--blog-primary);
}
.blog-comment {
padding: 1rem;
border: 1px solid var(--blog-border);
border-radius: 1rem;
background: #ffffff;
}
.blog-comment + .blog-comment {
margin-top: 1rem;
}
.blog-post-item.is-hidden {
display: none !important;
}
@media (max-width: 767.98px) {
.blog-visual-featured {
min-height: 190px;
}
.blog-toolbox .card-body {
padding: 1rem;
}
}
@media (prefers-reduced-motion: reduce) {
.blog-components-demo *,
.blog-components-demo *::before,
.blog-components-demo *::after {
transition: none !important;
}
}document.addEventListener('DOMContentLoaded', function () {
var demo = document.querySelector('.blog-components-demo');
if (!demo) return;
var searchInput = demo.querySelector('#blogSearch');
var filterButtons = demo.querySelectorAll('.blog-tag-filter');
var postItems = demo.querySelectorAll('.blog-post-item');
var resultsText = demo.querySelector('.blog-results-text');
var activeFilter = 'all';
function normalize(value) {
return String(value || '').toLowerCase().trim();
}
function updateVisiblePosts() {
var query = normalize(searchInput ? searchInput.value : '');
var visibleCount = 0;
postItems.forEach(function (item) {
var category = normalize(item.getAttribute('data-category'));
var searchable = normalize(item.getAttribute('data-search'));
var matchesFilter = activeFilter === 'all' || category === activeFilter;
var matchesSearch = !query || searchable.indexOf(query) !== -1;
var shouldShow = matchesFilter && matchesSearch;
item.classList.toggle('is-hidden', !shouldShow);
if (shouldShow) visibleCount += 1;
});
if (resultsText) {
resultsText.textContent = visibleCount === 1 ? 'Showing 1 blog component.' : 'Showing ' + visibleCount + ' blog components.';
}
}
if (searchInput) {
searchInput.addEventListener('input', updateVisiblePosts);
}
filterButtons.forEach(function (button) {
button.addEventListener('click', function () {
activeFilter = button.getAttribute('data-filter') || 'all';
filterButtons.forEach(function (currentButton) {
var isActive = currentButton === button;
currentButton.classList.toggle('active', isActive);
currentButton.setAttribute('aria-pressed', String(isActive));
});
updateVisiblePosts();
});
});
var replyButtons = demo.querySelectorAll('.blog-reply-toggle');
replyButtons.forEach(function (button) {
button.addEventListener('click', function () {
var targetId = button.getAttribute('data-target');
var replyBox = targetId ? demo.querySelector('#' + targetId) : null;
if (!replyBox) return;
var isOpening = replyBox.hasAttribute('hidden');
replyBox.toggleAttribute('hidden', !isOpening);
button.setAttribute('aria-expanded', String(isOpening));
if (isOpening) {
var textarea = replyBox.querySelector('textarea');
if (textarea) textarea.focus();
}
});
});
updateVisiblePosts();
});