So I finally hacked in some dark mode support, only to run into another odd quirk: the syntax blocks wouldn’t change.
What gives? The various Nuxt module websites all have code examples that all switch beautifully to a dark theme when the system is in dark mode or the user switches to dark mode through a selector in the header, yet on my lil’ webpage things were broken.
The dark mode selector on the nuxt module websites are powered by @nuxtjs/color-mode
. This relatively lightweight module effectively just keeps a class
on the html
element in sync the users device preference and offers a composable so you can change it in runtime. This allows you to do things like:
<script lang="ts" setup>
const colorMode = useColorMode();
</script>
<template>
<div>
<h1>Color mode: {{ $colorMode.value }}</h1>
<select v-model="$colorMode.preference">
<option value="system">System</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
</div>
</template>
According to the docs, @nuxt/content
’s syntax highlighting is natively compatible with this library. However.. this didn’t seem to be the case on my end.
After no more than 15 minutes of reverse engineering, I realized all the previously mentioned Nuxt module websites have two things in common: they all use .dark
on the html
element rather than @nuxtjs/color-mode
’s default .dark-mode
, and they all use @nuxt/ui
. Turns out @nuxt/content
relies on the html class being called .dark
to influence shiki’s theme. @nuxtjs/color-mode
has an option classSuffix
which is set to "-mode"
by default, which in turn breaks the syntax highlighting from working properly.
Easiest workaround is to just set classSuffix
back to ""
in your nuxt.config.ts
:
export default defineNuxtConfig({
// ...
colorMode: { classSuffix: "" },
});
This in turn makes the html class .dark
, which makes it work with @nuxt/content
’s usage of shiki
.
When you use Nuxt UI, it’s colorMode
option allows you to opt-in to having @nuxtjs/color-mode
available without having to install it as a separate module. This makes sense as @nuxt/ui
’s pro version itself has some components included that rely on color mode being present, like ColorModeAvatar
and ColorModeSwitch
. However, when you opt-in to colorMode
through @nuxt/ui
, it actually overrides classSuffix
back to ""
on your behalf! This is why the Nuxt module websites and any other projects that use @nuxt/ui
all work without a problem out of the box.