Reputation: 89
the problem is when the dark mode is enabled, and the page is reloaded for some reason, there's a flicker of white background all over the page before it turns to be dark. It stays a fraction of a second. It just doesn't look professional. i Know there is already a similar answer i tried, but that one doesn't resolve my problem.
As you can see in the gif flicker
HTML
<header class="header" id="header">
<nav class="nav container">
<a href="#home" class="nav__logo smooth">
<svg version="1.1" id="logo" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 106.08 30" style="enable-background:new 0 0 106.08 30;" xml:space="preserve">
<g id="logo_x5F_brand">
<g>
<g>
<polygon class="st0" points="34.39,7.99 34.39,22.01 33.05,22.78 30.35,24.34 29,25.12 27.65,25.9 26.31,26.68 24.96,27.45
23.61,28.23 22.26,29.01 20.91,28.23 19.56,27.45 18.22,26.68 16.87,25.9 15.52,25.12 14.17,24.34 11.48,22.78 10.13,22.01
10.13,7.99 11.48,7.22 12.82,6.44 14.17,5.66 15.52,4.88 16.87,4.1 18.22,3.32 20.91,1.77 22.26,0.99 23.61,1.77 26.31,3.32
27.65,4.1 29,4.88 30.35,5.66 31.7,6.44 33.05,7.22 " />
</g>
</g>
<g>
<g>
<path class="st1" d="M22.3,10.7c-0.34,0.22-0.66,0.44-1,0.66c0.84,0.56,1.69,1.12,2.54,1.68c2.26,1.5,4.52,3,6.78,4.5
c1.02,0.68,0.89,1.89-0.26,2.45c-0.17-0.37-0.55-0.63-0.94-0.89c-4.51-2.99-9.01-5.97-13.51-8.96c-0.59-0.39-0.59-0.85,0.01-1.25
c1.92-1.27,3.84-2.55,5.76-3.82c0.2-0.13,0.37-0.27,0.6-0.44c0.82,0.56,1.58,1.08,2.36,1.6c2.11,1.4,4.22,2.8,6.33,4.2
c0.53,0.35,0.53,0.72,0.01,1.07c-0.99,0.65-1.98,1.31-2.96,1.97c-0.5,0.33-1.07,0.33-1.57,0C25.06,12.53,23.68,11.62,22.3,10.7z
M19.56,10.17c0.91-0.61,1.82-1.22,2.75-1.84c1.64,1.09,3.28,2.18,4.87,3.24c0.34-0.22,0.66-0.43,0.97-0.63
c-1.95-1.29-3.92-2.59-5.86-3.88c-1.23,0.81-2.48,1.63-3.71,2.45C18.88,9.72,19.2,9.93,19.56,10.17z" />
</g>
<g>
<path class="st2" d="M27.77,14.46l3.38-2.25v0c0,0.28-0.14,0.54-0.37,0.69l-2.54,1.72v0.01l2.53,1.71
c0.23,0.16,0.37,0.41,0.37,0.69l0,0l-3.36-2.24V14.46z" />
</g>
<g>
<path class="st1" d="M22.41,19.25c0.34-0.23,0.66-0.44,0.99-0.66c-0.85-0.55-1.7-1.1-2.55-1.66c-2.27-1.48-4.55-2.96-6.81-4.45
c-1.03-0.67-0.91-1.89,0.24-2.45c0.17,0.37,0.55,0.63,0.95,0.88c4.53,2.95,9.05,5.91,13.58,8.86c0.6,0.39,0.6,0.85,0,1.25
c-1.91,1.29-3.83,2.58-5.74,3.87c-0.19,0.13-0.37,0.28-0.59,0.44c-0.82-0.55-1.59-1.07-2.37-1.58c-2.12-1.39-4.24-2.77-6.36-4.16
c-0.53-0.35-0.53-0.72-0.01-1.07c0.98-0.66,1.97-1.32,2.95-1.99c0.5-0.34,1.06-0.34,1.57-0.01
C19.63,17.43,21.02,18.34,22.41,19.25z M25.16,19.76c-0.9,0.61-1.81,1.23-2.74,1.86c-1.65-1.08-3.29-2.16-4.89-3.21
c-0.34,0.22-0.66,0.44-0.96,0.64c1.96,1.28,3.94,2.57,5.89,3.84c1.23-0.82,2.46-1.65,3.69-2.47
C25.83,20.2,25.51,19.99,25.16,19.76z" />
</g>
<g>
<path class="st2" d="M16.92,15.53l-3.36,2.27l0,0c0-0.28,0.13-0.54,0.36-0.69l2.53-1.74l0-0.01l-2.54-1.7
c-0.23-0.15-0.37-0.41-0.37-0.69v0l3.38,2.21L16.92,15.53z" />
</g>
</g>
</g>
<g id="name_x5F_brand">
<path class="st1" d="M40.64,18.9c0.66,0.41,1.62,0.74,2.63,0.74c1.5,0,2.38-0.79,2.38-1.94c0-1.06-0.61-1.67-2.14-2.26
c-1.86-0.66-3.01-1.62-3.01-3.22c0-1.77,1.47-3.09,3.68-3.09c1.17,0,2.01,0.27,2.52,0.56l-0.41,1.2c-0.37-0.2-1.13-0.54-2.16-0.54
c-1.55,0-2.14,0.93-2.14,1.71c0,1.06,0.69,1.59,2.26,2.19c1.93,0.74,2.9,1.67,2.9,3.34c0,1.76-1.3,3.28-3.98,3.28
c-1.1,0-2.3-0.32-2.9-0.73L40.64,18.9z" />
<path class="st1" d="M50.64,9.31v11.38h-1.47V9.31H50.64z" />
<path class="st1" d="M62.8,15.69c-0.08-1.59-0.19-3.5-0.17-4.91h-0.05c-0.39,1.33-0.86,2.75-1.44,4.32l-2.01,5.52h-1.11l-1.84-5.42
c-0.54-1.6-1-3.07-1.32-4.42h-0.03c-0.03,1.42-0.12,3.33-0.22,5.03l-0.3,4.88h-1.4L53.7,9.31h1.87l1.94,5.5
c0.47,1.4,0.86,2.65,1.15,3.83h0.05c0.29-1.15,0.69-2.4,1.2-3.83l2.03-5.5h1.87l0.71,11.38h-1.44L62.8,15.69z" />
<path class="st1" d="M76.52,14.88c0,3.92-2.38,5.99-5.28,5.99c-3.01,0-5.12-2.33-5.12-5.77c0-3.61,2.25-5.98,5.28-5.98
C74.51,9.12,76.52,11.5,76.52,14.88z M67.69,15.07c0,2.43,1.32,4.61,3.63,4.61c2.33,0,3.65-2.14,3.65-4.73
c0-2.26-1.18-4.63-3.63-4.63C68.9,10.32,67.69,12.57,67.69,15.07z" />
<path class="st1" d="M78.43,20.69V9.31h1.6l3.65,5.76c0.84,1.33,1.5,2.53,2.04,3.7l0.03-0.02c-0.14-1.52-0.17-2.9-0.17-4.68V9.31
h1.38v11.38h-1.49l-3.61-5.77c-0.79-1.27-1.55-2.57-2.13-3.8l-0.05,0.02c0.08,1.43,0.12,2.8,0.12,4.69v4.86H78.43z" />
<path class="st1" d="M95.44,15.35h-4.42v4.1h4.93v1.23h-6.4V9.31h6.15v1.23h-4.68v3.6h4.42V15.35z" />
</g>
</svg>
</a>
<div class="nav__menu" id="nav-menu">
<ul class="nav__list grid">
<li class="nav__item">
<a href="#home" class="nav__link smooth">
<i class="uil uil-estate nav__icon"></i>Home
</a>
</li>
<li class="nav__item">
<a href="#about" class="nav__link smooth">
<i class="uil uil-user nav__icon"></i>About
</a>
</li>
<li class="nav__item">
<a href="#qualification" class="nav__link smooth">
<i class="uil uil-briefcase-alt nav__icon"></i>Qualification
</a>
</li>
<li class="nav__item">
<a href="#portfolio" class="nav__link smooth">
<i class="uil uil-scenery nav__icon"></i>Portfolio
</a>
</li>
<li class="nav__item">
<a href="#contact" class="nav__link smooth">
<i class="uil uil-message nav__icon"></i>Contact
</a>
</li>
</ul>
<i class="uil uil-angle-down icon__menu nav__close" id="nav-close"></i>
</div>
<div class="nav__btns">
<!-- Theme change button-->
<i class="uil uil-moon change-theme" id="theme-button"></i>
<div class="nav__toggle" id="nav-toggle">
<i class="uil uil-angle-up icon__menu hover"></i>
</div>
</div>
</nav>
</header>
CSS Light
/*=============== BASE ===============*/
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
body {
background-color: var(--body-color);
font-size: var(--normal-font-size);
font-family: var(--body-font);
color: var(--text-color);
margin: 0 0 var(--header-height) 0;
}
h1,
h2,
h3 {
color: var(--title-color);
font-weight: var(--font-semi-bold);
}
ul {
list-style: none;
}
a {
text-decoration: none;
}
img {
max-width: 100%;
height: auto;
}
CSS dark
/*========== Variables Dark theme ==========*/
body.dark-theme {
--title-color: hsl(var(--hue), 12%, 95%);
--text-color: hsl(var(--hue), 12%, 75%);
--body-color: hsl(var(--hue), 40%, 8%);
--container-color: hsl(var(--hue), 24%, 12%);
}
/*========== Button Dark/Light ==========*/
.nav__btns {
display: flex;
align-items: center;
}
.change-theme {
font-size: 1.25rem;
color: var(--title-color);
cursor: pointer;
margin-right: var(--mb-2);
}
.change-theme:hover {
color: var(--first-color);
}
JAVASCRIPT
/*==================== DARK LIGHT THEME ====================*/
const themeButton = document.getElementById('theme-button')
const darkTheme = 'dark-theme'
const iconTheme = 'uil-sun'
const selectedTheme = localStorage.getItem('selected-theme')
const selectedIcon = localStorage.getItem('selected-icon')
const getCurrentTheme = () => document.body.classList.contains(darkTheme) ? 'dark' : 'light'
const getCurrentIcon = () => themeButton.classList.contains(iconTheme) ? 'uil-moon' : 'uil-sun'
if (selectedTheme) {
document.body.classList[selectedTheme === 'dark' ? 'add' : 'remove'](darkTheme)
themeButton.classList[selectedIcon === 'uil-moon' ? 'add' : 'remove'](iconTheme)
}
themeButton.addEventListener('click', () => {
document.body.classList.toggle(darkTheme)
themeButton.classList.toggle(iconTheme)
localStorage.setItem('selected-theme', getCurrentTheme())
localStorage.setItem('selected-icon', getCurrentIcon())
})
Upvotes: 7
Views: 9020
Reputation: 28611
This is a common issue called FOUC - flash of unstyled content.
Caused by <script src=... defer></script>
Or, in other cases, by running the dark mode script inside doc.ready
What happens is that your page renders (with light style) and then, when the page has finished rendering, the defer
script runs (just before DOMContentLoaded
).
As the page has already been rendered, you see it with the light styles, until the js has a chance to add your dark-theme
to the body
tag.
This will have nothing to do with how long it takes to "parse"/"apply" the css, given the assumption that these too are in the <head>
then they will be applied before content is rendered; if this takes a long time then it will still be before the rest of the HTML is rendered (giving a blank page for that duration).
The solution is to run the js as soon as possible within the html document. eg:
<head>
... css and other js scripts
</head>
<body>
<script>
const selectedTheme = localStorage.getItem('selected-theme')
document.body.classList[selectedTheme === 'dark' ? 'add' : 'remove'](darkTheme)
</script>
... rest of body
the script will run at the time it appears in the render process - before the unstyled content is rendered. So you never see the unstyled content.
Care needs to be taken, for example OPs code also sets a class and a click event on a button; that button won't exist yet.
Upvotes: 9