🐛 fix: remove flash when navigating in dark-mode

The `initialize-theme.js` script takes care of the following:

  1. If there is a stored theme value in the localStorage, set the theme
 based on that value.
  2. If there is no stored theme value, check the  user's system
  preference (dark or light) and set the theme accordingly.

The new `main.js` takes care of the actual theme switching and listening
to system preference changes (if the user has not manually set a theme).

Now the icons are stored in CSS, and are set according to the current
theme. This allows for having different icons that dynamically switch.

Additionally, wraps social and navigation elements in ul/li.

Fixes #76
main
welpo 2 years ago
parent eb63718bbf
commit 1efb0330e3
No known key found for this signature in database
GPG Key ID: A2F978CF4EC1F5A6

@ -62,7 +62,7 @@ socials = [
# Default config, allows for https remote images and embedding YouTube and Vimeo content. # Default config, allows for https remote images and embedding YouTube and Vimeo content.
# This configuration (along with the right webserver settings) gets an A+ in Mozilla's Observatory: https://observatory.mozilla.org # This configuration (along with the right webserver settings) gets an A+ in Mozilla's Observatory: https://observatory.mozilla.org
allowed_domains = [ allowed_domains = [
{ directive = "img-src", domains = ["'self'", "https://*"] }, { directive = "img-src", domains = ["'self'", "https://*", "data:"] },
{ directive = "script-src", domains = ["'self'"] }, { directive = "script-src", domains = ["'self'"] },
{ directive = "style-src", domains = ["'self'"] }, { directive = "style-src", domains = ["'self'"] },
{ directive = "frame-src", domains = ["player.vimeo.com", "https://www.youtube-nocookie.com"] }, { directive = "frame-src", domains = ["player.vimeo.com", "https://www.youtube-nocookie.com"] },

@ -1,7 +1,7 @@
+++ +++
title = "Almost no JavaScript" title = "Almost no JavaScript"
date = 2023-01-06 date = 2023-01-06
updated = 2023-04-15 updated = 2023-04-28
description = "JavaScript is only used when HTML and CSS aren't enough." description = "JavaScript is only used when HTML and CSS aren't enough."
[taxonomies] [taxonomies]
@ -10,8 +10,8 @@ tags = ["showcase"]
# JavaScript? # JavaScript?
This theme has almost no JavaScript. It includes a ~950 byte `.js` file with the logic for the light/dark mode switch which can be disabled by setting `theme_switcher = false` in the `config.toml` file. This theme has almost no JavaScript. It includes ~900 bytes of `.js` with the logic for the light/dark mode switch, which can be disabled by setting `theme_switcher = false` in the `config.toml` file.
KaTex support, which requires JavaScript, can be activated for specific posts. KaTex support, which requires loading a 274 KB JavaScript file, can be activated for specific posts.
Other than that, it's a fast site with HTML and CSS. Just the way (most of) the web should be :-) Other than that, it's a fast site with HTML and CSS. Just the way (most of) the web should be :-)

@ -62,6 +62,8 @@
--quote-color: #355f62; --quote-color: #355f62;
--border-color: #727272; --border-color: #727272;
--meta-color: #5b5b65; --meta-color: #5b5b65;
--theme-switcher-svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M283.211 512c78.962 0 151.079-35.925 198.857-94.792 7.068-8.708-.639-21.43-11.562-19.35-124.203 23.654-238.262-71.576-238.262-196.954 0-72.222 38.662-138.635 101.498-174.394 9.686-5.512 7.25-20.197-3.756-22.23A258.156 258.156 0 0 0 283.211 0c-141.309 0-256 114.511-256 256 0 141.309 114.511 256 256 256z'/%3E%3C/svg%3E%0A");
} }
[data-theme='dark'] { [data-theme='dark'] {
@ -78,6 +80,8 @@
--border-color: black; --border-color: black;
--meta-color: #B0B0B0; --meta-color: #B0B0B0;
--theme-switcher-svg: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 96 960 960' %3E%3Cpath d='M480 776q-83 0-141.5-58.5T280 576q0-83 58.5-141.5T480 376q83 0 141.5 58.5T680 576q0 83-58.5 141.5T480 776ZM80 616q-17 0-28.5-11.5T40 576q0-17 11.5-28.5T80 536h80q17 0 28.5 11.5T200 576q0 17-11.5 28.5T160 616H80Zm720 0q-17 0-28.5-11.5T760 576q0-17 11.5-28.5T800 536h80q17 0 28.5 11.5T920 576q0 17-11.5 28.5T880 616h-80ZM480 296q-17 0-28.5-11.5T440 256v-80q0-17 11.5-28.5T480 136q17 0 28.5 11.5T520 176v80q0 17-11.5 28.5T480 296Zm0 720q-17 0-28.5-11.5T440 976v-80q0-17 11.5-28.5T480 856q17 0 28.5 11.5T520 896v80q0 17-11.5 28.5T480 1016ZM226 378l-43-42q-12-11-11.5-28t11.5-29q12-12 29-12t28 12l42 43q11 12 11 28t-11 28q-11 12-27.5 11.5T226 378Zm494 495-42-43q-11-12-11-28.5t11-27.5q11-12 27.5-11.5T734 774l43 42q12 11 11.5 28T777 873q-12 12-29 12t-28-12Zm-42-495q-12-11-11.5-27.5T678 322l42-43q11-12 28-11.5t29 11.5q12 12 12 29t-12 28l-43 42q-12 11-28 11t-28-11ZM183 873q-12-12-12-29t12-28l43-42q12-11 28.5-11t27.5 11q12 11 11.5 27.5T282 830l-42 43q-11 12-28 11.5T183 873Z'/%3E%3C/svg%3E");
.invertible-image { .invertible-image {
filter: invert(.88); filter: invert(.88);
} }

@ -13,7 +13,6 @@ footer section {
footer nav { footer nav {
display: flex; display: flex;
gap: 0rem;
margin: 0 0rem; margin: 0 0rem;
} }
@ -23,6 +22,10 @@ footer nav {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
align-items: flex-end; align-items: flex-end;
ul {
gap: 5px;
}
} }
.social { .social {

@ -43,10 +43,16 @@ header {
.nav-navs { .nav-navs {
display: flex; display: flex;
gap: 5px; flex-wrap: wrap;
img { ul {
border: none; display: flex;
align-items: center;
gap: 1px;
flex-wrap: wrap;
list-style: none;
padding: 0;
margin: 0;
} }
} }
@ -57,6 +63,7 @@ header {
justify-content: right; justify-content: right;
color: var(--text-color); color: var(--text-color);
padding: 0.66rem; padding: 0.66rem;
line-height: 2.5;
} }
.home-title { .home-title {
@ -114,6 +121,7 @@ header {
margin-top: 0.8rem; margin-top: 0.8rem;
width: 100%; width: 100%;
justify-content: center; justify-content: center;
flex-wrap: wrap;
} }
.navbar { .navbar {

@ -5,43 +5,6 @@
height: 1rem; height: 1rem;
position: relative; position: relative;
cursor: pointer; cursor: pointer;
-webkit-mask: var(--theme-switcher-svg);
.switch { background: var(--text-color);
width: 1rem;
height: 1rem;
position: absolute;
left: 0px;
display: flex;
justify-content: center;
align-items: center;
img {
width: 100%;
height: auto;
position: absolute;
border: none;
}
.sun {
opacity: 0;
}
.moon {
opacity: 1;
}
}
input {
display: none;
&:checked + .switch {
.sun {
opacity: 1;
}
.moon {
opacity: 0;
}
}
}
} }

@ -0,0 +1,9 @@
(function () {
let currentTheme = localStorage.getItem('theme');
if (currentTheme) {
document.documentElement.setAttribute('data-theme', currentTheme);
} else {
const isSystemDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
document.documentElement.setAttribute('data-theme', isSystemDark ? 'dark' : 'light');
}
})();

@ -0,0 +1 @@
!function(){let e=localStorage.getItem("theme");if(e)document.documentElement.setAttribute("data-theme",e);else{let t=window.matchMedia("(prefers-color-scheme: dark)").matches;document.documentElement.setAttribute("data-theme",t?"dark":"light")}}();

@ -1,28 +1,20 @@
const themeSwitcher = document.querySelector('.theme-switcher input'); const themeSwitcher = document.querySelector('.theme-switcher');
let currentTheme = localStorage.getItem('theme'); let currentTheme = localStorage.getItem('theme');
let userHasManuallyChangedTheme = currentTheme !== null; let userHasManuallyChangedTheme = currentTheme !== null;
function setTheme(theme) { function setTheme(theme) {
document.documentElement.setAttribute('data-theme', theme); document.documentElement.setAttribute('data-theme', theme);
themeSwitcher.checked = theme === 'dark';
localStorage.setItem('theme', theme); localStorage.setItem('theme', theme);
currentTheme = theme; currentTheme = theme;
} }
if (currentTheme) { function switchTheme() {
setTheme(currentTheme); const newTheme = currentTheme === 'dark' ? 'light' : 'dark';
} else {
const isSystemDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
setTheme(isSystemDark ? 'dark' : 'light');
}
function switchTheme(e) {
const newTheme = e.target.checked ? 'dark' : 'light';
setTheme(newTheme); setTheme(newTheme);
userHasManuallyChangedTheme = true; userHasManuallyChangedTheme = true;
} }
themeSwitcher.addEventListener('change', switchTheme, false); themeSwitcher.addEventListener('click', switchTheme, false);
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => { window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
if (!userHasManuallyChangedTheme) { if (!userHasManuallyChangedTheme) {

@ -0,0 +1 @@
const themeSwitcher=document.querySelector(".theme-switcher");let currentTheme=localStorage.getItem("theme"),userHasManuallyChangedTheme=null!==currentTheme;function setTheme(e){document.documentElement.setAttribute("data-theme",e),localStorage.setItem("theme",e),currentTheme=e}function switchTheme(){let e="dark"===currentTheme?"light":"dark";setTheme(e),userHasManuallyChangedTheme=!0}themeSwitcher.addEventListener("click",switchTheme,!1),window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change",e=>{userHasManuallyChangedTheme||setTheme(e.matches?"dark":"light")});

@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<path d="M283.211 512c78.962 0 151.079-35.925 198.857-94.792 7.068-8.708-.639-21.43-11.562-19.35-124.203 23.654-238.262-71.576-238.262-196.954 0-72.222 38.662-138.635 101.498-174.394 9.686-5.512 7.25-20.197-3.756-22.23A258.156 258.156 0 0 0 283.211 0c-141.309 0-256 114.511-256 256 0 141.309 114.511 256 256 256z"/>
</svg>

Before

Width:  |  Height:  |  Size: 388 B

@ -1 +0,0 @@
<svg height="24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="m12 17q-2.07 0-3.54-1.46-1.46-1.47-1.46-3.54t1.46-3.54q1.47-1.46 3.54-1.46t3.54 1.46q1.46 1.47 1.46 3.54 0 2.07-1.46 3.54-1.47 1.46-3.54 1.46zm-10-4q-.43 0-.71-.29-.29-.28-.29-.71t.29-.71q.29-.29.71-.29h2q.42 0 .71.29.29.28.29.71t-.29.71q-.29.29-.71.29zm18 0q-.43 0-.71-.29-.29-.28-.29-.71t.29-.71q.28-.29.71-.29h2q.43 0 .71.29.29.29.29.71t-.29.71q-.28.29-.71.29zm-8-8q-.43 0-.71-.29-.29-.29-.29-.71v-2q0-.43.29-.71.28-.29.71-.29t.71.29q.29.29.29.71v2q0 .42-.29.71-.28.29-.71.29zm0 18q-.43 0-.71-.29-.29-.28-.29-.71v-2q0-.43.29-.71.28-.29.71-.29t.71.29q.29.28.29.71v2q0 .43-.29.71-.28.29-.71.29zm-6.35-15.95-1.07-1.05q-.3-.28-.29-.7.01-.42.29-.72.3-.3.72-.3t.7.3l1.05 1.07q.28.3.28.7 0 .4-.28.7-.28.3-.69.29-.41-.01-.71-.29zm12.35 12.38-1.05-1.08q-.27-.3-.27-.71 0-.41.27-.69.27-.3.69-.29.41.02.71.29l1.08 1.05q.3.27.28.7-.01.43-.28.73-.3.3-.73.3t-.7-.3zm-1.05-12.38q-.3-.27-.29-.69.02-.41.29-.71l1.05-1.07q.27-.3.7-.29.43.01.73.29.3.3.3.72t-.3.7l-1.08 1.05q-.3.28-.7.28-.4 0-.7-.28zm-12.38 12.38q-.3-.3-.3-.73t.3-.7l1.08-1.05q.3-.27.71-.27.41 0 .69.27.3.27.29.69-.01.41-.29.71l-1.05 1.08q-.28.3-.7.28-.42-.01-.72-.28z" fill="#fff"/></svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

@ -2,18 +2,19 @@
<section> <section>
<nav class="socials nav-navs"> <nav class="socials nav-navs">
{%- if config.extra.socials %} {%- if config.extra.socials %}
{% for social in config.extra.socials %} <ul>
<a rel="noopener noreferrer" target="_blank" class="nav-links no-hover-padding social" href={{ social.url | safe | replace(from="$BASE_URL", to=config.base_url) }}> {% for social in config.extra.socials %}
<img alt={{ social.name }} title={{ social.name }} src="{{config.base_url}}/social_icons/{{ social.icon }}.svg"> <li>
</a> <a rel="noopener noreferrer" target="_blank" class="nav-links no-hover-padding social" href={{ social.url | safe | replace(from="$BASE_URL", to=config.base_url) }}>
{% endfor %} <img alt={{ social.name }} title={{ social.name }} src="{{config.base_url}}/social_icons/{{ social.icon }}.svg">
</a>
</li>
{% endfor %}
</ul>
{% endif %} {% endif %}
</nav> </nav>
<div class="credits"> <div class="credits">
<small>Powered by <a href="https://www.getzola.org" target="_blank">Zola</a> & <a href="https://github.com/welpo/tabi" target="_blank">tabi</a></small> <small>Powered by <a href="https://www.getzola.org" target="_blank">Zola</a> & <a href="https://github.com/welpo/tabi" target="_blank">tabi</a></small>
</div> </div>
</section> </section>
{%- if config.extra.theme_switcher == true -%}
<script src="{{ get_url(path='js/main.js', trailing_slash=false) | safe }}"/></script>
{%- endif -%}
</footer> </footer>

@ -55,4 +55,9 @@
{%- endfor -%} {%- endfor -%}
{%- endif -%}"> {%- endif -%}">
{%- if config.extra.theme_switcher == true -%}
<script type="text/javascript" src="{{ get_url(path='js/initialize_theme_min.js') | safe }}"></script>
<script defer src="{{ get_url(path='js/main_min.js', trailing_slash=false) | safe }}"/></script>
{%- endif -%}
</head> </head>

@ -6,23 +6,19 @@
{%- if config.extra.menu %} {%- if config.extra.menu %}
<div class="nav-navs"> <div class="nav-navs">
<div> <ul>
{% for menu in config.extra.menu %} {% for menu in config.extra.menu %}
<a class="nav-links no-hover-padding" href={{ menu.url | safe | replace(from="$BASE_URL" , to=config.base_url) }}>{{ menu.name <li>
}}</a> <a class="nav-links no-hover-padding" href={{ menu.url | safe | replace(from="$BASE_URL" , to=config.base_url) }}>{{ menu.name }}</a>
</li>
{% endfor %} {% endfor %}
</div> {%- if config.extra.theme_switcher == true -%}
{%- if config.extra.theme_switcher == true -%} <li class="theme-switcher-wrapper">
<label class="theme-switcher" for="themeswitch"> <div class="theme-switcher"></div>
<input type="checkbox" id="themeswitch"> </li>
<div class="switch"> {%- endif -%}
<img alt="set dark theme" class="moon" src="{{ config.base_url }}/menu_icon/moon.svg"> </ul>
<img alt="set light theme" class="sun" src="{{ config.base_url }}/menu_icon/sun.svg">
</div>
{%- endif -%}
</label>
</div> </div>
{% endif %} {% endif %}
</nav> </nav>
</header> </header>

Loading…
Cancel
Save