Copied SVG to clipboard
Something went wrong
Copied code to clipboard
Something went wrong

Default

User image

Default

Name

  • Osmo Discount
    -25%
The Vault/

Dark/Light Mode with Cookie

Dark/Light Mode with Cookie

Documentation

Webflow

Code

Setup: External Scripts

External Scripts in Webflow

Make sure to always put the External Scripts before the Javascript step of the resource.

In this video you learn where to put these in your Webflow project? Or how to include a paid GSAP Club plugin in your project?

HTML

Copy
<script src="https://cdn.jsdelivr.net/npm/js-cookie@3.0.5/dist/js.cookie.min.js"></script>

Step 1: Copy structure to Webflow

Copy structure to Webflow

In the video below we described how you can copy + paste the structure of this resource to your Webflow project.

Copy to Webflow

Webflow structure is not required for this resource.

Step 1: Add HTML

HTML

Copy
<button data-theme-toggle="" class="btn-darklight">
  <div class="btn-darklight__icon">
    <div class="btn-darklight__icon-box">
      <svg xmlns="http://www.w3.org/2000/svg" width="100%" viewbox="0 0 24 24" fill="none"><path d="M15.5355 8.46447C17.4882 10.4171 17.4882 13.5829 15.5355 15.5355C13.5829 17.4882 10.4171 17.4882 8.46447 15.5355C6.51184 13.5829 6.51184 10.4171 8.46447 8.46447C10.4171 6.51184 13.5829 6.51184 15.5355 8.46447Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 4V2" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 22V20" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M18.3599 5.63999L19.0699 4.92999" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M4.93018 19.07L5.64018 18.36" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M20 12H22" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M2 12H4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M18.3599 18.36L19.0699 19.07" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M4.93018 4.92999L5.64018 5.63999" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>
    </div>
    <div class="btn-darklight__icon-box is--absolute">
      <svg xmlns="http://www.w3.org/2000/svg" width="100%" viewbox="0 0 24 24" fill="none"><path d="M18.395 13.027C18.725 12.872 19.077 13.197 18.985 13.55C18.671 14.752 18.054 15.896 17.104 16.846C14.283 19.667 9.77001 19.726 7.02201 16.978C4.27401 14.23 4.33401 9.71601 7.15501 6.89501C8.10501 5.94501 9.24801 5.32801 10.451 5.01401C10.804 4.92201 11.128 5.27401 10.974 5.60401C9.97201 7.74301 10.301 10.305 11.998 12.002C13.694 13.7 16.256 14.029 18.395 13.027Z" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg>
    </div>
  </div>
  <div class="btn-darklight__word">
    <p class="btn-darklight__word-p">Light</p>
    <p class="btn-darklight__word-p is--absolute">Dark</p>
  </div>
  <p class="btn-darklight__word-p">mode</p>
</button>

HTML structure is not required for this resource.

Step 2: Add CSS

CSS

Copy
.btn-darklight {
  color: #131313;
  cursor: pointer;
  background-color: #efeeec;
  border: 0 solid transparent;
  border-radius: .25em;
  outline: 0 transparent;
  justify-content: center;
  align-items: center;
  padding: 0 1.125em 0 .75em;
  display: flex;
  position: relative;
  overflow: hidden;
}

.btn-darklight__icon {
  width: 1.25em;
  height: 100%;
  margin-right: .25em;
  position: relative;
}

.btn-darklight__word {
  padding-right: .25em;
  position: relative;
}

.btn-darklight__word-p {
  margin-top: .05em;
  margin-bottom: 0;
  line-height: 1.2;
  position: relative;
}

.btn-darklight__word-p.is--absolute {
  opacity: 0;
  letter-spacing: .025em;
  position: absolute;
  top: 0;
}

.btn-darklight__icon-box {
  height: 100%;
  padding-top: .66em;
  padding-bottom: .66em;
  display: flex;
  position: relative;
}

.btn-darklight__icon-box.is--absolute {
  position: absolute;
}

/* Background */
[data-theme-status] {
  transition: background-color 0.4s cubic-bezier(0.35, 1, 0.6, 1);
}
[data-theme-status="dark"] {
  background-color: #070915 !important;
}

/* Button Word */
[data-theme-status="dark"] .btn-darklight .btn-darklight__word .btn-darklight__word-p,
[data-theme-status="light"] .btn-darklight .btn-darklight__word .btn-darklight__word-p.is--absolute{
  opacity: 0;
}

[data-theme-status="light"] .btn-darklight .btn-darklight__word .btn-darklight__word-p,
[data-theme-status="dark"] .btn-darklight .btn-darklight__word .btn-darklight__word-p.is--absolute {
  opacity: 1;
}

/* Button Icon */
.btn-darklight .btn-darklight__icon-box{
  transition: transform 0.8s cubic-bezier(0.35, 1.5, 0.6, 1);
  transform: translateY(0%) rotate(-90deg);
}

