Sidebar Menu with Dark/Light Theme Toggle in HTML CSS & JavaScript

0

Sidebar Menu with DarkLight Theme Toggle in HTML CSS & JavaScript

Sidebars have become a key part of web layouts today. They help organize navigation links, settings, and other interactive elements without cluttering the main content area. A well-designed sidebar improves user experience and adds a polished, professional feel to your website.

In this tutorial, we’ll build a clean and responsive sidebar menu from scratch using HTML, CSS, and JavaScript. But we’re not stopping there, we’re also adding two interactive features that users love:

  • A toggle button to expand or collapse the sidebar.
  • A theme switcher that lets users switch between dark mode and light mode.

This sidebar is built entirely with vanilla HTML, CSS, and JavaScript. No frameworks or libraries required. So it’s perfect if you’re learning front-end development or want to improve your JavaScript skills with a hands-on project.

Why Build a Sidebar Menu with Dark/Light Themes?

If you’re working on a personal site, admin dashboard, or portfolio, this kind of sidebar is incredibly useful. Here’s why it’s a great beginner-friendly project:

  • JavaScript Practice: Learn how to manipulate DOM elements, add event listeners, and toggle classes dynamically.
  • Theme Switching: Implementing a theme switch helps you understand how CSS variables and JavaScript can work together for real-time style changes.
  • Responsive Layouts: You’ll practice media queries and CSS layout techniques like Flexbox to ensure the sidebar works on all screen sizes.
  • Real-World Application: Features like collapsible menus and dark mode are common in today’s apps. You’ll walk away with practical skills you can reuse in other projects.

Video Tutorial of Sidebar Menu with Dark/Light Themes in HTML, CSS & JavaScript

If you prefer learning by watching, check out the linked YouTube tutorial that walks you through each step with clear explanations and hands-on examples. You can follow along from start to finish or jump to sections you want to focus on.

If reading is more your style, just keep scrolling for a detailed step-by-step guide on building this responsive sidebar.

Steps to Create Sidebar Menu With Dark/Light Themes in HTML, CSS & JavaScript

To build your responsive card slider with HTML, CSS, and JavaScript (using SwiperJS), follow these easy steps:

  • Create Your Project Folder: Start by creating a new folder for your project. Name it something like card-slider.
  • Set Up Your Files: Inside the folder, create three files: index.htmlstyle.css, and script.js.
  • Add Images: Download the logo and place it in your project directory. Alternatively, you can use your own logo if preferred.

Paste the following HTML code into your index.html to create the sidebar layout. It includes a sidebar wrapped in <aside>, with a header, search box, navigation menu, and footer section. This structure keeps your layout clean, accessible, and easy to manage.

<!DOCTYPE html>
<!-- Coding By CodingNepal - youtube.com/@codingnepal -->
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Sidebar Menu | CodingNepal</title>
    <link rel="stylesheet" href="style.css" />
    <!-- Linking Google fonts for icons -->
    <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Rounded:opsz,wght,FILL,GRAD@24,400,0,0" />
  </head>
  <body>
    <!-- Navbar -->
    <nav class="site-nav">
      <button class="sidebar-toggle">
        <span class="material-symbols-rounded">menu</span>
      </button>
    </nav>

    <div class="container">
      <!-- Sidebar -->
      <aside class="sidebar collapsed">
        <!-- Sidebar header -->
        <div class="sidebar-header">
          <img src="logo.png" alt="CodingNepal" class="header-logo" />
          <button class="sidebar-toggle">
            <span class="material-symbols-rounded">chevron_left</span>
          </button>
        </div>

        <div class="sidebar-content">
          <!-- Search Form -->
          <form action="#" class="search-form">
            <span class="material-symbols-rounded">search</span>
            <input type="search" placeholder="Search..." required />
          </form>

          <!-- Sidebar Menu -->
          <ul class="menu-list">
            <li class="menu-item">
              <a href="#" class="menu-link active">
                <span class="material-symbols-rounded">dashboard</span>
                <span class="menu-label">Dashboard</span>
              </a>
            </li>
            <li class="menu-item">
              <a href="#" class="menu-link">
                <span class="material-symbols-rounded">insert_chart</span>
                <span class="menu-label">Analytics</span>
              </a>
            </li>
            <li class="menu-item">
              <a href="#" class="menu-link">
                <span class="material-symbols-rounded">notifications</span>
                <span class="menu-label">Notifications</span>
              </a>
            </li>
            <li class="menu-item">
              <a href="#" class="menu-link">
                <span class="material-symbols-rounded">star</span>
                <span class="menu-label">Favourites</span>
              </a>
            </li>
            <li class="menu-item">
              <a href="#" class="menu-link">
                <span class="material-symbols-rounded">storefront</span>
                <span class="menu-label">Products</span>
              </a>
            </li>
            <li class="menu-item">
              <a href="#" class="menu-link">
                <span class="material-symbols-rounded">group</span>
                <span class="menu-label">Customers</span>
              </a>
            </li>
            <li class="menu-item">
              <a href="#" class="menu-link">
                <span class="material-symbols-rounded">settings</span>
                <span class="menu-label">Settings</span>
              </a>
            </li>
          </ul>
        </div>

        <!-- Sidebar Footer -->
        <div class="sidebar-footer">
          <button class="theme-toggle">
            <div class="theme-label">
              <span class="theme-icon material-symbols-rounded">dark_mode</span>
              <span class="theme-text">Dark Mode</span>
            </div>
            <div class="theme-toggle-track">
              <div class="theme-toggle-indicator"></div>
            </div>
          </button>
        </div>
      </aside>

      <!-- Site main content -->
      <div class="main-content">
        <h1 class="page-title">Dashboard Overview</h1>
        <p class="card">Welcome to your dashboard! Use the menu to navigate, toggle the sidebar, or switch between light and dark themes to personalize your experience.</p>
      </div>
    </div>

    <script src="script.js"></script>
  </body>
</html>

Paste the following CSS code into your style.css to style the sidebar. It uses flexbox for layout, CSS variables for themes, and transitions for smooth animations. The styles also ensure responsiveness across devices.

/* Importing Google Fonts - Poppins */
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap');

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: "Poppins", sans-serif;
}

:root {
  /* Light theme colors */
  --color-text-primary: #1F2936;
  --color-text-placeholder: #798EAE;
  --color-bg-primary: #f9fafb;
  --color-bg-secondary: #ECECFD;
  --color-bg-sidebar: #FFFFFF;
  --color-border-hr: #E2E8F0;
  --color-hover-primary: #695CFE;
  --color-hover-secondary: #e2e2fb;
  --color-shadow: rgba(0, 0, 0, 0.05);
}

body.dark-theme {
  /* Dark theme colors */
  --color-text-primary: #F1F5F9;
  --color-text-placeholder: #A6B7D2;
  --color-bg-primary: #111827;
  --color-bg-secondary: #3D4859;
  --color-bg-sidebar: #1f2937;
  --color-border-hr: #3B475C;
  --color-hover-secondary: #48566a;
  --color-shadow: rgba(0, 0, 0, 0.3);
}

body {
  min-height: 100vh;
  background: var(--color-bg-primary);
}

.sidebar {
  position: sticky;
  top: 0;
  width: 270px;
  height: 100vh;
  display: flex;
  flex-shrink: 0;
  flex-direction: column;
  background: var(--color-bg-sidebar);
  border-right: 1px solid var(--color-border-hr);
  box-shadow: 0 3px 9px var(--color-shadow);
  transition: width 0.4s ease;
}

.sidebar.collapsed {
  width: 90px;
}

.sidebar .sidebar-header {
  padding: 20px 18px;
  display: flex;
  position: relative;
  align-items: center;
  justify-content: space-between;
  border-bottom: 1px solid var(--color-border-hr);
}

.sidebar-header .header-logo {
  width: 46px;
  height: 46px;
  display: block;
  object-fit: contain;
  border-radius: 50%;
  transition: opacity 0.4s ease;
}

.sidebar.collapsed .header-logo {
  opacity: 0;
  pointer-events: none;
}

.site-nav .sidebar-toggle,
.sidebar-header .sidebar-toggle {
  height: 40px;
  width: 40px;
  border: none;
  cursor: pointer;
  display: flex;
  position: absolute;
  right: 18px;
  align-items: center;
  justify-content: center;
  border-radius: 8px;
  color: var(--color-text-primary);
  background: var(--color-bg-secondary);
  transition: 0.4s ease;
}

