Jelajahi Sumber

prevent white flash on page load when dark theme is persisted

zwbetz-gh 4 tahun lalu
induk
melakukan
27dbcc6dd9

+ 48 - 25
assets/js/template-dom-scripts.js

@@ -97,41 +97,64 @@
 
 /* Switch and persist theme */
 (function () {
-  function CSSSupported (property, value) {
-    var prop = property + ':',
-        el = document.createElement('test'),
-        mStyle = el.style;
-    el.style.cssText = prop + value;
-    return mStyle[property];
-  }
-
   var checkbox = document.getElementById('themer');
-  var inverter = document.getElementById('inverter');
 
-  if (!CSSSupported('filter', 'invert(100%)')) {
-    checkbox.parentNode.hidden = true;
-    return;
+  function persistTheme(val) {
+    localStorage.setItem('darkTheme', val);
   }
 
-  function darkTheme(media) {
-    inverter.setAttribute('media', media);
-    inverter.textContent = inverter.textContent.trim();
-    localStorage.setItem('darkTheme', media);
+  function applyDarkTheme() {
+    var rules = [
+      '.intro-and-nav, .main-and-footer { filter: invert(100%); }',
+      '* { background-color: inherit; }',
+      'img:not([src*=".svg"]), .colors, iframe, .demo-container { filter: invert(100%); }'
+    ];
+    rules.forEach(function(rule) {
+      document.styleSheets[0].insertRule(rule);
+    })
+  }
+
+  function clearDarkTheme() {
+    for (let i = 0; i < document.styleSheets[0].cssRules.length; i++) {
+      document.styleSheets[0].deleteRule(i);
+    }
   }
 
   checkbox.addEventListener('change', function () {
-    darkTheme(this.checked ? 'screen' : 'none');
+    if (this.checked) {
+      applyDarkTheme();
+      persistTheme('true');
+    } else {
+      clearDarkTheme();
+      persistTheme('false');
+    }
   });
 
-  window.addEventListener('DOMContentLoaded', function () {
-    if ('filter' in document.body.style) {
-      if (localStorage.getItem('darkTheme') === 'screen') {
-        checkbox.click();
-      }
+  function handleDarkThemeAsDefault() {
+    {{ if .Site.Params.darkThemeAsDefault }}
+      persistTheme('true');
+      handleDarkThemeAsDefault = function() {};
+    {{ end }}
+  }
+
+  function showTheme() {
+    if (localStorage.getItem('darkTheme') === 'true') {
+      applyDarkTheme();
+      checkbox.checked = true;
     }
+  }
+
+  function showContent() {
+    document.body.style.visibility = 'visible';
+    document.body.style.opacity = 1;
+  }
+
+  window.addEventListener('DOMContentLoaded', function () {
+    handleDarkThemeAsDefault();
+
+    showTheme();
+
+    showContent();
   });
 
-  {{ if .Site.Params.darkThemeAsDefault }}
-  darkTheme('screen');
-  {{ end }}
 }());

+ 1 - 0
layouts/_default/baseof.html

@@ -3,6 +3,7 @@
   {{ partial "head.html" . }}
   <body>
     <a href="#main">{{ T "skip_to_content" }}</a>
+    {{ partial "noscript.html" . }}
     {{ partial "svg.html" . }}
     <div class="wrapper">
       {{ partial "header.html" . }}

+ 1 - 0
layouts/partials/footer.html

@@ -2,6 +2,7 @@
   <div>
     <label for="themer">
       {{ T "dark_theme" }} <input type="checkbox" id="themer" class="vh">
+      <!-- Shows "on" or "off" -->
       <span aria-hidden="true"></span>
     </label>
   </div>

+ 7 - 6
layouts/partials/head.html

@@ -20,6 +20,13 @@
   <meta name="msapplication-TileColor" content="#ffffff">
   <meta name="theme-color" content="#ffffff">
 
+  <style>
+    body {
+      visibility: hidden;
+      opacity: 0;
+    }
+  </style>
+
   <link rel="stylesheet" href="{{ "css/prism.css" | absURL }}" media="none" onload="this.media='all';">
 
   {{ $templateStyles := resources.Get "css/template-styles.css" }}
@@ -30,12 +37,6 @@
     <link rel="stylesheet" href="{{ . | absURL }}">
   {{ end }}
 
-  <style id="inverter" media="none">
-    .intro-and-nav, .main-and-footer { filter: invert(100%) }
-    * { background-color: inherit }
-    img:not([src*=".svg"]), .colors, iframe, .demo-container { filter: invert(100%) }
-  </style>
-
   {{ $title := print .Title " | " .Site.Title }}
   {{ if .IsHome }}
     {{ $title = .Site.Title }}

+ 8 - 0
layouts/partials/noscript.html

@@ -0,0 +1,8 @@
+<noscript>
+  <style>
+    body {
+      visibility: visible;
+      opacity: 1;
+    }
+  </style>
+</noscript>

+ 3 - 3
layouts/partials/script.html

@@ -1,8 +1,8 @@
-<script src="{{ "js/prism.js" | absURL }}"></script>
-
 {{ $templateDomScripts := resources.Get "js/template-dom-scripts.js" }}
 {{ $domScripts := $templateDomScripts | resources.ExecuteAsTemplate "js/dom-scripts.js" . }}
-<script src="{{ $domScripts.Permalink }}"></script>
+<script src="{{ $domScripts.Permalink }}"></script>  
+
+<script src="{{ "js/prism.js" | absURL }}"></script>
 
 {{ if site.Params.search }}
 {{ $searchJs := resources.Get "js/search.js" | fingerprint }}