settle on a dark theme and implement with override

This commit is contained in:
2026-03-08 10:55:41 -04:00
parent 0f5dadbf6f
commit 0070ed1c19
3 changed files with 98 additions and 215 deletions

View File

@@ -1,65 +0,0 @@
---
---
<div class="theme-switcher">
<label for="theme-select">Theme</label>
<select id="theme-select">
<option value="">Light</option>
<option value="cool">Cool</option>
<option value="midnight-garden">Midnight Garden</option>
<option value="stormfront">Stormfront</option>
<option value="copper-slate">Copper &amp; Slate</option>
<option value="northern-lights">Northern Lights</option>
<option value="obsidian">Obsidian</option>
<option value="mocha">Mocha</option>
<option value="deep-ocean">Deep Ocean</option>
</select>
</div>
<style>
.theme-switcher {
position: fixed;
top: 0.5rem;
right: 0.5rem;
z-index: 1000;
display: flex;
align-items: center;
gap: 0.4rem;
padding: 0.25rem 0.5rem;
border-radius: 0.25rem;
background: var(--bg-color);
border: 1px solid var(--content-color-faded);
font-size: 0.75rem;
}
label {
color: var(--content-color-faded);
font-size: 0.7rem;
text-transform: uppercase;
letter-spacing: 0.05em;
}
select {
background: var(--bg-color);
color: var(--content-color);
border: none;
font-size: 0.75rem;
font-family: inherit;
cursor: pointer;
padding: 0.1rem;
}
</style>
<script>
const select = document.getElementById('theme-select') as HTMLSelectElement;
const saved = localStorage.getItem('theme');
if (saved !== null) {
document.documentElement.setAttribute('data-theme', saved);
select.value = saved;
}
select.addEventListener('change', () => {
const theme = select.value;
document.documentElement.setAttribute('data-theme', theme);
localStorage.setItem('theme', theme);
});
</script>

View File

@@ -1,55 +1,71 @@
---
import '@styles/main.css';
import ThemeSwitcher from '@components/ThemeSwitcher.astro';
import '@fontsource-variable/baskervville';
import '@fontsource-variable/baskervville-sc';
---
<style>
header {
background-color: var(--primary-color-faded);
border-bottom: var(--header-border-width) solid var(--header-border-color);
}
nav {
max-width: 30rem;
margin: 0 auto;
display: flex;
justify-content: space-between;
& a {
flex: 1;
max-width: 8rem;
padding: 0.25rem 1rem;
font-size: 1.75rem;
color: white;
text-decoration: none;
text-align: center;
&:hover {
background: var(--nav-hover);
color: var(--nav-hover-color);
}
}
}
</style>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<!-- avoid FOUC by setting the color schme here in the header -->
<script>
const pref = localStorage.getItem('theme-preference');
if (pref) {
document.documentElement.dataset.theme = pref;
}
</script>
{/* Note: The styles are inside the document here because otherwise it breaks Astro's parsing */}
<style>
header {
background-color: var(--primary-color-faded);
padding: 0.5rem var(--content-padding);
}
nav {
max-width: var(--content-width);
margin: 0 auto;
display: flex;
gap: 1.5rem;
align-items: baseline;
& a {
font-family: 'Baskervville Variable';
font-weight: 600;
font-size: 1.3rem;
color: var(--nav-link-color);
text-decoration: underline;
text-underline-offset: 0.5rem;
/*border-bottom: 2px solid transparent;*/
text-decoration-color: transparent;
transition: text-decoration-color 0.2s ease, opacity 0.2s ease;
&.home {
font-family: 'Baskervville SC Variable';
font-size: 2rem;
margin-right: auto;
}
&:hover, &:active {
text-decoration-color: var(--accent-color);
/*border-bottom-color: var(--accent-color);*/
}
}
}
</style>
</head>
<body>
<header>
<nav>
<a href="/" data-astro-prefetch>Home</a>
<a href="/" class="home" data-astro-prefetch>Joe's Blog</a>
<a href="/posts" data-astro-prefetch>Posts</a>
<a href="/about" data-astro-prefetch>About</a>
</nav>
</header>
<ThemeSwitcher />
<main>
<slot />
</main>

