×

Add Dark theme & Light theme in website

Table of content

  1. Introduction
  2. Need of dark mode on websites
  3. Different ways of enabling dark mode on your websites
    1. Using color-scheme CSS property.
    2. Using prefers-color-scheme media query.
    3. Using color-scheme meta tag.
    4. Setting color-scheme value in meta tag using JavaScript.
    5. Setting attributes in the body tag using JavaScript.
    6. Setting class name in html tag using JavaScript.
  4. Additional concepts

Introduction

Enabling dark mode and light mode on a website involves creating a user interface (UI) that allows users to switch between two different color schemes: one with lighter backgrounds and darker text (light mode) and one with darker backgrounds and lighter text (dark mode). This can enhance the user experience by making the website more accessible and comfortable to view in different lighting conditions.

Each web browser has its own default CSS styles, often referred to as "user agent stylesheets". These stylesheets provide default styling for HTML elements that aren't explicitly styled by a web page's CSS. So when you create an element in HTML and don't give any styling to it, generally it used to take the default styling from the user-agent stylesheet and even these stylesheets have beautifully handled all the scenarios of light and dark mode based on the user OS theme preferences.

Need of dark mode on websites

Most people love to interact in dark mode and if you do not have this functionality in your website then there is a high chance that they would not like to interact with your website and may leave from there.

A lot of developers struggle to build the dark mode functionality in their websites due to which they use libraries or complicate their codes. In this article let's see what are the different ways using which you can build the dark mode / light mode functionality in your website without using any third-party library. In some of the ways we will only use HTML and CSS and we will also use JavaScript to build this feature using some interactions like buttons, toggles or checkboxes.

Different ways of enabling dark mode on your website.

1. Enable dark mode using color-scheme CSS property.

color-scheme is a CSS property that defines which color schemes a web page or HTML elements in a webpage can use based on the user Operating System theme selection. It affects how the user agent selects the colors for displaying various UI elements when there is no CSS defined for any particular element. This property indicates to the browser which color scheme options should be used depending on the value provided to this CSS property.

Values we can provide to color-scheme are,

color-scheme: normal; color-scheme: light; color-scheme: dark; color-scheme: light dark; color-scheme: only light;

The default value is normal.

Read more: https://developer.mozilla.org/en-US/docs/Web/CSS/color-scheme

Example:

:root { color-scheme: dark; /* above code means dark theme supported */ }

Let's say we have this CSS defined in our CSS code, this indicates the browser's user-agent to use only dark theme by default without checking which theme is there in the user's Operating System.

and you will see the below output.

example1

Now, let's see one more case,

:root { color-scheme: dark light; /* above code means both dark and light theme is supported */ }

Here we have informed user-agent to use both dark and light themes, Hence browser will check the OS theme selection and based on that it will apply the color theme.

Let's see the output based on OS theme.


When the user has a dark OS theme

example1


When the user has a light OS theme

example2


Advantages of using color-scheme:

By declaring support for light and dark color schemes, web pages can automatically adapt to the user's preferred theme, providing a better user experience and ensuring consistency with the operating system or browser settings.


Limitations of using color-scheme:

With color-scheme we are just declaring the theme color and the control of styling we are giving to the user-agent, we don't have any control over giving our own customized style with color-scheme. If your design requires a specific theme irrespective of the system settings (the default ones), you’ll need additional logic to override these preferences.

If you want more control over your website design then you can use media queries prefers-color-scheme and CSS variables for finer control over your theme design.



2. Enable light/dark mode using prefers-color-scheme media query.

prefers-color-scheme is a media feature or a media query property using which we can customize our CSS layouts and assign our own colors/styles to the elements based on the user's OS theme preference, unlike the previous one as with color-scheme we don't have the option of providing our own customizes CSS style based on OS theme. When the user or system has not specified a preference, you can assume a "no preference" scenario.

The values for this can be no-preference, dark and light.

@media (prefers-color-scheme: no-preference){} @media (prefers-color-scheme: dark){} @media (prefers-color-scheme: light){}

Read more: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme

Example: Let's see how to handle dark mode

