usePreferredColorScheme
Tracks the user's light, dark, or no-preference color-scheme media setting.
About
usePreferredColorScheme subscribes to the light and dark prefers-color-scheme media queries. It returns a normalized scheme plus convenient light/dark booleans and updates when the operating-system preference changes.
Example
import { usePreferredColorScheme } from "rooks";
export default function ThemePreview() {
const preference = usePreferredColorScheme();
const dark = preference.isDark;
return (
<section
style={{
padding: 16,
background: dark ? "#171717" : "#ffffff",
color: dark ? "#ffffff" : "#171717",
border: "1px solid currentColor",
}}
>
Preferred scheme:{" "}
{preference.colorScheme ?? "unknown during server rendering"}
</section>
);
}Parameters
This hook accepts no parameters.
Return value
Returns an object with this inline shape:
| Field | Type | Meaning |
|---|---|---|
colorScheme | "light" | "dark" | "no-preference" | null | Normalized preference; null is the server snapshot. |
isDark | boolean | true only when colorScheme is "dark". |
isLight | boolean | true only when colorScheme is "light". |
The source module declares names for these shapes, but they are not type exports of the rooks package entrypoint.
Behavior and lifecycle
On the client, dark is checked first, then light; if neither query matches, the scheme is "no-preference". The hook subscribes to both query lists and removes both listeners on unmount. It uses modern change events when available and falls back to legacy addListener/removeListener methods.
The server snapshot is always null, with both booleans false. Hydration then reconciles to the browser preference, so avoid producing fundamentally different document structure from the initial value.
Compatibility and accessibility
Server rendering does not access window. The client requires window.matchMedia; unlike the listener method, that function itself has no fallback. The hook does not persist a user override, change the document theme, or edit CSS.
Treat the system preference as a default and, when appropriate, let users choose a persistent override. Ensure either color scheme retains sufficient contrast and does not communicate status through color alone. See SSR and browser APIs.
Related
- useMediaMatch accepts an arbitrary media query and a configurable server value.
- usePrefersReducedMotion tracks the motion accessibility preference.