[data-theme-status="dark"] .btn-darklight .btn-darklight__icon-box{
  transform: translateY(-100%) rotate(0.001deg);
}

Step 2: Add custom Javascript

Custom Javascript in Webflow

In this video, Ilja gives you some guidance about using JavaScript in Webflow:

Step 2: Add Javascript

Step 3: Add Javascript

Javascript

Copy
function initCookieDarkLight() {

  // Function to toggle theme
  function initThemeCheck() {
    // Get the element that has [data-dash-theme] attribute
    const dashThemeElement = document.querySelector('[data-theme-status]');
    if (!dashThemeElement) return;

    // Toggle between light/dark
    const currentTheme = dashThemeElement.getAttribute('data-theme-status');
    const newTheme = (currentTheme === 'light') ? 'dark' : 'light';

    dashThemeElement.setAttribute('data-theme-status', newTheme);
    Cookies.set('theme', newTheme, { expires: 365 });
  }

  // Keydown to toggle theme when Shift + T is pressed
  document.addEventListener('keydown', function(e) {
    const tagName = e.target.tagName.toLowerCase();
    if (tagName === 'input' || tagName === 'textarea' || e.target.isContentEditable) {
      return; // Do nothing if typing into a field
    }

    if (e.shiftKey && e.keyCode === 84) { // Shift+T
      e.preventDefault();
      initThemeCheck();
    }
  });

  // For all elements with [data-theme-toggle], add click handler
  document.querySelectorAll('[data-theme-toggle]').forEach(function(button) {
    button.addEventListener('click', initThemeCheck);
  });

  // If theme cookie is 'dark', set theme to dark
  if (Cookies.get('theme') === 'dark') {
    const themeElement = document.querySelector('[data-theme-status]');
    if (themeElement) {
      themeElement.setAttribute('data-theme-status', 'dark');
    }
  }
}

// Initialize Cookie Dark/Light Theme
document.addEventListener('DOMContentLoaded', function() {
  initCookieDarkLight();
});

Step 3: Add custom CSS

Step 2: Add custom CSS

Custom CSS in Webflow

Curious about where to put custom CSS in Webflow? Ilja explains it in the below video:

CSS

Copy
/* Background */
[data-theme-status] {
  transition: background-color 0.4s cubic-bezier(0.35, 1, 0.6, 1);
}
[data-theme-status="dark"] {
  background-color: #070915 !important;
}

/* Button Word */
[data-theme-status="dark"] .btn-darklight .btn-darklight__word .btn-darklight__word-p,
[data-theme-status="light"] .btn-darklight .btn-darklight__word .btn-darklight__word-p.is--absolute{
  opacity: 0;
}

[data-theme-status="light"] .btn-darklight .btn-darklight__word .btn-darklight__word-p,
[data-theme-status="dark"] .btn-darklight .btn-darklight__word .btn-darklight__word-p.is--absolute {
  opacity: 1;
}

/* Button Icon */
.btn-darklight .btn-darklight__icon-box{
  transition: transform 0.8s cubic-bezier(0.35, 1.5, 0.6, 1);
  transform: translateY(0%) rotate(-90deg);
}

[data-theme-status="dark"] .btn-darklight .btn-darklight__icon-box{
  transform: translateY(-100%) rotate(0.001deg);
}

Implementation

Attributes

  • Add [data-theme-status="light"] to the <body>, used to style the elements on the page.
  • Use [data-theme-toggle] to toggle between theme (light & dark).

Example Structure

For both Webflow and Code

<body data-theme-status="light">
  <button data-theme-toggle>Change theme</button>
</body>

Animating

[data-theme-status="dark"] {
  background-color: var(--color-dark);
  color: var(--color-light);
}

Cookie

We store the user’s theme preference in a cookie, ensuring the chosen theme remains consistent across page loads and future visits. In fact, you can store any type of preference this way—such as filter settings, grid or list views, font sizes, and more.

More information

Read more about the Cookie library: JS-Cookie Documentation

Variant: Using localStorage

An alternative way to save a user's preference that does not require a 3rd party library like JS-Cookie, is using the localStorage API. This will also persist and save even if the website or window is closed. To utilise this, you of course don't need the CDN link, and then you need to replace 2 things in the JS.

In your theme toggle function:

// Replace:
Cookies.set('theme', newTheme, { expires: 365 });

// With:
localStorage.setItem('theme', newTheme);

In your theme initialization, replace:

// Replace: 
if (Cookies.get('theme') === 'dark') {

// With:
if (localStorage.getItem('theme') === 'dark') {

Resource Details

Toggle
Theme
Dark
Light
Color
Button
Animation

Original source

Dennis Snellenberg

Creator Credits

We always strive to credit creators as accurately as possible. While similar concepts might appear online, we aim to provide proper and respectful attribution.