html { /* the default variables */ --background-color: #f3c2c1; --text-color: #000000; } @media (prefers-color-scheme: dark) { html { /* variable defined for dark theme */ --background-color: #160100; --text-color: #ffffff } } @media (prefers-color-scheme: light) { html { /* variable defined for light theme */ --background-color: #ffffff; --text-color: #000000; } } @media (prefers-color-scheme: no-preference) { html { /* variable defined when user has no-preference */ --background-color: #1c0ae0; --text-color: #02ff6c; } }

Here if you see, we have defined the background-color variable and text-colorCSS variable so by default when the user doesn't have any theme preference then the color #f3c2c1 for --background-color and #000000 for --text-color will be applied and if the user's OS has any of the themes selected then based on that theme the colors will be applied.

CSS Variables: https://www.capscode.in/blog/variable-in-css


If the user has selected a light theme:

example3


If the user has selected a dark theme:

example4


some corner cases,

If the user has a dark OS theme and @media (prefers-color-scheme: dark) is not defined, then whatever CSS you have written in the .html{} will be the default one. Similarly for the light theme as well.

Example

html { --background-color: #f3c2c1; --text-color: #000000; } @media (prefers-color-scheme: light) { html { --background-color: #ffffff; --text-color: #000000; } }

Based on the above code, when the OS theme is light then @media (prefers-color-scheme: light){} will be used but if the user's OS has a dark theme then the code written in html{} will be considered as we haven't defined @media (prefers-color-scheme: dark){} in our CSS code.

Let's see the output below.


If the user has a light OS theme:

example5


If the user has a dark OS theme:

example6



3. Enable light/dark mode using <meta name="color-scheme" content="dark light">

The next way of enabling light/dark mode is using a meta tag. This looks similar to the first implementation isn't it, But in the first implementation we were doing it using CSS and in this approach, we are using HTML document (meta tag). Hence we have more control over the HTML element and changing the attributes of the HTML elements. In this section, we will see the default behavior of adding color-scheme meta tag and then we will see how changing attributes will help in creating light-themed & dark-themed web apps using JavaScript in further topics.


Example:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="color-scheme" content="dark light"> <link rel="stylesheet" href="index.css"> <title>Document</title> </head> <body> <section> <h1>Hello CapsCode...Type 3</h1> <p>Using meta tag as: &lt;meta name="color-scheme" content="dark light"&gt; </p> </section> </body> </html>

Here if you see we have added a meta tag named color-scheme and assigned a content value of dark light in the header of the document. This indicates that our document supports both dark and light themes based on the user's OS theme selection and the rest of the functionality is similar to the first approach discussed above.


If the user has a light OS theme.

example7

If the user has a dark OS theme.

example8

As of now, we have seen the different ways of enabling light mode & dark mode on the website but all of those steps are static based on the user's operating system theme selection where the user doesn't have control over switching between the themes. Now let us see how we can add JavaScript in our code to have some interactivity and will switch between the themes in our web apps.


4. Enable dark mode by setting color-scheme value in the meta tag using JS

In this section, we will see how we can change color-scheme content value to dark/light when clicking on the button.

Example

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="color-scheme" id="colorScheme" content=""> <title>Document</title> <script> function setColorScheme(scheme) { var colorSchemeMeta = document.getElementById('colorScheme'); colorSchemeMeta.setAttribute('content', scheme); } </script> </head> <body> <section> <h1>Hello CapsCode...Type 4</h1> <button onclick="setColorScheme('dark')">Enable dark mode</button> <button onclick="setColorScheme('light')">Enable light mode</button> </section> </body> </html>

Below is the output:

example9


In this example, we have two buttons, one for light mode and another for dark mode, clicking on which will call the setColorScheme function and that function will add the light or dark values in the color-scheme meta tag and based on that we can see the styles in the UI.


Advantages of this method:

We can have a toggle to switch between the light and the dark mode and it's not only depend upon the OS theme.


Limitations of this method:

We cannot add our customized colors/styles for the theme selected, the colors and other styling stuff will be handled by the user-agent and we don't have much control over the UX (mostly colors).

So, The next question is how we can have both, a toggle between the themes and the control over the declaration of our custom CSS.

Well, there are multiple ways but in this article, we will see the two most easy and helpful approaches.


5. Enable dark mode by setting an attribute in the body or html tag

We can add some attribute in the html or body tag and based on the value of that attribute we can declare our CSS so that our UI will reflect the CSS based on the attribute value.

Example:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="index.css"> <title>Document</title> <script> function darkmode() { document.body.setAttribute('dark-theme', true); } function lightmode() { document.body.setAttribute('dark-theme', false); } </script> </head> <body> <section> <button id="dark" onclick="darkmode()">Enable dark mode</button> <button id="light" onclick="lightmode()">Enable light mode</button> <h1>Hello CapsCode...Type 5</h1> <p>Using JS and toggle buttons</p> </section> </body> </html>

So, here in the above code, you can see that we have two buttons, one for light mode and other for dark mode, clicking on one will call their respective functions which will add the dark-theme attribute in the body and give it a boolean value of true or false depending on the function called.


Let's see how our CSS is defined.

body[dark-theme=false] { --background-color: #f3c2c1; --text-color: #000000; } body[dark-theme=true] { --background-color: #160100; --text-color: #ffffff } body { min-height: 100vh; background: var(--background-color); } h1,p { color: var(--text-color) }

Based on the defined CSS, we can see the below output.

example10

you can see in the dev tool, how clicking on the buttons adds/changes the values in the data-theme attribute of the body tag.

When we click on the Enable dark mode button, dark-theme="true" attribute is added in the body tag and from our CSS file, the below CSS will be taken into consideration.

body[dark-theme=true] { --background-color: #160100; --text-color: #ffffff }

Due to the above CSS background-color of the body becomes darker and the text-color becomes lighter.


When we click on the Enable light mode button, dark-theme="false" attribute is added in the body tag and from our CSS file, the below CSS will be taken into consideration.

body[dark-theme=false] { --background-color: #f3c2c1; --text-color: #000000; }

Due to the above CSS background-color of the body becomes lighter and the text-color becomes darker.


NOTE: Instead of adding the attribute in the body tag we can add the attribute in the html tag as well and there is no restriction in providing the attribute names.


6. Enable dark mode by setting the class name in the body or html tag

In this example, we will see how we can enable dark mode in our application by adding class names in the body tag dynamically by clicking on a toggle button.

Example:

Here is our HTML code

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="index.css"> <title>Document</title> <script> function themeHandler() { const themeToggleButton = document.getElementById('toggle'); let currentTheme = document.body.classList[0] if (currentTheme == undefined) { document.body.classList.add(`dark-mode`); } if (currentTheme == "dark-mode") { document.body.classList.remove('dark-mode'); document.body.classList.add(`light-mode`); } else { document.body.classList.remove('light-mode'); document.body.classList.add(`dark-mode`); } } </script> </head> <body> <section> <button id="toggle" onclick="themeHandler()">Toggle Theme</button> <h1>Hello CapsCode...Type 7</h1> <p>Using JS and toggle buttons</p> </section> </body> </html>

In the above code, you can see that we are adding a class name dynamically in the body tag (i.e. dark-mode or light-mode).

Our themeHandler function first checks what is the current class name in the body tag and if there is no class name given to the body tag then we give the class name as dark-theme. We have written a condition that if the current theme is dark-mode and when you click on the toggle button it will add light-mode and vice versa.


Below is our CSS code.

/* Default (light mode) styles */ body.light-mode { --background-color: #f3c2c1; --text-color: #000000; } /* Dark mode styles */ body.dark-mode { --background-color: #160100; --text-color: #ffffff } body { height: 100vh; background-color: var(--background-color); } h1, p { color: var(--text-color); }

Below is the output.

example11


You can see in the dev tool, how clicking on the toggle buttons adds the class name in the body tag.

When dark-mode class name is added then the below CSS will be taken into consideration.

body.dark-mode { --background-color: #160100; --text-color: #ffffff }

Due to the above CSS, the background-color of the body becomes darker and the text-color becomes lighter.

When light-mode class name is added in the body tag then the below CSS will be taken into consideration.

body.light-mode { --background-color: #f3c2c1; --text-color: #000000; }

Due to this, the background-color of the body becomes lighter and the text-color becomes darker.


Additional concept

We have seen how we can play around the theme using JavaScript by adding our custom class name or attributes and assigning CSS based on this. So let's design something different using this concept.

Use case: Click on the button to zoom-in and zoom-out contents on the website.

Example:

Below is the html code.

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link rel="stylesheet" href="index.css"> <title>Document</title> <script> function zoomIn() { document.documentElement.setAttribute('data-zoom', "2") } function zoomOut() { document.documentElement.setAttribute('data-zoom', "1") } </script> </head> <body> <section> <h1>Hello CapsCode...Type 8</h1> <button onclick="zoomIn()">Zoom In</button> <button onclick="zoomOut()">Zoom Out</button> </section> </body> </html>

Here we have one Zoom In button and one Zoom Out button, clicking on which will add the attribute data-zoom=2 and data-zoom=1 respectively in the html tag.


Based on this we have below CSS written in our CSS file.

html { --background-color: #f3c2c1; --text-color: #000000; font-size: 24px } html[data-zoom="1"] { font-size: 24px } html[data-zoom="2"] { font-size: 44px } body { min-height: 100vh; background: var(--background-color); font-size: 1rem; } h1, p { color: var(--text-color) }

In this example, we are changing the font-size of the root element based on the attribute of HTML tag.

If you want to learn more about how rem font unit works then do check out the link below. https://www.youtube.com/watch?v=0GjVwGvvNtk


Below is the Output:

example12

Conclusion

These are the multiple ways to add dark mode or light mode to your website, enhancing the user experience by allowing users to view content in their preferred mode. By leveraging CSS media queries, JavaScript, and browser or system theme preferences, you can provide a seamless and personalized browsing experience. Whether you choose to rely on system settings, offer a manual toggle, or a combination of both, implementing theme toggle mode ensures your website is accessible and visually appealing to a wider audience.

Hope it's a nice and informative read for you. If you find this article useful, like and share this article. Someone could find it useful too.