最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to stop light mode flickering to darker background on page load - Stack Overflow

programmeradmin1浏览0评论

So I have a bit of script for toggling between light and dark modes on my site. The dark mode is the default. Problem is, whenever the light mode is toggled on, with every page load it flickers to the dark mode for just a second before loading the light mode. I would really like it to not do this and super appreciate any help you all can give. Thanks in advance!

My Code is as follows:

if (localStorage['blackout']) {
 if (Number(localStorage['blackout']) == 1) {
$('BODY').addClass('blackout');
 } else {
  $('BODY').removeClass('blackout');
 }
} else {
  localStorage['blackout'] = 0;
  $('BODY').removeClass('blackout');
}
$('BODY').show();
$('#boToggle').on('click', function(){
  if (Number(localStorage['blackout']) == 0) {
      localStorage['blackout'] = 1;
$('BODY').addClass('blackout');
  } else {
      localStorage['blackout'] = 0;
$('BODY').removeClass('blackout');
 }
});

So I have a bit of script for toggling between light and dark modes on my site. The dark mode is the default. Problem is, whenever the light mode is toggled on, with every page load it flickers to the dark mode for just a second before loading the light mode. I would really like it to not do this and super appreciate any help you all can give. Thanks in advance!

My Code is as follows:

if (localStorage['blackout']) {
 if (Number(localStorage['blackout']) == 1) {
$('BODY').addClass('blackout');
 } else {
  $('BODY').removeClass('blackout');
 }
} else {
  localStorage['blackout'] = 0;
  $('BODY').removeClass('blackout');
}
$('BODY').show();
$('#boToggle').on('click', function(){
  if (Number(localStorage['blackout']) == 0) {
      localStorage['blackout'] = 1;
$('BODY').addClass('blackout');
  } else {
      localStorage['blackout'] = 0;
$('BODY').removeClass('blackout');
 }
});
Share Improve this question asked Jun 29, 2020 at 9:39 Charmaine SimpsonCharmaine Simpson 411 silver badge2 bronze badges 0
Add a ment  | 

2 Answers 2

Reset to default 5

Put your JS (the part reading from local storage and applying the class) in the <head> section, and add the class to the <html> tag, so that it get executed before the body is parsed and displayed.

You can try it with this simple working demo:

<html>
<head>
  <script>
    // Do this before the body gets parsed
    if (localStorage.getItem('darkmode') === '1') {
      document.documentElement.classList.add('darkmode');
    }
  </script>
  <style>
    .darkmode body { background: #222; }
    .darkmode .light-only { display: none; }
    html:not(.darkmode) .dark-only { display: none; }
  </style>
</head>
<body>
  <button id="darkToggle">
    Switch to
    <span class="dark-only">light</span>
    <span class="light-only">dark</span>
    mode
  </button>

  <script>
    document.querySelector('#darkToggle').addEventListener('click', function() {
      var wasDarkMode = localStorage.getItem('darkmode') === '1';

      localStorage.setItem('darkmode', wasDarkMode ? '0' : '1');
      document.documentElement.classList[wasDarkMode ? 'remove' : 'add']('darkmode');
    });
  </script>
</body>
</html>

In case anyone else is having this issue and this helps; my solution to this was to store the chosen theme in the user's session data, and then ensuring the correct class was applied when in the HTML.

Here is my JavaScript client code:

window.getTheme = function () {
    let theme = localStorage.getItem('theme');
    if (!["dark", "light"].includes(theme)) {
        theme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
    }
    return theme;
}
window.setTheme = function (theme) {
    if (theme) {
        localStorage.setItem('theme', theme);
        // You could use the fetch API here instead...
        axios.post('/theme', { theme });
    } else {
        theme = getTheme();
    }
    document.querySelector('body').classList.remove('dark', 'light');
    document.querySelector('body').classList.add(theme);
}

window.unsetTheme = function () {
    localStorage.removeItem('theme');
    setTheme();
}

window.matchMedia('(prefers-color-scheme: dark)')
    .addEventListener('change', e => {
        setTheme();
    });

setTheme();

I'm using Laravel in the back end, so here's a simple handler for the theme endpoint:

Route::post('theme', function () {
    $theme = request('theme');

    if (in_array($theme, ['light', 'dark'])) {
        Session::put('theme', $theme);
    }
})->name('theme');

Finally we then need to add this to the body in the main layout:

<body class="font-sans antialiased {{Session::get("theme")}}">
发布评论

评论列表(0)

  1. 暂无评论