View File

@@ -4,129 +4,61 @@
--content-line-height: 1.5;
--content-width: 52.5rem;
--content-padding: 0.65rem;
--bg-color: hsl(0deg 0% 100%);
--content-color: hsl(0deg 0% 20%);
--content-color-faded: #555;
--heading-color: hsl(0deg 0% 27%);
--primary-color: hsl(202deg 72% 28%);
--primary-color-faded: hsl(202deg 14% 36%);
--accent-color: hsl(0deg 92% 29%);
--accent-color-faded: hsl(0deg 25% 55%);
--nav-hover: hsl(0deg 0% 0% / 10%);
--nav-hover-color: white;
--header-border-width: 0;
--header-border-color: transparent;
/* squish things down a little on mobile so more text fits on the screen */
@media(max-width: 640px) {
--content-line-height: 1.25;
--content-size: 1.15rem;
--content-size-sm: 0.9rem;
}
}
/* v1: Cool */
[data-theme="cool"] {
--bg-color: hsl(210deg 12% 12%);
--content-color: hsl(0deg 0% 82%);
--content-color-faded: hsl(0deg 0% 60%);
--heading-color: hsl(0deg 0% 90%);
--primary-color: hsl(202deg 50% 50%);
--primary-color-faded: hsl(202deg 14% 22%);
--accent-color: hsl(0deg 72% 55%);
--accent-color-faded: hsl(0deg 20% 60%);
--nav-hover: hsl(0deg 0% 100% / 12%);
}
/* light-mode colors */
--bg-color: hsl(0deg 0% 100%);
/* text */
--content-color: hsl(0deg 0% 20%);
--content-color-faded: #555;
/* links */
--primary-color: hsl(202deg 72% 28%);
--primary-color-faded: hsl(202deg 14% 36%);
/* indicators, hover effects, etc */
--accent-color: hsl(0deg 92% 29%);
--accent-color-faded: hsl(0deg 25% 55%);
/* misc */
--heading-color: hsl(0deg 0% 27%);
--nav-link-color: white;
/* v6: Midnight Garden */
[data-theme="midnight-garden"] {
--bg-color: hsl(160deg 15% 9%);
--content-color: hsl(100deg 8% 78%);
--content-color-faded: hsl(110deg 5% 52%);
--heading-color: hsl(45deg 20% 90%);
--primary-color: hsl(155deg 30% 35%);
--primary-color-faded: hsl(155deg 20% 14%);
--accent-color: hsl(340deg 45% 65%);
--accent-color-faded: hsl(340deg 20% 50%);
--nav-hover: hsl(155deg 15% 100% / 10%);
}
/* dark-mode colors (defined here so that we only have to update them in one place) */
--dark-bg-color: hsl(220deg 10% 13%);
--dark-content-color: hsl(30deg 10% 75%);
--dark-content-color-faded: hsl(25deg 6% 50%);
--dark-primary-color: hsl(220deg 15% 40%);
--dark-primary-color-faded: hsl(220deg 12% 18%);
--dark-accent-color: hsl(18deg 70% 55%);
--dark-accent-color-faded: hsl(18deg 30% 45%);
--dark-heading-color: hsl(35deg 25% 88%);
--dark-nav-link-color: var(--dark-heading-color);
/* v7: Stormfront */
[data-theme="stormfront"] {
--bg-color: hsl(0deg 0% 8%);
--content-color: hsl(0deg 0% 75%);
--content-color-faded: hsl(0deg 0% 50%);
--heading-color: hsl(0deg 0% 95%);
--primary-color: hsl(270deg 60% 60%);
--primary-color-faded: hsl(0deg 0% 8%);
--accent-color: hsl(270deg 75% 65%);
--accent-color-faded: hsl(270deg 25% 50%);
--nav-hover: hsl(270deg 30% 100% / 10%);
--nav-hover-color: var(--accent-color);
--header-border-width: 2px;
--header-border-color: var(--accent-color);
}
&[data-theme="dark"] {
--bg-color: var(--dark-bg-color);
--content-color: var(--dark-content-color);
--content-color-faded: var(--dark-content-color-faded);
--primary-color: var(--dark-primary-color);
--primary-color-faded: var(--dark-primary-color-faded);
--accent-color: var(--dark-accent-color);
--accent-color-faded: var(--accent-color-faded);
--heading-color: var(--dark-heading-color);
}
/* v8: Copper & Slate */
[data-theme="copper-slate"] {
--bg-color: hsl(220deg 10% 13%);
--content-color: hsl(30deg 10% 75%);
--content-color-faded: hsl(25deg 6% 50%);
--heading-color: hsl(35deg 25% 88%);
--primary-color: hsl(220deg 15% 40%);
--primary-color-faded: hsl(220deg 12% 18%);
--accent-color: hsl(18deg 70% 55%);
--accent-color-faded: hsl(18deg 30% 45%);
--nav-hover: hsl(20deg 15% 100% / 10%);
}
/* v9: Northern Lights */
[data-theme="northern-lights"] {
--bg-color: hsl(230deg 20% 10%);
--content-color: hsl(200deg 12% 75%);
--content-color-faded: hsl(200deg 8% 50%);
--heading-color: hsl(260deg 15% 90%);
--primary-color: hsl(230deg 25% 40%);
--primary-color-faded: hsl(230deg 18% 15%);
--accent-color: hsl(175deg 65% 50%);
--accent-color-faded: hsl(175deg 25% 42%);
--nav-hover: hsl(175deg 20% 100% / 10%);
}
/* v10: Obsidian */
[data-theme="obsidian"] {
--bg-color: hsl(0deg 0% 5%);
--content-color: hsl(0deg 0% 88%);
--content-color-faded: hsl(0deg 0% 55%);
--heading-color: hsl(0deg 0% 98%);
--primary-color: hsl(200deg 10% 40%);
--primary-color-faded: hsl(200deg 10% 15%);
--accent-color: hsl(210deg 100% 65%);
--accent-color-faded: hsl(210deg 30% 50%);
--nav-hover: hsl(0deg 0% 100% / 8%);
}
/* v11: Mocha */
[data-theme="mocha"] {
--bg-color: hsl(30deg 12% 12%);
--content-color: hsl(35deg 15% 80%);
--content-color-faded: hsl(35deg 10% 55%);
--heading-color: hsl(40deg 30% 90%);
--primary-color: hsl(25deg 20% 45%);
--primary-color-faded: hsl(25deg 15% 20%);
--accent-color: hsl(15deg 65% 60%);
--accent-color-faded: hsl(15deg 30% 50%);
--nav-hover: hsl(35deg 20% 100% / 8%);
}
/* v12: Deep Ocean */
[data-theme="deep-ocean"] {
--bg-color: hsl(225deg 25% 10%);
--content-color: hsl(220deg 15% 82%);
--content-color-faded: hsl(220deg 10% 60%);
--heading-color: hsl(220deg 25% 95%);
--primary-color: hsl(225deg 40% 50%);
--primary-color-faded: hsl(225deg 30% 18%);
--accent-color: hsl(330deg 75% 65%);
--accent-color-faded: hsl(330deg 35% 55%);
--nav-hover: hsl(220deg 20% 100% / 10%);
&:not([data-theme="light"]) {
@media(prefers-color-scheme: dark) {
--bg-color: var(--dark-bg-color);
--content-color: var(--dark-content-color);
--content-color-faded: var(--dark-content-color-faded);
--primary-color: var(--dark-primary-color);
--primary-color-faded: var(--dark-primary-color-faded);
--accent-color: var(--dark-accent-color);
--accent-color-faded: var(--accent-color-faded);
--heading-color: var(--dark-heading-color);
}
}
}