.site-nav .sidebar-toggle:hover,
.sidebar-header .sidebar-toggle:hover {
  background: var(--color-hover-secondary);
}

.sidebar.collapsed .sidebar-header .sidebar-toggle {
  transform: translateX(-2px);
  height: 48px;
  width: 50px;
}

.sidebar-header .sidebar-toggle span {
  font-size: 1.75rem;
  transition: transform 0.4s ease;
}

.sidebar.collapsed .sidebar-toggle span {
  transform: rotate(180deg);
}

.sidebar .sidebar-content {
  flex: 1;
  padding: 20px 18px;
  overflow: hidden auto;
  scrollbar-width: thin;
  scrollbar-color: var(--color-text-placeholder) transparent;
}

.sidebar.collapsed .sidebar-content {
  scrollbar-width: none;
}

.sidebar-content .search-form {
  border-radius: 8px;
  min-height: 48px;
  margin: 5px 0 20px;
  align-items: center;
  display: flex;
  padding: 0 15px;
  white-space: nowrap;
  background: var(--color-bg-secondary);
  transition: 0.4s ease;
}

.sidebar.collapsed .search-form:hover {
  cursor: pointer;
}

.sidebar-content .search-form:focus-within,
.sidebar.collapsed .search-form:hover {
  background: var(--color-hover-secondary);
}

.sidebar-content .search-form span {
  color: var(--color-text-placeholder);
}

.search-form input {
  background: none;
  outline: none;
  border: none;
  width: 100%;
  margin-left: 15px;
  font-size: 1rem;
  color: var(--color-text-primary);
}

.search-form input::placeholder {
  color: var(--color-text-placeholder);
}

.sidebar-content .menu-list {
  display: flex;
  gap: 4px;
  list-style: none;
  flex-direction: column;
}

.menu-list .menu-link {
  display: flex;
  gap: 12px;
  white-space: nowrap;
  border-radius: 8px;
  padding: 12px 15px;
  align-items: center;
  text-decoration: none;
  color: var(--color-text-primary);
  transition: 0.3s ease;
}

.menu-link .menu-label {
  transition: opacity 0.3s ease;
}

.sidebar.collapsed .menu-link .menu-label {
  opacity: 0;
  pointer-events: none;
}

.menu-list .menu-link:is(:hover, .active) {
  color: #fff;
  background: var(--color-hover-primary);

}

.sidebar .sidebar-footer {
  padding: 20px 18px;
  white-space: nowrap;
  border-top: 1px solid var(--color-border-hr);
}

.sidebar-footer .theme-toggle {
  width: 100%;
  min-height: 48px;
  border-radius: 8px;
  display: flex;
  align-items: center;
  cursor: pointer;
  border: none;
  padding: 0 15px;
  white-space: nowrap;
  color: var(--color-text-primary);
  background: var(--color-bg-secondary);
  transition: 0.3s ease;
}

.sidebar-footer .theme-toggle:hover {
  background: var(--color-hover-secondary);
}

.theme-toggle .theme-label {
  display: flex;
  gap: 10px;
  align-items: center;
}

.theme-toggle .theme-label .theme-text {
  font-size: 1rem;
  transition: opacity 0.4s 0.2s ease;
}

.sidebar.collapsed .theme-toggle :where(.theme-text, .theme-toggle-track) {
  opacity: 0;
  width: 0;
  transition: all 0.2s ease;
}

.theme-toggle .theme-toggle-track {
  height: 24px;
  width: 48px;
  border-radius: 999px;
  margin-left: auto;
  background: #c3d1ec;
  position: relative;
  transition: opacity 0.4s 0.2s ease, background-color 0.3s ease;
}

body.dark-theme .theme-toggle-track {
  background: #695CFE;
}

.theme-toggle-track .theme-toggle-indicator {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background-color: #fff;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  transition: transform 0.3s ease;
}

body.dark-theme .theme-toggle-indicator {
  transform: translateX(24px);
}

.site-nav {
  top: 0;
  display: none;
  padding: 15px 20px;
  position: sticky;
  background: var(--color-bg-primary);
  border-bottom: 1px solid var(--color-border-hr);
}

