Img Alt Text

How To: Build a pure HTML/CSS Theme Switcher

CSS

Switching between light and dark themes is a common feature in modern web applications. While many implementations rely on JavaScript, you can achieve this functionality purely with HTML and CSS. This guide walks you through building a theme switcher with just HTML and CSS using a hidden checkbox and the CSS :has() pseudo-class.

Step 1: The HTML Structure

The HTML structure for the theme switcher includes a hidden checkbox, a label styled as a toggle, and some content to demonstrate the theme change.

<div class="content">
  <!-- Start theme toggle -->
  <!-- Hidden checkbox for toggling theme -->
  <input type="checkbox" id="theme-toggle">
  <!-- Toggle label, the part we see -->
  <label for="theme-toggle" class="toggle-label"></label>
  <!-- End theme toggler -->
  <!-- Content -->
  <h1>Click the Toggle</h1>
  <p>to change between light and dark modes.</p>
  <button>Example button</button>
</div>

Key Points:

  1. The input checkbox is hidden from view (display: none) but serves as the control for the toggle.
  2. The label element is styled to resemble a switch and toggles the checkbox state when clicked.

Step 2: The CSS Styling

The CSS handles: 1. The base styles (light theme). 2. The appearance of the toggle. 3. The dark theme styles applied when the checkbox is checked.

/* Base styles for light theme */
body {
  font-family: Arial, sans-serif;
  background-color: #ffffff;
  color: #333333;
  transition: background-color 0.3s ease, color 0.3s ease;
}
/* Center content */
.content {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: 20px;
}
button {
  background-color: #333333;
  color: #fff;
  border: 1px solid #f0f0f0;
  border-radius: 8px;
  height: 40px;
  cursor: pointer;
}
button:hover {
  background-color: #d0b5dd;
  color: #333333;
}
/* Hidden checkbox */
#theme-toggle {
  display: none;
}
/* Toggle label */
.toggle-label {
  cursor: pointer;
  width: 60px;
  height: 30px;
  background-color: #ccc;
  border-radius: 30px;
  position: relative;
  transition: background-color 0.3s ease;
}
/* Circle inside the toggle */
.toggle-label::after {
  content: "";
  width: 26px;
  height: 26px;
  background-color: yellow;
  border-radius: 50%;
  position: absolute;
  top: 2px;
  left: 2px;
  transition: transform 0.3s ease;
}
/* Dark theme styles */
body:has(#theme-toggle:checked) {
  background-color: #333333;
  color: #ffffff;
}
body:has(#theme-toggle:checked) .toggle-label::after {
  background-color: #4b89e6;
}
body:has(#theme-toggle:checked) .toggle-label {
  background-color: #666;
}
body:has(#theme-toggle:checked) button {
  background-color: #fff;
  color: #333333;
}
body:has(#theme-toggle:checked) button:hover {
  background-color: #b5ddc1;
  color: #333333;
}
body:has(#theme-toggle:checked) .toggle-label::after {
  transform: translateX(30px);
}

Explanation:

  1. Base Styles: Define the default light theme.
  2. Transition Effects: Smoothly animate theme changes using transition.
  3. Dark Theme: Utilize :has() to apply styles when the checkbox is checked.

Step 3: How It Works

  • The hidden checkbox (#theme-toggle) toggles its state when the label is clicked.
  • The :has() pseudo-class detects when the checkbox is checked and applies the dark theme styles to the body.
  • All transitions ensure the theme change is smooth and visually appealing.

Demo and Customization

You can experiment with the toggle styles by adjusting the label and ::after pseudo-element. For example: - Change the size of the toggle by modifying the width and height of .toggle-label. - Customize the dark theme colors to suit your design needs.

Conclusion

Creating a theme switcher with just HTML and CSS is a great way to keep your codebase simple and efficient. By leveraging modern CSS features like :has(), you can achieve powerful interactions without JavaScript. Feel free to customize this implementation to fit your project’s aesthetic and functionality!