Skip to content

System, Light and Dark Theme Dropdown

Accessible Tailwind CSS dropdown to choose a light, dark or system theme, with live OS sync, saved preference and CSS variable tokens.

Also known as: dark mode toggle, theme switcher dropdown, light dark system theme, color scheme picker

System, Light and Dark Theme Dropdown live demo

Open in new tab

Tailwind CSS code (HTML, CSS, JS)

A theme picker dropdown built with Tailwind CSS and vanilla JavaScript that lets users choose Light, Dark or System, the three-way switch found in most modern apps and documentation sites. It is shown inside a small notes app so you can see every surface, border and text color change with the selection.

How it works

The root is .tsd-theme. All colors in the markup use arbitrary values such as bg-[var(--tsd-surface)] and text-[var(--tsd-muted)], and style.css defines those custom properties twice: once on .tsd-theme and once on .tsd-theme[data-tsd-theme="dark"]. Switching the theme is therefore a single attribute change, with no dark: variants or Tailwind configuration needed.

The trigger is button.tsd-trigger with aria-haspopup="menu". It shows the icon of the current mode (data-tsd-icon) and its name (data-tsd-label). The #tsd-menu list has role="menu" and three menuitemradio buttons, each carrying data-tsd-value. The check mark and accent icon of the chosen item are driven by group-aria-checked: variants, so the script only sets aria-checked.

On DOMContentLoaded the script reads the saved choice from localStorage (inside try/catch, so it also works where storage is blocked), falls back to data-tsd-mode and calls apply(). In System mode it resolves the theme with matchMedia('(prefers-color-scheme: dark)') and listens for its change event, so the component follows the OS live. The System item's data-tsd-hint shows what the device currently prefers.

Customization

  • --tsd-accent, --tsd-surface and the other tokens in style.css: set your own palette for the light and the [data-tsd-theme="dark"] block.
  • data-tsd-mode on .tsd-theme: change the default from system to light or dark for first-time visitors.
  • Add data-tsd-global to .tsd-theme: the script also toggles the dark class and color-scheme on the html element, so the whole page can follow the choice.
  • STORAGE_KEY in script.js: rename the saved key, or share one key between several pickers.
  • w-60 and right-0 on #tsd-menu: change the menu width or align it to the left edge with left-0.
  • transition-duration: 0.25s in style.css: speed up or slow down the color crossfade.

Use cases

  • Documentation sites: visitors pick light, dark or system theme from a small dropdown menu
  • Web apps: the choice is saved and the interface follows the operating system live in system mode
  • Settings pages: a notes-style demo shows every surface, border and text color changing together
  • Design systems: colors come from CSS variable tokens, so switching needs just one attribute

Accessibility

The trigger exposes aria-haspopup="menu", aria-controls and a live aria-expanded state, plus a visually hidden "Theme:" prefix. Menu items use role="menuitemradio" with aria-checked, so screen readers announce the selected option. Enter, Space, Arrow Down or Arrow Up opens the menu and focuses the current option; Arrow keys, Home and End move between items; Escape closes and returns focus to the trigger; Tab closes the menu and continues; a click outside closes it. Each change is announced through a role="status" region. Focus rings use the accent color, and transitions and the menu animation are removed under prefers-reduced-motion: reduce.

Usage notes

To avoid a flash of the wrong theme on full pages, run the same storage and matchMedia check in a tiny inline script in the head before the page renders.

System, Light and Dark Theme Dropdown at a glance

Framework
Tailwind CSS
Code
HTML, CSS, JavaScript
JavaScript
Vanilla JavaScript, no jQuery
Dependencies
Tailwind CSS
Layout
Responsive, works on mobile
Category
Theme Toggles
License
Free for personal and commercial use

Questions about this template

Can I use the System, Light and Dark Theme Dropdown code for free?

Yes. You can copy or download the code and use it in personal and commercial projects, including client work. No sign-up is needed. Reselling it as part of a component library or template collection is not allowed; see the license.

How do I add it to my website?

Load Tailwind CSS from a CDN (the links are under Requirements). Paste the HTML where the component should appear, add the CSS to your stylesheet and load the JavaScript before the closing </body> tag. Download HTML gives you a complete page with everything already linked.

Does it need jQuery or a JavaScript framework?

No. The script is plain vanilla JavaScript, so it works without jQuery, React or Vue. You can still use the markup inside those frameworks.

Does it work on mobile?

Yes. The layout adapts to small screens. Use the Mobile and Tablet buttons above the live demo to check it at phone and tablet width.

Requirements

Add these to your page (already included in the download):

  • <script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>

The Tailwind browser build is for prototyping. In production, compile Tailwind with its CLI or your bundler.

System, Light and Dark Theme Dropdown – Tailwind CSS theme toggles component screenshot
System, Light and Dark Theme Dropdown · Tailwind CSS Theme Toggles

More Theme Toggles

Light/Dark Theme Toggle – Tailwind CSS theme toggles preview

Light/Dark Theme Toggle

Tailwind CSS dark mode toggle with an animated sun/moon switch that follows the system preference, remembers the choice and can reset to system.