Dark mode and color variants
Pico comes with two themes — light and dark — and by default picks between them itself, based on the visitor's system setting. A theme here is a set of colors for the background, text, borders and cards. Pico also has ready builds with different primary colors.
Automatic choice and data-theme
With no extra setup Pico follows the prefers-color-scheme media query from the tutorial: if the system uses dark mode, the page is dark too. To lock one theme, put the data-theme attribute on the <html> tag in index.html:
<!DOCTYPE html>
<html lang="en" data-theme="dark">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Anna's blog</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css">
</head>
<body>
<main class="container">
<h1>Anna's blog</h1>
</main>
</body>
</html>Open the file: the page is dark whatever the system setting. The value light locks the light theme, and without the attribute the automatic choice works again.
A theme switcher
A script can change the theme by rewriting data-theme on document.documentElement — that is the <html> tag:
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css">
<style>
body { background: var(--pico-background-color); color: var(--pico-color); }
</style>
<button id="theme-toggle" class="contrast">Dark theme</button>
<article>
<h4>A grid without media queries</h4>
<p>How auto-fit and minmax choose the number of columns.</p>
</article>
<script>
const root = document.documentElement;
const toggle = document.querySelector('#theme-toggle');
root.dataset.theme = 'light';
toggle.addEventListener('click', () => {
const isDark = root.dataset.theme === 'dark';
root.dataset.theme = isDark ? 'light' : 'dark';
toggle.textContent = isDark ? 'Dark theme' : 'Light theme';
console.log('Theme:', root.dataset.theme);
});
</script>Click the button: the background, text, card and the button itself change colors, and the theme name appears under the example. The body rule in <style> is needed only by the preview window, which paints <body> white itself; your own file can do without it. To keep the choice after a reload, save it to localStorage and read it when the page opens.
Color variants
The primary color — buttons, links, the focus ring — changes when you link a different build. The file name is pico. + color + .min.css.
| Colors | Example file |
|---|---|
| red, pink, fuchsia, purple, violet | pico.violet.min.css |
| indigo, blue, cyan, jade, green, lime | pico.jade.min.css |
| yellow, amber, pumpkin, orange | pico.amber.min.css |
| sand, grey, zinc, slate | pico.slate.min.css |
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.violet.min.css">
<p>New post: <a href="#">Forms without pain</a></p>
<button>Subscribe</button>
<button class="outline">Archive</button>The link and the buttons turned violet, and the rest of the styling stayed the same. The default blue is called azure and lives in the regular pico.min.css.
Common mistake
Linking two builds at once — say, pico.min.css and pico.violet.min.css — hoping to add a color to the main one. Each build contains the whole of Pico, so the second fully overrides the first and doubles the CSS size. Link exactly one Pico file.