mirror of
https://github.com/jgthms/bulma.git
synced 2024-12-12 13:28:30 +00:00
474 lines
16 KiB
Markdown
474 lines
16 KiB
Markdown
---
|
|
title: Dark Mode in Bulma
|
|
layout: docs
|
|
markdown: true
|
|
theme: features
|
|
doc-tab: features
|
|
doc-subtab: dark-mode
|
|
breadcrumb:
|
|
- home
|
|
- documentation
|
|
- features
|
|
- features-dark-mode
|
|
---
|
|
|
|
|
|
|
|
Modern browsers come with a way to detect if a user has set their theme preference to `light` or `dark` by using the [`prefers-color-scheme`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme) keyword.
|
|
|
|
This value can be used in a media query to change a website's styles accordingly:
|
|
|
|
```css
|
|
@media (prefers-color-scheme: dark) {
|
|
:root {
|
|
/* Update CSS variables */
|
|
}
|
|
}
|
|
```
|
|
|
|
However, it's not possible for a website to alter this preference. That's why it's preferable to **also** add a `data-theme` HTML attribute or a `theme-dark` CSS class.
|
|
|
|
This is how Bulma defines its dark theme:
|
|
|
|
```css
|
|
@media (prefers-color-scheme: dark) {
|
|
:root {
|
|
/* Update CSS variables */
|
|
}
|
|
}
|
|
|
|
[data-theme=dark],
|
|
.theme-dark {
|
|
/* Update CSS variables */
|
|
}
|
|
```
|
|
|
|
With these rules:
|
|
|
|
* the website will be **light by default**, if no user preference is set
|
|
* it will also be **light** if the user has set their preference to `light`
|
|
* the website will be **dark** if the user has set their preference to `dark`
|
|
|
|
{% include docs/elements/anchor.html name="Force Dark Mode within a page" %}
|
|
|
|
You can **enable** Dark Mode in part of your HTML by simply using the HTML attribute or the CSS class:
|
|
|
|
```html
|
|
<div>
|
|
This is in Light Mode if the user hasn't set a preference, or if their preference is set to <code>light</code>.
|
|
</div>
|
|
|
|
<div data-theme="dark">
|
|
This is in Dark Mode
|
|
</div>
|
|
|
|
<div class="theme-dark">
|
|
This is also in Dark Mode
|
|
</div>
|
|
```
|
|
|
|
{% include docs/elements/anchor.html name="Force Dark Mode for a whole webpage" %}
|
|
|
|
If you want to enable Dark Mode for a whole webpage, simply set the attribute or the class on the `<html>` element:
|
|
|
|
```html
|
|
<html data-theme="dark">
|
|
<!-- Or -->
|
|
<html class="theme-dark">
|
|
```
|
|
|
|
{% include docs/elements/anchor.html name="How the Dark theme is created" %}
|
|
|
|
This is the content of the `sass/themes/dark.scss` file:
|
|
|
|
```scss
|
|
@use "sass/utilities/initial-variables" as iv;
|
|
@use "sass/utilities/css-variables" as cv;
|
|
@use "sass/utilities/derived-variables" as dv;
|
|
@use "sass/themes/setup";
|
|
|
|
// The main lightness of this theme
|
|
$scheme-main-l: 11%;
|
|
$background-l: 14%;
|
|
$text-l: 71%;
|
|
|
|
// The main scheme color, used to make calculations
|
|
$scheme-main: hsl(iv.$scheme-h, iv.$scheme-s, $scheme-main-l);
|
|
$background: hsl(iv.$scheme-h, iv.$scheme-s, $background-l);
|
|
$text: hsl(iv.$scheme-h, iv.$scheme-s, $text-l);
|
|
|
|
@mixin dark-theme {
|
|
// Required: update the lightness colors and hover/active states
|
|
@include cv.register-vars(
|
|
(
|
|
"scheme-brightness": "dark",
|
|
"scheme-main-l": $scheme-main-l,
|
|
"scheme-main-bis-l": $scheme-main-l + 2%,
|
|
"scheme-main-ter-l": $scheme-main-l + 4%,
|
|
"background-l": $background-l,
|
|
"border-weak-l": 21%,
|
|
"border-l": 24%,
|
|
"text-weak-l": 53%,
|
|
"text-l": $text-l,
|
|
"text-strong-l": 93%,
|
|
"text-title-l": 100%,
|
|
"hover-background-l-delta": 5%,
|
|
"active-background-l-delta": 10%,
|
|
"hover-border-l-delta": 10%,
|
|
"active-border-l-delta": 20%,
|
|
"hover-color-l-delta": 5%,
|
|
"active-color-l-delta": 10%,
|
|
)
|
|
);
|
|
|
|
// Required: update the "on scheme" colors since the main scheme color is changed
|
|
// from white (100% lightness)
|
|
// to black (11% lightness in this case)
|
|
@each $name, $color in dv.$colors {
|
|
@include cv.generate-on-scheme-colors($name, $color, $scheme-main);
|
|
}
|
|
|
|
// Optional: update the shadow color
|
|
@include cv.register-hsl("shadow", white);
|
|
}
|
|
```
|
|
|
|
This mixin outputs a list of CSS variables and their new value.
|
|
|
|
To use this theme with the `prefer-color-scheme` media query, write the following:
|
|
|
|
```scss
|
|
@use "sass/utilities/css-variables" as cv;
|
|
@use "sass/themes/dark";
|
|
|
|
@include cv.system-theme($name: "dark") {
|
|
@include dark.dark-theme;
|
|
}
|
|
```
|
|
|
|
To use this theme with the `[data-theme=dark]` and `.theme-dark` selectors, write the following:
|
|
|
|
```scss
|
|
@use "sass/utilities/css-variables" as cv;
|
|
@use "sass/themes/dark";
|
|
@use "sass/themes/setup";
|
|
|
|
@include cv.bulma-theme($name: "dark") {
|
|
@include dark.dark-theme;
|
|
@include setup.setup-theme;
|
|
}
|
|
```
|
|
|
|
|
|
### The `bulma-theme()` mixin
|
|
|
|
This mixin will allow you to generate a CSS rule-set with both an appropriate HTML attribute selector and a CSS class selector, which names are defined by the `$name` parameter.
|
|
|
|
```scss
|
|
@use "sass/utilities/css-variables" as cv;
|
|
|
|
@include cv.bulma-theme($name: "my-theme") {
|
|
// Your code
|
|
}
|
|
```
|
|
|
|
This will output the following:
|
|
|
|
```css
|
|
[data-theme=my-theme],
|
|
.theme-my-theme {
|
|
/* Your code */
|
|
}
|
|
```
|
|
|
|
### The `system-theme()` mixin
|
|
|
|
This mixin will generate a `@media (prefers-color-scheme: $name)` media query.
|
|
|
|
```scss
|
|
@use "sass/utilities/css-variables" as cv;
|
|
|
|
@include cv.system-theme($name: "dark") {
|
|
// Your code
|
|
}
|
|
```
|
|
|
|
This will output the following:
|
|
|
|
```css
|
|
@media (prefers-color-scheme: dark) {
|
|
:root {
|
|
/* Your code */
|
|
}
|
|
}
|
|
```
|
|
|
|
### The `register-vars()` function
|
|
|
|
All Bulma CSS variables are prefixed with `bulma-`. This prefix is defined with the `$cssvars-prefix: "bulma-";` Sass variable.
|
|
|
|
Because writing all CSS variables with this prefix can be cumbersome, Bulma provides a Sass function to register new variables: `register-vars()`.
|
|
|
|
This function accepts a Sass map of `name: value` pairs.
|
|
|
|
```scss
|
|
@use "sass/utilities/css-variables" as cv;
|
|
|
|
$scheme-main-l: 11%;
|
|
$background-l: 14%;
|
|
$text-l: 71%;
|
|
|
|
@include cv.bulma-theme($name: "my-theme") {
|
|
@include cv.register-vars(
|
|
(
|
|
"scheme-brightness": "dark",
|
|
"scheme-main-l": $scheme-main-l,
|
|
"scheme-main-bis-l": $scheme-main-l + 2%,
|
|
"scheme-main-ter-l": $scheme-main-l + 4%,
|
|
"background-l": $background-l,
|
|
"border-weak-l": 21%,
|
|
"border-l": 24%,
|
|
"text-weak-l": 53%,
|
|
"text-l": $text-l,
|
|
"text-strong-l": 93%,
|
|
"text-title-l": 100%,
|
|
"hover-background-l-delta": 5%,
|
|
"active-background-l-delta": 10%,
|
|
"hover-border-l-delta": 10%,
|
|
"active-border-l-delta": 20%,
|
|
"hover-color-l-delta": 5%,
|
|
"active-color-l-delta": 10%,
|
|
)
|
|
);
|
|
}
|
|
```
|
|
|
|
### Updating the lightness
|
|
|
|
For Dark Mode, Bulma will keep the same hue and saturation of the main scheme color. It will however **invert the lightness** of background, borders, text colors, and hover/active states.
|
|
|
|
<table class="table is-bordered">
|
|
<thead>
|
|
<tr>
|
|
<th>Lightness Name</th>
|
|
<th colspan="2">Light Mode (default)</th>
|
|
<th colspan="2">Dark Mode (default)</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<th><code>--bulma-scheme-main-l</code></th>
|
|
<td><code>100%</code></td>
|
|
<td><span class="bd-color-swatch" style="--background: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), var(--bulma-scheme-main-l));"></span></td>
|
|
<td><code>11%</code></td>
|
|
<td class="theme-dark"><span class="bd-color-swatch" style="--background: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), var(--bulma-scheme-main-l));"></span></td>
|
|
</tr>
|
|
<tr>
|
|
<th><code>--bulma-scheme-main-bis-l</code></th>
|
|
<td><code>98%</code></td>
|
|
<td><span class="bd-color-swatch" style="--background: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), var(--bulma-scheme-main-bis-l));"></span></td>
|
|
<td><code>13%</code></td>
|
|
<td class="theme-dark"><span class="bd-color-swatch" style="--background: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), var(--bulma-scheme-main-bis-l));"></span></td>
|
|
</tr>
|
|
<tr>
|
|
<th><code>--bulma-scheme-main-ter-l</code></th>
|
|
<td><code>98%</code></td>
|
|
<td><span class="bd-color-swatch" style="--background: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), var(--bulma-scheme-main-ter-l));"></span></td>
|
|
<td><code>15%</code></td>
|
|
<td class="theme-dark"><span class="bd-color-swatch" style="--background: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), var(--bulma-scheme-main-ter-l));"></span></td>
|
|
</tr>
|
|
<tr>
|
|
<th><code>--bulma-background-l</code></th>
|
|
<td><code>96%</code></td>
|
|
<td><span class="bd-color-swatch" style="--background: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), var(--bulma-background-l));"></span></td>
|
|
<td><code>14%</code></td>
|
|
<td class="theme-dark"><span class="bd-color-swatch" style="--background: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), var(--bulma-background-l));"></span></td>
|
|
</tr>
|
|
<tr>
|
|
<th><code>--bulma-border-weak-l</code></th>
|
|
<td><code>93%</code></td>
|
|
<td><span class="bd-color-swatch" style="--background: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), var(--bulma-border-weak-l));"></span></td>
|
|
<td><code>21%</code></td>
|
|
<td class="theme-dark"><span class="bd-color-swatch" style="--background: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), var(--bulma-border-weak-l));"></span></td>
|
|
</tr>
|
|
<tr>
|
|
<th><code>--bulma-border-l</code></th>
|
|
<td><code>86%</code></td>
|
|
<td><span class="bd-color-swatch" style="--background: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), var(--bulma-border-l));"></span></td>
|
|
<td><code>24%</code></td>
|
|
<td class="theme-dark"><span class="bd-color-swatch" style="--background: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), var(--bulma-border-l));"></span></td>
|
|
</tr>
|
|
<tr>
|
|
<th><code>--bulma-text-weak-l</code></th>
|
|
<td><code>48%</code></td>
|
|
<td><span class="bd-color-swatch" style="--background: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), var(--bulma-text-weak-l));"></span></td>
|
|
<td><code>53%</code></td>
|
|
<td class="theme-dark"><span class="bd-color-swatch" style="--background: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), var(--bulma-text-weak-l));"></span></td>
|
|
</tr>
|
|
<tr>
|
|
<th><code>--bulma-text-l</code></th>
|
|
<td><code>29%</code></td>
|
|
<td><span class="bd-color-swatch" style="--background: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), var(--bulma-text-l));"></span></td>
|
|
<td><code>71%</code></td>
|
|
<td class="theme-dark"><span class="bd-color-swatch" style="--background: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), var(--bulma-text-l));"></span></td>
|
|
</tr>
|
|
<tr>
|
|
<th><code>--bulma-text-strong-l</code></th>
|
|
<td><code>21%</code></td>
|
|
<td><span class="bd-color-swatch" style="--background: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), var(--bulma-text-strong-l));"></span></td>
|
|
<td><code>93%</code></td>
|
|
<td class="theme-dark"><span class="bd-color-swatch" style="--background: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), var(--bulma-text-strong-l));"></span></td>
|
|
</tr>
|
|
<tr>
|
|
<th><code>--bulma-text-title-l</code></th>
|
|
<td><code>14%</code></td>
|
|
<td><span class="bd-color-swatch" style="--background: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), var(--bulma-text-title-l));"></span></td>
|
|
<td><code>100%</code></td>
|
|
<td class="theme-dark"><span class="bd-color-swatch" style="--background: hsl(var(--bulma-scheme-h), var(--bulma-scheme-s), var(--bulma-text-title-l));"></span></td>
|
|
</tr>
|
|
<tr>
|
|
<th><code>--bulma-hover-background-l-delta</code></th>
|
|
<td colspan="2"><code>5%</code></td>
|
|
<td colspan="2"><code>5%</code></td>
|
|
</tr>
|
|
<tr>
|
|
<th><code>--bulma-active-background-l-delta</code></th>
|
|
<td colspan="2"><code>10%</code></td>
|
|
<td colspan="2"><code>10%</code></td>
|
|
</tr>
|
|
<tr>
|
|
<th><code>--bulma-hover-border-l-delta</code></th>
|
|
<td colspan="2"><code>10%</code></td>
|
|
<td colspan="2"><code>10%</code></td>
|
|
</tr>
|
|
<tr>
|
|
<th><code>--bulma-active-border-l-delta</code></th>
|
|
<td colspan="2"><code>20%</code></td>
|
|
<td colspan="2"><code>20%</code></td>
|
|
</tr>
|
|
<tr>
|
|
<th><code>--bulma-hover-color-l-delta</code></th>
|
|
<td colspan="2"><code>5%</code></td>
|
|
<td colspan="2"><code>5%</code></td>
|
|
</tr>
|
|
<tr>
|
|
<th><code>--bulma-active-color-l-delta</code></th>
|
|
<td colspan="2"><code>10%</code></td>
|
|
<td colspan="2"><code>10%</code></td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
|
|
### The `generate-on-scheme-colors()` function
|
|
|
|
The **scheme** color is the one used for:
|
|
|
|
* {% include docs/elements/color-swatch.html background="var(--bulma-background)" %} backgrounds
|
|
* {% include docs/elements/color-swatch.html background="var(--bulma-border)" %} borders
|
|
* text shades
|
|
* {% include docs/elements/color-swatch.html background="var(--bulma-text-strong)" %} strong text
|
|
* {% include docs/elements/color-swatch.html background="var(--bulma-text-weak)" %} weak text
|
|
* {% include docs/elements/color-swatch.html background="var(--bulma-title-color)" %} title text
|
|
* {% include docs/elements/color-swatch.html background="var(--bulma-text)" %} and normal text
|
|
|
|
For each of the 7 primary colors {% include docs/elements/primary-colors.html %}, the default Bulma theme generates **on scheme** shades, meaning shades of each color that will look decent on the main scheme color.
|
|
|
|
In Light Mode, they look like this:
|
|
|
|
<table class="table is-bordered">
|
|
<tbody>
|
|
{% for color in site.data.colors.justColors %}
|
|
{% assign foreground = color | prepend: 'var(--bulma-' | append: '-on-scheme)' %}
|
|
<tr>
|
|
<th><code>{{ color }}</code></th>
|
|
<td>{% include docs/elements/color-swatch.html background="var(--bulma-scheme-main)" color=foreground text=foreground %}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
|
|
Because in Dark Mode we are inverting the lightness of these colors, the page background will go from white {% include docs/elements/color-swatch.html background="#fff" %} to black {% include docs/elements/color-swatch.html background="#141414" %}. We thus need to update the `-on-scheme` colors of all 7 primary colors.
|
|
|
|
In Dark Mode, they look like this:
|
|
|
|
<table class="table is-bordered">
|
|
<tbody>
|
|
{% for color in site.data.colors.justColors %}
|
|
{% assign foreground = color | prepend: 'var(--bulma-' | append: '-on-scheme)' %}
|
|
<tr>
|
|
<th><code>{{ color }}</code></th>
|
|
<td class="theme-dark">{% include docs/elements/color-swatch.html background="var(--bulma-scheme-main)" color=foreground text=foreground %}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
|
|
If you are creating your own theme, you can automatically generate new `-on-scheme` colors by using the `generate-on-scheme-colors()` for **each** color. It takes 3 parameters:
|
|
|
|
* `$name` which is a string. E.g. `"primary"`
|
|
* `$color` which is the color value. E.g.
|
|
* `$scheme-main` which is the theme's main scheme color (the one used as the page background). E.g. `#fff`
|
|
|
|
The full code looks like this:
|
|
|
|
```scss
|
|
@use "sass/utilities/css-variables" as cv;
|
|
@use "sass/utilities/derived-variables" as dv;
|
|
|
|
$scheme-main-l: 11%;
|
|
$scheme-main: hsl(iv.$scheme-h, iv.$scheme-s, $scheme-main-l);
|
|
|
|
@include cv.bulma-theme($name: "my-theme") {
|
|
@each $name, $color in dv.$colors {
|
|
@include cv.generate-on-scheme-colors($name, $color, $scheme-main);
|
|
}
|
|
}
|
|
```
|
|
|
|
### The `setup-theme()` function
|
|
|
|
In Bulma, some CSS variables reference other CSS variables. For example, `--bulma-scheme-main` is defined like this:
|
|
|
|
```css
|
|
:root {
|
|
--bulma-scheme-main: hsl(
|
|
var(--bulma-scheme-h)
|
|
var(--bulma-scheme-s)
|
|
var(--bulma-scheme-main-l)
|
|
);
|
|
}
|
|
```
|
|
|
|
Because of how CSS variables work, if you update the value of `--bulma-scheme-main-l`, you need to define `--bulma-scheme-main` again. That is what `setup-theme()` does.
|
|
|
|
```css
|
|
[data-theme=my-theme],
|
|
.theme-my-theme {
|
|
--bulma-scheme-main-l: 7%;
|
|
--bulma-scheme-main: hsl(
|
|
var(--bulma-scheme-h)
|
|
var(--bulma-scheme-s)
|
|
var(--bulma-scheme-main-l)
|
|
);
|
|
}
|
|
```
|
|
|
|
If you create your own theme, simply call this function _after_ having set your own CSS variables:
|
|
|
|
```scss
|
|
@use "sass/themes/setup";
|
|
|
|
@include cv.bulma-theme($name: "my-theme") {
|
|
// Set your own CSS variables,
|
|
// either manually:
|
|
--bulma-scheme-main-l: 7%;
|
|
// or using Bulma's register-vars() function:
|
|
@include register-vars((
|
|
"bulma-scheme-main-l": 7%,
|
|
));
|
|
|
|
// Then, setup the new theme.
|
|
@include setup.setup-theme();
|
|
}
|
|
```
|