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

javascript - Implementing a dark theme in jekyll - Stack Overflow

programmeradmin3浏览0评论

I'm trying to add a simple light/dark mode toggle to my Jekyll site.

The way I have it setup now is that the body has a dark class that is switched to a light class on toggle, and the theme is persisted in localStorage and loaded whenever the user goes to a new page. The SCSS simply has selectors for .dark and .light that will show the corresponding color scheme.

The problem with this approach is that my default theme is dark, so if the theme is set to light there's a very clear .2 second flash as the classes switch from dark to light when I load a new page.

I've tried solving the issue by setting the body's visibilty to hidden then making it visible again once the switch has been made, but unfortunately this approach introduces another annoying flash/lag, and there's no good way to stop it from flashing on every page load.

Some of the potential solutions I've thought of, but don't know if they are possible or how to implement them are:

  1. Have Jekyll somehow read from localStorage and change the class of the rendered HTML based on that (probably the best solution, but also probably not possible)

  2. Somehow have Jekyll produce two separate style sheets from the SCSS and use JS to select the correct one

    Would appreciate any insight on how to do these things or potential alternate solutions, thanks!

I'm trying to add a simple light/dark mode toggle to my Jekyll site.

The way I have it setup now is that the body has a dark class that is switched to a light class on toggle, and the theme is persisted in localStorage and loaded whenever the user goes to a new page. The SCSS simply has selectors for .dark and .light that will show the corresponding color scheme.

The problem with this approach is that my default theme is dark, so if the theme is set to light there's a very clear .2 second flash as the classes switch from dark to light when I load a new page.

I've tried solving the issue by setting the body's visibilty to hidden then making it visible again once the switch has been made, but unfortunately this approach introduces another annoying flash/lag, and there's no good way to stop it from flashing on every page load.

Some of the potential solutions I've thought of, but don't know if they are possible or how to implement them are:

  1. Have Jekyll somehow read from localStorage and change the class of the rendered HTML based on that (probably the best solution, but also probably not possible)

  2. Somehow have Jekyll produce two separate style sheets from the SCSS and use JS to select the correct one

    Would appreciate any insight on how to do these things or potential alternate solutions, thanks!

Share Improve this question edited Jun 20, 2020 at 9:12 CommunityBot 11 silver badge asked Oct 18, 2018 at 18:46 Meme OverlordMeme Overlord 1,0371 gold badge10 silver badges17 bronze badges 6
  • Possible duplicate of Eliminate flash of unstyled content – David Jacquel Commented Oct 18, 2018 at 19:36
  • it's really not -_- - actually I should make my question clearer, since I know the third option isn't really viable and will just make people confused and give me unnecessary answers – Meme Overlord Commented Oct 18, 2018 at 20:29
  • Why just not hide content by default, and when it finish loads show it? – BladeMight Commented Oct 24, 2018 at 20:53
  • Because even when I wait until the switch is made there is still a momentary flicker as they go from hidden to visible – Meme Overlord Commented Oct 24, 2018 at 21:58
  • Are Light & Dark themes in the same stylesheet or two different stylesheets? for every background-color & color in both styles have transition same duration and easing? I think having two stylesheets will create problem instead have one stylesheet. with scss it wont be difficult for you the manage them. – vssadineni Commented Oct 31, 2018 at 12:19
 |  Show 1 more ment

4 Answers 4

Reset to default 8 +25

So breaking this down:

  • As you are using a static site generator, you can only apply the dark or light theme once a small piece of Javascript executes to determine and set the theme.
  • This is resulting in some delay/flash of content as the Javascript executes.

I think using a static site generator means that reading from localStorage and applying a theming class with Javascript is a perfectly good approach. As I see it, there are two possible approaches to minimising the flashing issue that don't involve changing the architecture away from a Jekyll site.

Execute the Javascript sooner, as the page content is loading:

Because the only DOM element that needs to have loaded is the <html> element itself, to which you can apply a theme class, you could put your 'critical' Javascript in a small script tag inside the <head>. i.e. just the 'theme-switching' line of code.

It should then execute straight away before the content loads.

Use CSS transitions to minimise the flash itself:

You could hide the page content while the <html> element has no theming class, and fade it in once one is applied like so:

html {
    opacity: 0;
    transition: opacity 1s;
}

html.light, html.dark {
    opacity: 1;
}

What you want, according to point 3,

Implement some kind of fade in/fade out when changing the visibility from hidden to visible

is --

CSS Transitions

Example usage to show ease-in effect whenever a CSS property change:

body {
  transition: background 1s ease-in, color 1s ease-in;
}
.dark {
  color: white;
  background: black;
}
<body>

  <p> Lorem Ipsum dolor sit amet... </p>

  <button onclick="document.body.classList.toggle('dark')">Change Theme</button>

</body>

No javascript is needed, with the prefers-color-scheme media query:

@media (prefers-color-scheme: dark) {
  // Styles for dark mode here
  body { background-color: #222 }
  ...
}

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

I tried this in my local it works fine, though I am not using any js or jekyll simple transition. Let js do the class switching and nothing else. let the transition be taken care by css. use one stylesheet.

.theme {
    &.dark {
        background: #000;
        color: #fff;
    }
    &.light {
        background: #fff;
        color: #000;
    }
    transition:background-color 200ms ease-in-out, color 200ms ease-in-out;
}


<body class="body theme dark"> <!-- just switch dark to light class-->
    <h1 class="sticky">Thank you</h1>
    <div class="row" id="bindlinkTempl"></div>
    <script src="js/dist/app.js"></script>


</body>
发布评论

评论列表(0)

  1. 暂无评论