Leveraging Astro's astro:after-swap for Persistent Dark Mode Across View Transitions


Astro’s capabilities for creating websites with smooth, single-page application-like transitions can greatly enhance user experience. These transitions make navigating a static site feel incredibly fluid, similar to an interactive application. A common enhancement in modern web development is supporting a dark mode, and maintaining this setting across page transitions can sometimes present challenges. In this blog post, we’ll discuss how to use the astro:after-swap event in Astro to persist user preferences for dark mode across different pages.

The Challenge with Dark Mode and View Transitions

When implementing a toggleable dark mode on an Astro site, developers might encounter an issue where the user’s theme preference doesn’t persist when navigating to different pages. This issue typically arises when the theme setting is stored in the session storage and each new page load resets to the default theme, often the light mode.

This can frustrate users who expect their preference for dark mode to be remembered as they navigate through the site. Here’s how you can solve this problem using Astro’s astro:after-swap event.

Implementing a Persistent Dark Mode

The key to solving the dark mode persistence issue is to ensure that the dark mode setting is applied not only on initial page load but also after each view transition. Here’s a step-by-step guide on how to implement this:

1. Detecting User Preference and System Settings

First, determine the user’s preferred theme by checking the session storage and the system color scheme. If a user has not set a preference, the system preference can be used as a default:

const setDarkMode = () => {
  if (typeof window !== "undefined") {
    const isSystemColorSchemeDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
    const storageTheme = sessionStorage.getItem("theme");
    if (!storageTheme && isSystemColorSchemeDark) {
      document.documentElement.classList.add("dark");
      document.head.children.namedItem("theme-color").content = "#262626";
    } else if (storageTheme === "dark") {
      document.documentElement.classList.add("dark");
      document.head.children.namedItem("theme-color").content = "#262626";
    } else {
      // we already server render light theme
      document.head.children.namedItem("theme-color").content = "#ffffff";
    }
  }
};

2. Applying the Setting on Initial Load and View Transitions

To ensure that the dark mode setting is applied consistently across the site, invoke the setDarkMode function on both the initial page load and after each page swap using the astro:after-swap event:

// Runs on initial navigation
setDarkMode();

// Runs on view transitions navigation
document.addEventListener('astro:after-swap', setDarkMode);

This script ensures that every time a user navigates to a new page within the Astro site, the dark mode preference is checked and applied correctly, making the transition seamless and preserving the user’s desired theme.

Conclusion

By using the astro:after-swap event, developers can enhance the functionality of their Astro sites, ensuring that user preferences like dark mode are consistently maintained across all pages and view transitions. This not only improves the user experience but also showcases the flexibility and power of Astro in building dynamic, user-friendly websites.

This solution ensures that user preferences for visual themes are respected throughout the site, solving the common problem of preference resets on new page loads and enhancing the overall usability of your Astro-built site.