Create responsive, production-grade static HTML pages using Bootstrap 5 (latest) with modern UI components, icons, dark/light mode, and professional design patterns. Use when creating demo pages, dashboards, sample applications, or UI mockups that need polished, responsive interfaces.
This skill guides creation of responsive HTML pages that leverage Bootstrap 5 to produce professional, fully-functional static web applications. The approach emphasizes clean code, semantic HTML, proper Bootstrap patterns, and modern UI/UX features.
Note: For data management features (search, sort, filter, pagination) and Faker.js integration, see data-features-with-faker. For SEO optimization, see seo-optimization.
When a user requests an HTML page, clarify these points:
Once requirements are clear, provide complete, working HTML file.
Always include Bootstrap 5 latest from CDN:
<!-- Bootstrap 5 CSS -->
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- Font Awesome 6 Icons -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<!-- Bootstrap 5 JS Bundle (includes Popper.js) -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
Icon Search: Use fontawesome.com to find icons. Prefix with fas for solid, far for regular, fab for brands.
Common Icons:
fa-save, fa-trash, fa-edit, fa-check, fa-times, fa-plusfa-home, fa-user, fa-cog, fa-search, fa-barsfa-table, fa-list, fa-chart-bar, fa-databasefa-circle, fa-check-circle, fa-times-circle, fa-exclamation-trianglefa-chevron-left, fa-chevron-right, fa-chevron-down, fa-spinnerUsage Examples:
<!-- In buttons -->
<button class="btn btn-primary">
<i class="fas fa-save me-1"></i>Save
</button>
<!-- Icon-only button -->
<button class="btn btn-sm btn-danger" title="Delete" aria-label="Delete">
<i class="fas fa-trash"></i>
</button>
<!-- In text -->
<span class="me-2"><i class="fas fa-envelope"></i></span> Email
.container, .row, .col-* (12-column grid, breakpoints: xs, sm, md, lg, xl, xxl)d-none d-md-block for showing/hiding at breakpoints<main>, <section>, <article>, <header>, <footer> for structure<table> for tabular data (not divs)<form> with proper <label> associations<!-- Correct structure -->
<div class="container">
<div class="row">
<div class="col-md-6">Content</div>
<div class="col-md-6">Content</div>
</div>
</div>
Key points:
.container or .container-fluid for max-width wrapping.row must be direct child of .container.row<!-- Bootstrap responsive image with lazy loading -->
<img src="path/to/image.jpg"
class="img-fluid"
alt="Description"
loading="lazy"
decoding="async">
Always include a search input in the navbar or header for professional appearance.
Include at page bottom for system status and metadata display.
For pages displaying lists or data, include appropriate navigation controls.
Note: For detailed implementation of search, pagination, sorting, and filtering, see data-features-with-faker.
Bootstrap 5 supports dark mode through CSS data attributes.
<!-- Add data-bs-theme attribute to <html> root element -->
<html lang="en" data-bs-theme="light">
<!-- Add to navbar or header -->
<button class="btn btn-sm" id="themeToggle" aria-label="Toggle dark mode">
<i class="fas fa-moon"></i>
</button>
// Initialize theme on page load
function initTheme() {
const saved = localStorage.getItem('theme') || 'light';
document.documentElement.setAttribute('data-bs-theme', saved);
updateThemeIcon(saved);
}
// Toggle between light and dark
function toggleTheme() {
const current = document.documentElement.getAttribute('data-bs-theme');
const newTheme = current === 'light' ? 'dark' : 'light';
document.documentElement.setAttribute('data-bs-theme', newTheme);
localStorage.setItem('theme', newTheme);
updateThemeIcon(newTheme);
}
// Update icon based on theme
function updateThemeIcon(theme) {
const icon = document.querySelector('#themeToggle i');
if (theme === 'dark') {
icon.classList.remove('fa-moon');
icon.classList.add('fa-sun');
} else {
icon.classList.remove('fa-sun');
icon.classList.add('fa-moon');
}
}
// Initialize on page load
document.addEventListener('DOMContentLoaded', initTheme);
document.getElementById('themeToggle').addEventListener('click', toggleTheme);
<style>
:root[data-bs-theme="light"] {
--custom-bg: #ffffff;
--custom-text: #000000;
--custom-border: #e0e0e0;
}
:root[data-bs-theme="dark"] {
--custom-bg: #1a1a1a;
--custom-text: #ffffff;
--custom-border: #333333;
}
.custom-element {
background-color: var(--custom-bg);
color: var(--custom-text);
border: 1px solid var(--custom-border);
}
</style>
Key Points:
localStorageAll buttons lock for 3 seconds after click to prevent accidental double-submission.
// Attach button lock handlers to all buttons
function attachButtonLockHandlers() {
const buttons = document.querySelectorAll('button:not([data-no-lock])');
buttons.forEach(button => {
button.addEventListener('click', handleButtonClick);
});
}
function handleButtonClick(event) {
const button = event.currentTarget;
// Skip if already disabled
if (button.disabled) {
event.preventDefault();
return;
}
// Store original content
const originalHTML = button.innerHTML;
// Lock button
button.disabled = true;
button.innerHTML = '<i class="fas fa-spinner fa-spin me-2"></i>Processing...';
button.classList.add('opacity-75');
// Unlock after 3 seconds
setTimeout(() => {
button.disabled = false;
button.innerHTML = originalHTML;
button.classList.remove('opacity-75');
}, 3000);
}
// Initialize on page load
document.addEventListener('DOMContentLoaded', () => {
attachButtonLockHandlers();
});
<!-- Standard button - will auto-lock -->
<button class="btn btn-primary">
<i class="fas fa-save me-1"></i>Save
</button>
<!-- Button that should NOT lock -->
<button class="btn btn-secondary" data-no-lock>
<i class="fas fa-times"></i>Cancel
</button>
Important:
data-no-lock attribute<meta name="viewport" content="width=device-width, initial-scale=1.0">.container or .container-fluid.col-md-6, .col-lg-4, etc..img-fluid class with lazy loading.navbar-expand-lg, .navbar-toggler.table-responsive for mobile<style> tagaria-label to icon-only buttons.fa-lg, .fa-xl)loading="lazy" on images| Problem | Solution |
|---|---|
| Inconsistent column widths | Use .col-12 for xs, then .col-md-6, .col-lg-4 for larger screens |
| Layout breaks on large screens | Use .container (max-width) instead of .container-fluid |
| Text too small on mobile | Use responsive font sizes, add mobile padding |
| Images stretched | Always use .img-fluid + lazy loading |
| Gaps between cards missing | Use g-* classes: <div class="row g-4"> |
| Icons look tiny | Use .fa-lg, .fa-xl, .fa-2x classes |
| Dark mode not working | Ensure data-bs-theme on <html> root |
| Theme not persisting | Use localStorage.setItem('theme', newTheme) |
| Button lock not working | Attach listener after DOM ready |
| Status bar not at bottom | Use d-flex flex-column on body with min-height: 100vh |
When providing code:
loading="lazy" and decoding="async"Remember: Focus on clean, semantic HTML, proper Bootstrap patterns, and modern UI/UX features. For data features, reference data-features-with-faker. For SEO, reference seo-optimization.