Bootstrap 5 Tutorial
v5.3.0Bootstrap 5 Tutorial
Admin Dashboard Project
Project Goal: Create a comprehensive admin dashboard for managing web applications with charts, tables, and widgets.
Project Overview
This project demonstrates how to build a professional admin dashboard using Bootstrap 5. The dashboard includes sidebar navigation, statistics cards, charts, data tables, and user management interface.
Dashboard Sections
- Responsive sidebar navigation
- Top navigation bar
- Statistics cards with icons
- Charts and graphs section
- Data tables with sorting
- User management interface
- Activity timeline
- Quick settings panel
Key Features
- Dark/Light theme toggle
- Responsive sidebar collapse
- Interactive charts
- Searchable data tables
- Notification system
- User profile dropdown
- Breadcrumb navigation
- Modal dialogs
Complete Dashboard Structure
HTML Layout
<!-- Dashboard Container -->
<div class="dashboard-container">
<!-- Sidebar -->
<aside class="sidebar bg-dark text-white">
<div class="sidebar-header p-3">
<h3 class="mb-0">
<i class="fas fa-tachometer-alt me-2"></i>
Dashboard<span class="badge bg-primary ms-2">Pro</span>
</h3>
<button class="btn btn-sm btn-outline-light mt-2 d-lg-none" id="sidebarToggle">
<i class="fas fa-bars"></i>
</button>
</div>
<nav class="sidebar-nav">
<ul class="nav flex-column">
<li class="nav-item">
<a class="nav-link active" href="#">
<i class="fas fa-home me-2"></i> Dashboard
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">
<i class="fas fa-users me-2"></i> Users
<span class="badge bg-primary rounded-pill float-end">24</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">
<i class="fas fa-chart-bar me-2"></i> Analytics
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">
<i class="fas fa-shopping-cart me-2"></i> Orders
<span class="badge bg-success rounded-pill float-end">42</span>
</a>
</li>
<li class="nav-item">
<a class="nav-link" href="#">
<i class="fas fa-cog me-2"></i> Settings
</a>
</li>
</ul>
<div class="sidebar-footer mt-auto p-3">
<div class="d-flex align-items-center">
<img src="https://via.placeholder.com/40" class="rounded-circle me-2" alt="Admin">
<div>
<h6 class="mb-0">John Doe</h6>
<small class="text-white-50">Administrator</small>
</div>
<button class="btn btn-sm btn-outline-light ms-auto">
<i class="fas fa-sign-out-alt"></i>
</button>
</div>
</div>
</nav>
</aside>
<!-- Main Content -->
<main class="main-content">
<!-- Top Navigation -->
<nav class="top-nav navbar navbar-expand-lg navbar-light bg-white border-bottom">
<div class="container-fluid">
<div class="d-flex align-items-center">
<button class="btn btn-light me-3 d-none d-lg-block" id="sidebarCollapse">
<i class="fas fa-bars"></i>
</button>
<ol class="breadcrumb mb-0">
<li class="breadcrumb-item"><a href="#">Home</a></li>
<li class="breadcrumb-item active">Dashboard</li>
</ol>
</div>
<div class="d-flex align-items-center">
<!-- Search -->
<form class="d-none d-md-flex me-3">
<div class="input-group">
<input type="text" class="form-control" placeholder="Search...">
<button class="btn btn-outline-secondary" type="button">
<i class="fas fa-search"></i>
</button>
</div>
</form>
<!-- Notifications -->
<div class="dropdown me-3">
<button class="btn btn-light position-relative" type="button" data-bs-toggle="dropdown">
<i class="fas fa-bell"></i>
<span class="position-absolute top-0 start-100 translate-middle badge rounded-pill bg-danger">
3
</span>
</button>
<div class="dropdown-menu dropdown-menu-end">
<h6 class="dropdown-header">Notifications</h6>
<a class="dropdown-item" href="#">New user registered</a>
<a class="dropdown-item" href="#">Order #12345 completed</a>
<a class="dropdown-item" href="#">System update available</a>
</div>
</div>
<!-- Theme Toggle -->
<button class="btn btn-light me-3" id="themeToggle">
<i class="fas fa-moon"></i>
</button>
<!-- User Dropdown -->
<div class="dropdown">
<button class="btn btn-light dropdown-toggle" type="button" data-bs-toggle="dropdown">
<img src="https://via.placeholder.com/30" class="rounded-circle me-2" alt="User">
John Doe
</button>
<div class="dropdown-menu dropdown-menu-end">
<a class="dropdown-item" href="#"><i class="fas fa-user me-2"></i> Profile</a>
<a class="dropdown-item" href="#"><i class="fas fa-cog me-2"></i> Settings</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="#"><i class="fas fa-sign-out-alt me-2"></i> Logout</a>
</div>
</div>
</div>
</div>
</nav>
<!-- Content Area -->
<div class="content-area p-4">
<!-- Page Header -->
<div class="d-flex justify-content-between align-items-center mb-4">
<h1 class="h3 mb-0">Dashboard Overview</h1>
<div class="btn-group">
<button class="btn btn-primary">
<i class="fas fa-plus me-2"></i> Add New
</button>
<button class="btn btn-outline-primary">
<i class="fas fa-download me-2"></i> Export
</button>
</div>
</div>
<!-- Statistics Cards -->
<div class="row mb-4">
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-start border-primary border-4">
<div class="card-body">
<div class="d-flex justify-content-between">
<div>
<h6 class="text-muted">Total Users</h6>
<h3 class="mb-0">2,548</h3>
</div>
<div class="avatar bg-primary text-white p-3 rounded-circle">
<i class="fas fa-users fa-2x"></i>
</div>
</div>
<p class="text-success mt-3 mb-0">
<i class="fas fa-arrow-up me-1"></i> 12.5% since last month
</p>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-start border-success border-4">
<div class="card-body">
<div class="d-flex justify-content-between">
<div>
<h6 class="text-muted">Revenue</h6>
<h3 class="mb-0">$24,856</h3>
</div>
<div class="avatar bg-success text-white p-3 rounded-circle">
<i class="fas fa-dollar-sign fa-2x"></i>
</div>
</div>
<p class="text-success mt-3 mb-0">
<i class="fas fa-arrow-up me-1"></i> 8.3% since last month
</p>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-start border-warning border-4">
<div class="card-body">
<div class="d-flex justify-content-between">
<div>
<h6 class="text-muted">Orders</h6>
<h3 class="mb-0">1,243</h3>
</div>
<div class="avatar bg-warning text-white p-3 rounded-circle">
<i class="fas fa-shopping-cart fa-2x"></i>
</div>
</div>
<p class="text-danger mt-3 mb-0">
<i class="fas fa-arrow-down me-1"></i> 3.2% since last month
</p>
</div>
</div>
</div>
<div class="col-xl-3 col-md-6 mb-4">
<div class="card border-start border-info border-4">
<div class="card-body">
<div class="d-flex justify-content-between">
<div>
<h6 class="text-muted">Conversion Rate</h6>
<h3 class="mb-0">4.8%</h3>
</div>
<div class="avatar bg-info text-white p-3 rounded-circle">
<i class="fas fa-chart-line fa-2x"></i>
</div>
</div>
<p class="text-success mt-3 mb-0">
<i class="fas fa-arrow-up me-1"></i> 1.7% since last month
</p>
</div>
</div>
</div>
</div>
<!-- Charts Section -->
<div class="row mb-4">
<div class="col-xl-8 mb-4">
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">Revenue Overview</h5>
</div>
<div class="card-body">
<div class="chart-container" style="height: 300px;">
<!-- Chart would be inserted here -->
<div class="text-center py-5 border rounded bg-light">
<i class="fas fa-chart-line fa-3x text-muted mb-3"></i>
<p class="text-muted">Revenue Chart Area</p>
</div>
</div>
</div>
</div>
</div>
<div class="col-xl-4 mb-4">
<div class="card">
<div class="card-header">
<h5 class="card-title mb-0">Traffic Sources</h5>
</div>
<div class="card-body">
<div class="chart-container" style="height: 300px;">
<!-- Pie chart would be inserted here -->
<div class="text-center py-5 border rounded bg-light">
<i class="fas fa-chart-pie fa-3x text-muted mb-3"></i>
<p class="text-muted">Traffic Sources Chart</p>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Data Table -->
<div class="card">
<div class="card-header d-flex justify-content-between align-items-center">
<h5 class="card-title mb-0">Recent Orders</h5>
<div class="input-group" style="width: 250px;">
<input type="text" class="form-control" placeholder="Search orders...">
<button class="btn btn-outline-secondary" type="button">
<i class="fas fa-search"></i>
</button>
</div>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>Order ID</th>
<th>Customer</th>
<th>Date</th>
<th>Amount</th>
<th>Status</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
<tr>
<td>#ORD-001</td>
<td>John Smith</td>
<td>2024-01-15</td>
<td>$245.99</td>
<td><span class="badge bg-success">Completed</span></td>
<td>
<button class="btn btn-sm btn-outline-primary">
<i class="fas fa-eye"></i>
</button>
<button class="btn btn-sm btn-outline-danger ms-1">
<i class="fas fa-trash"></i>
</button>
</td>
</tr>
<tr>
<td>#ORD-002</td>
<td>Emma Johnson</td>
<td>2024-01-14</td>
<td>$89.50</td>
<td><span class="badge bg-warning">Pending</span></td>
<td>
<button class="btn btn-sm btn-outline-primary">
<i class="fas fa-eye"></i>
</button>
<button class="btn btn-sm btn-outline-danger ms-1">
<i class="fas fa-trash"></i>
</button>
</td>
</tr>
<!-- More rows would be here -->
</tbody>
</table>
</div>
<!-- Pagination -->
<nav class="mt-3">
<ul class="pagination justify-content-center">
<li class="page-item disabled">
<a class="page-link" href="#">Previous</a>
</li>
<li class="page-item active"><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>
</div>
</div>
</div>
</main>
</div>Dashboard Layout CSS
Custom Dashboard Styling
/* Dashboard Layout Styles */
.dashboard-container {
display: flex;
min-height: 100vh;
background-color: #f8f9fa;
}
/* Sidebar Styles */
.sidebar {
width: 250px;
min-height: 100vh;
display: flex;
flex-direction: column;
transition: all 0.3s ease;
}
.sidebar.collapsed {
width: 70px;
}
.sidebar.collapsed .sidebar-header h3 span,
.sidebar.collapsed .nav-link span:not(.badge) {
display: none;
}
.sidebar-header {
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.sidebar-nav {
flex: 1;
overflow-y: auto;
padding: 1rem 0;
}
.nav-link {
color: rgba(255, 255, 255, 0.8);
padding: 0.75rem 1.5rem;
border-left: 3px solid transparent;
transition: all 0.2s ease;
}
.nav-link:hover {
color: white;
background-color: rgba(255, 255, 255, 0.1);
border-left-color: #0d6efd;
}
.nav-link.active {
color: white;
background-color: rgba(255, 255, 255, 0.15);
border-left-color: #0d6efd;
}
.sidebar-footer {
border-top: 1px solid rgba(255, 255, 255, 0.1);
}
/* Main Content Area */
.main-content {
flex: 1;
display: flex;
flex-direction: column;
}
.top-nav {
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
z-index: 1000;
}
.content-area {
flex: 1;
overflow-y: auto;
}
/* Statistics Cards */
.avatar {
width: 60px;
height: 60px;
display: flex;
align-items: center;
justify-content: center;
}
.card.border-start {
border-left-width: 4px !important;
}
/* Table Styling */
.table-hover tbody tr:hover {
background-color: rgba(0, 0, 0, 0.02);
}
/* Responsive Design */
@media (max-width: 992px) {
.sidebar {
position: fixed;
left: -250px;
z-index: 1050;
}
.sidebar.show {
left: 0;
}
.main-content {
margin-left: 0;
}
.content-area {
padding: 1rem;
}
}
/* Dark Theme */
.dark-theme {
background-color: #212529;
color: #f8f9fa;
}
.dark-theme .card {
background-color: #2d3748;
border-color: #4a5568;
}
.dark-theme .table {
color: #f8f9fa;
}
.dark-theme .table-hover tbody tr:hover {
background-color: rgba(255, 255, 255, 0.05);
}
/* Animation Classes */
.fade-in {
animation: fadeIn 0.3s ease-in;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* Scrollbar Styling */
.sidebar-nav::-webkit-scrollbar {
width: 5px;
}
.sidebar-nav::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.1);
}
.sidebar-nav::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.3);
border-radius: 3px;
}
.content-area::-webkit-scrollbar {
width: 8px;
}
.content-area::-webkit-scrollbar-track {
background: #f1f1f1;
}
.content-area::-webkit-scrollbar-thumb {
background: #888;
border-radius: 4px;
}
.content-area::-webkit-scrollbar-thumb:hover {
background: #555;
}JavaScript Functionality
Interactive Features
// Dashboard JavaScript Functionality
document.addEventListener('DOMContentLoaded', function() {
// Sidebar Toggle
const sidebar = document.querySelector('.sidebar');
const sidebarToggle = document.getElementById('sidebarToggle');
const sidebarCollapse = document.getElementById('sidebarCollapse');
if (sidebarToggle) {
sidebarToggle.addEventListener('click', function() {
sidebar.classList.toggle('show');
});
}
if (sidebarCollapse) {
sidebarCollapse.addEventListener('click', function() {
sidebar.classList.toggle('collapsed');
});
}
// Theme Toggle
const themeToggle = document.getElementById('themeToggle');
const themeIcon = themeToggle?.querySelector('i');
if (themeToggle) {
themeToggle.addEventListener('click', function() {
document.body.classList.toggle('dark-theme');
if (document.body.classList.contains('dark-theme')) {
themeIcon?.classList.remove('fa-moon');
themeIcon?.classList.add('fa-sun');
localStorage.setItem('theme', 'dark');
} else {
themeIcon?.classList.remove('fa-sun');
themeIcon?.classList.add('fa-moon');
localStorage.setItem('theme', 'light');
}
});
}
// Load saved theme
const savedTheme = localStorage.getItem('theme');
if (savedTheme === 'dark') {
document.body.classList.add('dark-theme');
if (themeIcon) {
themeIcon.classList.remove('fa-moon');
themeIcon.classList.add('fa-sun');
}
}
// Table Row Click Actions
const tableRows = document.querySelectorAll('.table-hover tbody tr');
tableRows.forEach(row => {
row.addEventListener('click', function(e) {
if (!e.target.closest('button')) {
const orderId = this.cells[0].textContent;
alert(`Viewing details for order: ${orderId}`);
}
});
});
// Modal Example
const viewButtons = document.querySelectorAll('.btn-outline-primary');
viewButtons.forEach(button => {
button.addEventListener('click', function() {
// Open modal with details
const modal = new bootstrap.Modal(document.getElementById('detailsModal'));
modal.show();
});
});
// Search Functionality
const searchInput = document.querySelector('.input-group input');
if (searchInput) {
searchInput.addEventListener('input', function() {
const searchTerm = this.value.toLowerCase();
const rows = document.querySelectorAll('.table tbody tr');
rows.forEach(row => {
const text = row.textContent.toLowerCase();
row.style.display = text.includes(searchTerm) ? '' : 'none';
});
});
}
// Notification Mark as Read
const notificationItems = document.querySelectorAll('.dropdown-item');
notificationItems.forEach(item => {
item.addEventListener('click', function() {
const badge = document.querySelector('.badge.bg-danger');
if (badge) {
const count = parseInt(badge.textContent);
if (count > 1) {
badge.textContent = count - 1;
} else {
badge.remove();
}
}
});
});
// Initialize Bootstrap Tooltips
const tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
tooltipTriggerList.map(function(tooltipTriggerEl) {
return new bootstrap.Tooltip(tooltipTriggerEl);
});
// Initialize Bootstrap Popovers
const popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'));
popoverTriggerList.map(function(popoverTriggerEl) {
return new bootstrap.Popover(popoverTriggerEl);
});
// Chart Integration Example (using Chart.js)
function initializeCharts() {
// Revenue Chart
const revenueCtx = document.getElementById('revenueChart');
if (revenueCtx) {
new Chart(revenueCtx, {
type: 'line',
data: {
labels: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun'],
datasets: [{
label: 'Revenue',
data: [12000, 19000, 15000, 25000, 22000, 30000],
borderColor: '#0d6efd',
backgroundColor: 'rgba(13, 110, 253, 0.1)',
fill: true
}]
},
options: {
responsive: true,
maintainAspectRatio: false
}
});
}
// Traffic Sources Chart
const trafficCtx = document.getElementById('trafficChart');
if (trafficCtx) {
new Chart(trafficCtx, {
type: 'doughnut',
data: {
labels: ['Direct', 'Social', 'Referral', 'Organic'],
datasets: [{
data: [40, 25, 20, 15],
backgroundColor: [
'#0d6efd',
'#20c997',
'#fd7e14',
'#6f42c1'
]
}]
},
options: {
responsive: true,
maintainAspectRatio: false
}
});
}
}
// Initialize charts when Chart.js is loaded
if (typeof Chart !== 'undefined') {
initializeCharts();
}
});
// Export Data Functionality
function exportData(format) {
const data = {
format: format,
timestamp: new Date().toISOString(),
data: 'Sample export data'
};
console.log(`Exporting data as ${format}`, data);
alert(`Data exported as ${format.toUpperCase()}`);
}
// Refresh Dashboard
function refreshDashboard() {
location.reload();
}
// Print Report
function printReport() {
window.print();
}Dashboard Components Overview
| Component | Purpose | Features |
|---|---|---|
| Sidebar Navigation | Primary navigation menu | Collapsible, responsive, active state highlighting |
| Top Navigation | Secondary controls and user menu | Search, notifications, theme toggle, user dropdown |
| Statistics Cards | Display key metrics | Icons, trend indicators, color-coded borders |
| Charts Section | Visual data representation | Line charts, pie charts, responsive containers |
| Data Tables | Display and manage data | Search, pagination, hover effects, action buttons |
| Breadcrumb | Navigation hierarchy | Shows current location in site structure |
| Modals | Detail views and forms | Popup dialogs for CRUD operations |
| Theme System | Light/Dark mode | Toggle switch, persistent preference |
Responsive Design Strategy
Mobile View
- Sidebar becomes off-canvas
- Statistics cards stack vertically
- Search moves to mobile menu
- Tables become horizontally scrollable
Tablet View
- Sidebar remains fixed but narrow
- Two-column layout for statistics
- Charts adjust to available space
- Full table view with scroll
Desktop View
- Full sidebar navigation
- Four-column statistics grid
- Side-by-side charts
- Full-featured table with all columns
Integration with Backend
API Integration Points
- Statistics: Fetch real-time data from analytics API
- Charts: Use Chart.js with API data
- Tables: Implement server-side pagination and search
- Notifications: WebSocket for real-time updates
- User Management: CRUD operations via REST API
- Export: Generate and download reports
Performance Considerations
Optimization Tips
- Lazy load charts and heavy components
- Implement virtual scrolling for large tables
- Cache frequently accessed data
- Use CDN for libraries (Chart.js, Bootstrap)
- Minimize API calls with proper caching
- Compress images and assets
- Implement code splitting for different dashboard sections