add manual light/dark toggle
This commit is contained in:
parent
5634b290cd
commit
e5f29ff84b
3 changed files with 80 additions and 59 deletions
|
@ -2,6 +2,18 @@
|
||||||
@import url(fonts/ftaurebesh/ftaurebesh.css);
|
@import url(fonts/ftaurebesh/ftaurebesh.css);
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
|
font-size: 16px;
|
||||||
|
font-size: clamp(16px, 8px + 1.5vw, 24px);
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 100vh;
|
||||||
|
flex-grow: 1;
|
||||||
|
padding: 0;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
--c-highlight: hsl(0 0% 100% / 87.5%);
|
--c-highlight: hsl(0 0% 100% / 87.5%);
|
||||||
--c-dark: hsl(217 17% 21%);
|
--c-dark: hsl(217 17% 21%);
|
||||||
--c-accent: hsl(14 62% 53%);
|
--c-accent: hsl(14 62% 53%);
|
||||||
|
@ -11,15 +23,6 @@
|
||||||
--c-text-light: var(--c-highlight);
|
--c-text-light: var(--c-highlight);
|
||||||
--c-text-dark: var(--c-dark);
|
--c-text-dark: var(--c-dark);
|
||||||
|
|
||||||
box-sizing: border-box;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
min-height: 100vh;
|
|
||||||
flex-grow: 1;
|
|
||||||
padding: 0;
|
|
||||||
font-size: 16px;
|
|
||||||
font-size: clamp(16px, 8px + 1.5vw, 24px);
|
|
||||||
line-height: 1.5;
|
|
||||||
--ratio: 1.333;
|
--ratio: 1.333;
|
||||||
--s-5: calc(var(--s-4) / var(--ratio));
|
--s-5: calc(var(--s-4) / var(--ratio));
|
||||||
--s-4: calc(var(--s-3) / var(--ratio));
|
--s-4: calc(var(--s-3) / var(--ratio));
|
||||||
|
@ -34,34 +37,26 @@
|
||||||
--s5: calc(var(--s4) * var(--ratio));
|
--s5: calc(var(--s4) * var(--ratio));
|
||||||
--content-width: clamp(75vw, 40rem, 100vw - 3rem);
|
--content-width: clamp(75vw, 40rem, 100vw - 3rem);
|
||||||
--inset: calc(50vw - var(--content-width) / 2);
|
--inset: calc(50vw - var(--content-width) / 2);
|
||||||
--scrollLengthPx: 0;
|
|
||||||
--cloudyHeaderBottom: max(35vh, 10rem);
|
--cloudyHeaderBottom: max(35vh, 10rem);
|
||||||
}
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
|
||||||
:root {
|
|
||||||
--c-highlight: hsl(60 20% 60% / 50%);
|
|
||||||
--c-dark: hsl(217 9% 8%);
|
|
||||||
--c-accent: hsl(220 20% 35%);
|
|
||||||
--c-light: hsl(220 50% 10%);
|
|
||||||
|
|
||||||
--c-text-background-light: hsl(220 40% 10% / 40%);
|
|
||||||
--c-text-light: hsl(60 50% 86.67%);
|
|
||||||
--c-text-dark: hsl(60 50% 86.67%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
background-size: 100% 80vh;
|
background-size: 100% 80vh;
|
||||||
background-position: top;
|
background-position: top;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-color: var(--c-light);
|
background-color: var(--c-light);
|
||||||
background-image: linear-gradient(to bottom, #4379ef, #859cc4);
|
background-image: linear-gradient(to bottom, #4379ef, #859cc4);
|
||||||
}
|
}
|
||||||
@media (prefers-color-scheme: dark) {
|
body[data-theme="dark"] {
|
||||||
body {
|
background: var(--c-light);
|
||||||
background: var(--c-light);
|
}
|
||||||
}
|
|
||||||
|
[data-theme="dark"] {
|
||||||
|
--c-highlight: hsl(60 20% 60% / 50%);
|
||||||
|
--c-dark: hsl(217 9% 8%);
|
||||||
|
--c-accent: hsl(220 20% 35%);
|
||||||
|
--c-light: hsl(220 50% 10%);
|
||||||
|
|
||||||
|
--c-text-background-light: hsl(220 40% 10% / 40%);
|
||||||
|
--c-text-light: hsl(60 50% 86.67%);
|
||||||
|
--c-text-dark: hsl(60 50% 86.67%);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media screen {
|
@media screen {
|
||||||
|
@ -69,7 +64,7 @@ body {
|
||||||
--durationSeconds: 120;
|
--durationSeconds: 120;
|
||||||
--duration: calc(var(--durationSeconds) * 1s);
|
--duration: calc(var(--durationSeconds) * 1s);
|
||||||
--viewPointDelta: min(
|
--viewPointDelta: min(
|
||||||
1px * var(--scrollLengthPx),
|
1px * var(--scrollLengthPx, 0),
|
||||||
var(--cloudyHeaderBottom)
|
var(--cloudyHeaderBottom)
|
||||||
);
|
);
|
||||||
--travelDistance: 90vh;
|
--travelDistance: 90vh;
|
||||||
|
@ -114,10 +109,8 @@ body {
|
||||||
animation-play-state: paused;
|
animation-play-state: paused;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@media (prefers-color-scheme: dark) {
|
[data-theme="dark"] & {
|
||||||
& {
|
background-image: url("./cloud-night.png");
|
||||||
background-image: url("./cloud-night.png");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,10 +125,8 @@ body {
|
||||||
transform: translateY(calc(-1 * var(--viewPointDelta)));
|
transform: translateY(calc(-1 * var(--viewPointDelta)));
|
||||||
will-change: translateY;
|
will-change: translateY;
|
||||||
}
|
}
|
||||||
@media (prefers-color-scheme: dark) {
|
[data-theme="dark"] #brand > * {
|
||||||
#brand > * {
|
text-shadow: 0 0 0.5em currentColor;
|
||||||
text-shadow: 0 0 0.5em currentColor;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,7 +375,7 @@ body > header > nav {
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 1ch;
|
gap: 1ch;
|
||||||
}
|
}
|
||||||
.nav-languages {
|
.nav-toggles {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
font-size: var(--s-1);
|
font-size: var(--s-1);
|
||||||
}
|
}
|
||||||
|
@ -484,7 +475,7 @@ label {
|
||||||
bottom: 110%;
|
bottom: 110%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.nav-language-button {
|
.nav-toggle-button {
|
||||||
margin-left: 0.5ch;
|
margin-left: 0.5ch;
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
|
@ -505,14 +496,14 @@ label {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[data-font="aurebesh"] {
|
[data-language="aurebesh"] {
|
||||||
font-family: FTAurebesh;
|
font-family: FTAurebesh;
|
||||||
line-height: 1.25;
|
line-height: 1.25;
|
||||||
ul > li {
|
ul:not(.collection) > li {
|
||||||
list-style-type: square;
|
list-style-type: square;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
[data-font="english"] {
|
[data-language="english"] {
|
||||||
font-family: Inter;
|
font-family: Inter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,22 +8,52 @@
|
||||||
<a href="{{ "/music" | url }}">/music</a>
|
<a href="{{ "/music" | url }}">/music</a>
|
||||||
<a href="{{ "/books" | url }}">/books</a>
|
<a href="{{ "/books" | url }}">/books</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="nav-languages">
|
<div class="nav-toggles">
|
||||||
<label class="nav-language-button" data-font="english">English<input type="radio" name="language" value="english"/></label>
|
<label class="nav-toggle-button">☀️<input type="radio" name="theme" value="light"/></label>
|
||||||
<label class="nav-language-button" data-font="aurebesh">Aurebesh<input type="radio" name="language" value="aurebesh"/></label>
|
<label class="nav-toggle-button">🌒<input type="radio" name="theme" value="dark"/></label>
|
||||||
|
/
|
||||||
|
<label class="nav-toggle-button" data-language="english">English<input type="radio" name="language" value="english"/></label>
|
||||||
|
<label class="nav-toggle-button" data-language="aurebesh">Aurebesh<input type="radio" name="language" value="aurebesh"/></label>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
const initialLanguage = localStorage.getItem("language") ?? 'english'
|
const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
|
||||||
document.body.setAttribute('data-font', initialLanguage);
|
const defaultPrefs = {
|
||||||
document.querySelectorAll("input[name=language]").forEach(input => {
|
language: 'english',
|
||||||
if (input.value === initialLanguage) {
|
theme: darkModeMediaQuery.matches
|
||||||
input.checked = true;
|
? 'dark'
|
||||||
}
|
: 'light'
|
||||||
input.addEventListener('change', function () {
|
};
|
||||||
const newValue = this.value;
|
Object.entries(defaultPrefs).forEach(([key, defaultPref]) => {
|
||||||
localStorage.setItem("language", newValue);
|
const currentPref = localStorage.getItem(key) ?? defaultPref;
|
||||||
document.body.setAttribute('data-font', newValue);
|
applyPreference(key, currentPref, false)
|
||||||
|
document.querySelectorAll(`input[name=${key}]`).forEach(input => {
|
||||||
|
input.addEventListener('change', (e) => {
|
||||||
|
applyPreference(key, e.currentTarget.value, true);
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
});
|
||||||
|
darkModeMediaQuery.addEventListener('change', e => {
|
||||||
|
if (localStorage.getItem('theme') != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
applyPreference(
|
||||||
|
'theme',
|
||||||
|
e.matches
|
||||||
|
? 'dark'
|
||||||
|
: 'light',
|
||||||
|
false
|
||||||
|
);
|
||||||
})
|
})
|
||||||
|
function applyPreference(key, value, shouldSave) {
|
||||||
|
document.body.setAttribute(`data-${key}`, value);
|
||||||
|
document.querySelectorAll(`input[name=${key}]`).forEach(input => {
|
||||||
|
if (input.value === value) {
|
||||||
|
input.checked = true;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (shouldSave) {
|
||||||
|
localStorage.setItem(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
|
@ -8,8 +8,8 @@ title: Joshua's Homepage
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<link rel="stylesheet" href="{{ "/site.css" | url }}?modified={{buildTime}}"/>
|
<link rel="stylesheet" href="{{ "/site.css" | url }}?modified={{buildTime}}"/>
|
||||||
<link rel="preload" media="light" href="{{ "./cloud.png" | url }}" as="image" />
|
<link rel="preload" media="(prefers-color-scheme: light)" href="{{ "./cloud.png" | url }}" as="image" />
|
||||||
<link rel="preload" media="dark" href="{{ "./cloud-night.png" | url }}" as="image" />
|
<link rel="preload" media="(prefers-color-scheme: dark)" href="{{ "./cloud-night.png" | url }}" as="image" />
|
||||||
<title>{{ computedTitle }} - {{ site.title }}</title>
|
<title>{{ computedTitle }} - {{ site.title }}</title>
|
||||||
<meta name="description" content="{{ description }}" />
|
<meta name="description" content="{{ description }}" />
|
||||||
<meta property="og:title" content="{{ computedTitle }}" />
|
<meta property="og:title" content="{{ computedTitle }}" />
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue