Dark Mode
DarkMode is a standalone dark mode manager that handles theme switching,
persistent state, system preference sync, and custom toggle support.
The theme is applied through the fa-theme="dark" attribute on the root element —
the CSS handles visual output while DarkMode manages interaction and storage automatically.
DarkMode is suited for any application that needs a reliable, accessible, and React-compatible dark mode system without third-party dependencies.
Getting Started
Import DarkMode and create an instance. By default, a toggle button is
auto-created and appended to body.
import {DarkMode} from 'frontalign';
const darkMode = new DarkMode();
After the instance is created, DarkMode restores the saved theme from localStorage,
syncs with the system preference if no saved value exists, and activates the toggle button.
Structure
DarkMode applies the theme directly to document.documentElement using a data attribute.
| Element | Class / attribute | Purpose |
|---|---|---|
| Root | document.documentElement | Receives the fa-theme="dark" attribute when dark mode is active. |
| Theme attribute | fa-theme="dark" | Marks dark mode as active on the HTML root element. |
| Toggle button | dark-mode-toggler | Auto-created label element that wraps the checkbox input and icon track. |
| Fixed modifier | is-fixed | Positions the auto-created toggle button in a fixed corner when container is body. |
| Custom button state | is-dark | Applied to a custom toggle button when dark mode is active. |
| Storage key | darkMode | Key used in localStorage to persist the theme preference. |
Basic Example
const darkMode = new DarkMode({
container: '.darkmode-toggler-container',
autoCreateBtn: true,
});
This creates a toggle button appended to body and immediately restores
the saved or system-preferred theme.
Configuration Options
DarkMode accepts an options object in the constructor.
| Option | Default | Description |
|---|---|---|
container | 'body' | CSS selector for the element the auto-created toggle button is appended to. |
customBtn | false | CSS selector for an existing button element to use as the toggle trigger instead of the auto-created one. |
autoCreateBtn | true | When true, DarkMode creates and appends the default toggle button. Set to false when using a custom button. |
Custom Toggle Button
Set autoCreateBtn: false and pass a customBtn selector to wire
DarkMode to an existing element in your markup.
<button id="my-toggle">Toggle Dark Mode</button>
{
autoCreateBtn: false,
customBtn: '#my-toggle'
};
DarkMode adds the is-dark class to the custom button when dark mode is active
and removes it when switched back to light mode.
Custom Container
By default the auto-created toggle button is appended to body and positioned in a fixed corner.
Pass a container selector to mount it inside a specific element instead.
{
container: '#header-controls'
};
onChange Callback
Use onChange to run a function whenever the theme changes.
The callback receives a boolean: true for dark, false for light.
const darkMode = new DarkMode();
darkMode.onChange((isDark) => {
console.log(isDark ? 'Dark mode on' : 'Light mode on');
});
Multiple callbacks can be registered. All registered callbacks are called on each toggle.
darkModeChange Event
In addition to the onChange callback, DarkMode dispatches a native CustomEvent
on document.documentElement after every theme change.
| Event | Dispatched on | Detail |
|---|---|---|
darkModeChange | document.documentElement | |
document.documentElement.addEventListener('darkModeChange', (event) => {
console.log('Theme changed. Dark:', event.detail.isDark);
});
isDark Method
Call isDark() on the instance to read the current theme state at any time.
const darkMode = new DarkMode();
if (darkMode.isDark()) {
console.log('Currently in dark mode');
}
System Preference Sync
When no value is stored in localStorage, DarkMode automatically matches the system preference
via window.matchMedia('(prefers-color-scheme: dark)').
| Condition | Behavior |
|---|---|
| No saved preference | Applies the current system preference on initialization. |
| System preference changes | Follows the new system preference if no manual override is stored. |
| Saved preference exists | Ignores system preference changes and preserves the stored value. |
Once the user manually toggles the theme, localStorage is updated and system sync is paused.
Storage Behavior
DarkMode reads and writes to localStorage using the key darkMode.
| Stored value | Meaning |
|---|---|
"enabled" | Dark mode is explicitly enabled by the user. |
"disabled" | Light mode is explicitly set by the user. |
null | No manual preference — system preference is followed. |
Dispose
Call dispose() to remove all event listeners, the auto-created toggle button,
and all registered callbacks.
const darkMode = new DarkMode();
// Later, when cleanup is needed:
darkMode.dispose();
dispose() is required in environments where components are mounted and unmounted,
such as single-page applications and React components.
Runtime Behavior
| Behavior | Description |
|---|---|
| SSR safe | The constructor exits early when window or document is not available. |
| Theme attribute | Dark mode is toggled by setting or removing fa-theme="dark" on document.documentElement. |
| Persistence | Theme choice is written to localStorage on every toggle. |
| System sync | Follows prefers-color-scheme until the user makes a manual selection. |
| Custom event | Dispatches darkModeChange on the root element after every toggle. |
| Multiple callbacks | Any number of onChange listeners can be registered on a single instance. |
Accessibility
The auto-created toggle button uses a <label> wrapping a checkbox <input> with appropriate ARIA attributes.
- The input carries
role="switch"and anaria-label. - The label carries
aria-label="Dark Mode Toggle Button". - Sun and moon icons use
aria-hidden="true"to stay out of the accessibility tree.
When using a customBtn, add descriptive text or an accessible label to the button element yourself.
<button id="theme-toggle" aria-label="Toggle dark mode">
Dark Mode
</button>
Class Reference
| Class | Role |
|---|---|
dark-mode-toggler | Root label element wrapping the checkbox and icon track. |
is-fixed | Fixed-position modifier applied when container is body. |
dark-mode-toggler-track | The visual track element of the toggle button. |
dark-mode-toggler-thumb | The sliding thumb element inside the track. |
dark-mode-toggler-sun | Sun icon shown in light mode. |
dark-mode-toggler-moon | Moon icon shown in dark mode. |
is-dark | State class applied to the custom button when dark mode is active. |
Notes
- DarkMode requires no markup changes — only a JavaScript import.
- The
fa-theme="dark"attribute on<html>drives all CSS theming. - Call
dispose()when the instance is no longer needed to prevent memory leaks. - Use
autoCreateBtn: falsewhenever you supply acustomBtnselector. onChangecallbacks and thedarkModeChangeevent both fire on every toggle and on system preference changes when no saved value exists.- Use the React hook only in React or Next.js applications.
- Continue with the React Integration guide for provider setup and runtime helpers.