This article is part of a series about building my personal website:

  1. The idea and choosing the right tool
  2. SEO essentials: meta tags and base head element
  3. Content management with Markdown and Frontmatter
  4. Semantic HTML for accessibility and external readers
  5. Minimalist CSS: styling and native-like design
  6. Adding color themes with JavaScript
  7. Astro plugins: RSS, Sitemap, Word count
  8. SVG icons and Favicon
  9. Building resume with XeLaTeX
  10. Extras

Astro ships 0 JavaScript by default, which I love. For a simple website like mine, most things don’t require JavaScript at all.

But some interactions are only possible with it - like switching color themes dynamically.

Theme switching logic

I added a <select> element where users can choose a theme. Whenever they select a different option, the website should:

  1. Update the colors instantly.
  2. Save the choice so it persists across page reloads (my site is a multi-page app, so state isn’t preserved automatically).

Here’s the script I use:

const theme = localStorage.getItem("theme") ?? "system";
document.documentElement.dataset.theme = theme;

const selector = document.querySelector(
  "select#theme-selector"
) as HTMLSelectElement | null;

if (selector !== null) {
  selector.value = theme;

  selector.addEventListener("change", () => {
    const value = selector.value;
    localStorage.setItem("theme", value);
    document.documentElement.dataset.theme = value;
  });
}

This way, the site remembers the theme until the user clears browser storage.

Bonus: a little easter egg 🌿

Just for fun, I added this line:

console.log("%c🌿", "font-size: 8em");

Open the browser console and you’ll see a giant leaf emoji printed out.