skip to Main Content

I’m been trying to integrate a theme button into my website but unfortunately, it doesn’t work properly. When the page is refreshed the button toggles to the initial phase but the page remains with the theme that was set previously

I want the button to remain locked after setting a statement (light theme or dark one)

Function:

// function to set a given theme/color-scheme
function setTheme(themeName) {
  localStorage.setItem('theme', themeName);
  document.documentElement.className = themeName;
}
// function to toggle between light and dark theme
function toggleTheme() {
 if (localStorage.getItem('theme') === 'theme-dark'){
     setTheme('theme-light');
 } else {
     setTheme('theme-dark');
 }
}
// Immediately invoked function to set the theme on initial load
(function () {
 if (localStorage.getItem('theme') === 'theme-dark') {
     setTheme('theme-dark');
 } else {
     setTheme('theme-light');
 }
})();

CSS:

.theme-light {
    --color-body: #2610ff;
    --background-body: #fff;
    --heading-color: #226229;
    --font-color: #000000;
    --color-mainNav: rgba(255, 255, 255, 0.9);
    --text-mainNav: #333;
    --background-header: #a09b9b42;
    --background-featured: #4b3bf4;
 }
 .theme-dark {
    --color-body: #999CFF;
    --background-body: #000000;
    --heading-color: #3EB14E;
    --font-color: #ffffff;
    --color-mainNav: rgba(0, 0, 0, 0.8);
    --text-mainNav: #dbd5d5;
    --background-header: #45444880;
    --background-featured: rgb(38, 0, 255);
 }

 /* Hide default HTML checkbox */
.switch input {
   opacity: 0;
   width: 0;
   height: 0;
 }
 
 /* The slider */
 .slider {
   position: relative;
   cursor: pointer;
   top: 0;
   left: 0;
   right: 0;
   bottom: 0;
   background-color: #ccc;
   -webkit-transition: 0.4s;
   transition: 0.4s;
 }
 .slider:before {
   position: absolute;
   content: "";
   height: 40px;
   width: 40px;
   left: 0px;
   bottom: 4px;
   top: 0;
   margin: auto 0;
   -webkit-transition: 0.4s;
   transition: 0.4s;
   box-shadow: 0 0px 15px #2020203d;
   background: white url('https://i.ibb.co/7JfqXxB/sunny.png');
   background-repeat: no-repeat;
   background-position: center;
 }
 
 input:checked + .slider {
   background-color: #2196f3;
 }
 
 input:focus + .slider {
   box-shadow: 0 0 1px #2196f3;
 }
 
 input:checked + .slider:before {
   -webkit-transform: translateX(24px);
   -ms-transform: translateX(24px);
   transform: translateX(24px);
   background: white url('https://i.ibb.co/FxzBYR9/night.png');
   background-repeat: no-repeat;
   background-position: center;
 }
 /* Rounded sliders */
.slider.round {
   border-radius: 34px;
 }
 
 .slider.round:before {
   border-radius: 50%;
 }

HTML:

<link rel="stylesheet" href="./style.css">
<body class="body">
      <label id="switch" class="switch">
        <input type="checkbox" onchange="toggleTheme()" id="slider">
        <span class="slider round"></span>
    </label>
  </body>

I’ve created a codepen so maybe someone will help me out with my problem

link: https://codepen.io/cornelius89/pen/xxMZjza

2

Answers


  1. I believe your problem is that you have forgotten to set initial state for the button when the page loads :

    // Immediately invoked function to set the theme on initial load
    (function () {
      let crrTheme = localStorage.getItem('theme') ?? 'theme-light';
     if (crrTheme === 'theme-dark') {
         setTheme('theme-dark');
     } else {
         setTheme('theme-light');
     }
      document.querySelector("#slider").checked = (crrTheme === 'theme-dark');
    })();

    Additionally, it would we much better to come up with a solution to set state before rendering happens, like putting the function in separate script tag in the <head>.

    Login or Signup to reply.
  2. On initial load, there should be logic to change the state of the #slider checkbox element.

    // Immediately invoked function to set the theme on initial load
    (function () {
      const DEFAULT_THEME = 'theme-light';
      const theme = localStorage.getItem('theme') || DEFAULT_THEME;
      setTheme(theme);
    
      // This should set the initial state of the checkbox based on the localStorage data.
      document.getElementById('slider').checked = theme !== DEFAULT_THEME;  
    })();
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search