.site-nav .sidebar-toggle {
  position: unset;
}

.container {
  display: flex;
}

.container .main-content {
  flex: 1;
  padding: 30px;
  color: var(--color-text-primary);
}

.main-content .page-title {
  font-size: 1.5rem;
  font-weight: 600;
  margin-bottom: 20px;
}

.main-content .card {
  border-radius: 8px;
  padding: 20px;
  background-color: var(--color-bg-sidebar);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

/* Responsive media query code for small screens */
@media (max-width: 768px) {
  body::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: 10;
    opacity: 0;
    pointer-events: none;
    background: rgba(0, 0, 0, 0.6);
    transition: 0.4s ease;
  }

  body:has(.sidebar:not(.collapsed))::before {
    opacity: 1;
    pointer-events: auto;
  }

  body:has(.sidebar:not(.collapsed)) {
    overflow: hidden;
  }

  .site-nav {
    display: block;
  }

  .sidebar {
    position: fixed;
    top: 0;
    left: 0;
    height: 100%;
    z-index: 20;
    width: 270px;
    transition: left 0.4s ease;
  }

  .sidebar.collapsed {
    left: -270px;
    width: 270px;
  }

  .container .main-content {
    padding: 30px 20px;
  }
}

Paste the following JavaScript code into your script.js to add sidebar functionality. It toggles dark mode, collapses the sidebar, and saves user preferences using localStorage. This makes your layout interactive and user-friendly.

const sidebarToggleBtns = document.querySelectorAll(".sidebar-toggle");
const sidebar = document.querySelector(".sidebar");
const searchForm = document.querySelector(".search-form");
const themeToggleBtn = document.querySelector(".theme-toggle");
const themeIcon = themeToggleBtn.querySelector(".theme-icon");
const menuLinks = document.querySelectorAll(".menu-link");

// Updates the theme icon based on current theme and sidebar state
const updateThemeIcon = () => {
  const isDark = document.body.classList.contains("dark-theme");
  themeIcon.textContent = sidebar.classList.contains("collapsed") ? (isDark ? "light_mode" : "dark_mode") : "dark_mode";
};

// Apply dark theme if saved or system prefers, then update icon
const savedTheme = localStorage.getItem("theme");
const systemPrefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
const shouldUseDarkTheme = savedTheme === "dark" || (!savedTheme && systemPrefersDark);

document.body.classList.toggle("dark-theme", shouldUseDarkTheme);
updateThemeIcon();

// Toggle between themes on theme button click
themeToggleBtn.addEventListener("click", () => {
  const isDark = document.body.classList.toggle("dark-theme");
  localStorage.setItem("theme", isDark ? "dark" : "light");
  updateThemeIcon();
});

// Toggle sidebar collapsed state on buttons click
sidebarToggleBtns.forEach((btn) => {
  btn.addEventListener("click", () => {
    sidebar.classList.toggle("collapsed");
    updateThemeIcon();
  });
});

// Expand the sidebar when the search form is clicked
searchForm.addEventListener("click", () => {
  if (sidebar.classList.contains("collapsed")) {
    sidebar.classList.remove("collapsed");
    searchForm.querySelector("input").focus();
  }
});

// Expand sidebar by default on large screens
if (window.innerWidth > 768) sidebar.classList.remove("collapsed");

If you put everything together correctly, opening your index.html file in a browser will let you test the sidebar menu. Play with collapsing and expanding it, and switching between dark and light modes.

Conclusion and Final Words

Building a responsive sidebar with a dark/light mode toggle in HTML, CSS, and JavaScript is a great hands-on project for any front-end developer. It combines layout, styling, and interactivity—all essential skills you’ll use in real-world projects.

If you want to take your sidebar skills further, check out my other blog post on creating a sidebar menu with dropdown menus. It dives into adding nested navigation and more complex interactions, perfect for building feature-rich sidebars.

If you encounter any issues while building your sidebar menu or if your code isn’t behaving as expected, don’t stress! You can download the source code for this sidebar menu project for free by clicking the download button below. Alternatively, you can check out a live demo of the card slider by clicking the “View Live” button.

Previous articleHow to Build a Gemini AI Chatbot in React.js and CSS | Step-By-Step Guide

LEAVE A REPLY

Please enter your comment!
Please enter your name here