Expressive Code supports the full range of themes available for VS Code. Any theme that works in the editor will work in Expressive Code!
You can use our bundled themes , import themes from NPM , or export themes from VS Code .
Key features
Efficient multi-theme support : You can use multiple themes at the same time, e.g. a dark and a light theme for improved accessibility. In contrast to other popular solutions, this does not lead to duplicate HTML output with one block per theme. Instead, Expressive Code renders every code block once and uses optimized CSS variables to allow switching between themes.
Dark mode support : If you specify one dark and one light theme, Expressive Code automatically displays the theme that matches the user’s system preferences. You can configure this with the useDarkModeMediaQuery
option.
Theme switcher support : If your site has a theme switcher that allows users to pick a theme, Expressive Code can generate CSS code to support it. By default, you can use the data-theme
attribute to select a theme by name, both on the html
element and individual code blocks. You can configure this with the themeCssRoot
and themeCssSelector
options.
Automatic color contrast correction : Many themes you’ll find online do not meet the WCAG color contrast requirements for accessibility. Expressive Code fixes this by automatically processing the syntax highlighting colors of any theme to ensure a color contrast ratio of at least 5.5:1. You can configure this with the minSyntaxHighlightingColorContrast
option.
Using bundled themes
Expressive Code comes with a set of popular themes bundled with our default syntax highlighter. You can use them by passing their names to the themes
option:
import { defineConfig } from ' astro/config '
import astroExpressiveCode from ' astro-expressive-code '
export default defineConfig ( {
// Replace the default themes with a custom set of bundled themes:
// "dracula" (a dark theme) and "solarized-light"
themes: [ ' dracula ' , ' solarized-light ' ] ,
import { defineConfig } from ' astro/config '
import starlight from ' @astrojs/starlight '
export default defineConfig ( {
title: ' My Starlight site ' ,
// Replace the default themes with a custom set of bundled themes:
// "dracula" (a dark theme) and "solarized-light"
themes: [ ' dracula ' , ' solarized-light ' ] ,
import createMDX from ' @next/mdx '
import rehypeExpressiveCode from ' rehype-expressive-code '
/** @type { import ( 'rehype-expressive-code' ) .RehypeExpressiveCodeOptions } */
const rehypeExpressiveCodeOptions = {
// Replace the default themes with a custom set of bundled themes:
// "dracula" (a dark theme) and "solarized-light"
themes: [ ' dracula ' , ' solarized-light ' ] ,
/** @type { import ( 'next' ) .NextConfig } */
pageExtensions: [ " js " , " jsx " , " ts " , " tsx " , " md " , " mdx " ] ,
const withMDX = createMDX ( {
// The nested array structure is required to pass options
[ rehypeExpressiveCode, rehypeExpressiveCodeOptions ] ,
export default withMDX ( nextConfig )
Available themes
andromeeda
console . log ( ` ${ num } is even .` );
throw new Error ( 'Wait, what?' );
aurora-x
console . log ( `${ num } is even . ` ) ;
throw new Error ( ' Wait, what? ' ) ;
ayu-dark
console . log ( ` ${ num } is even .` ) ;
throw new Error ( 'Wait, what?' ) ;
catppuccin-frappe
console . log ( ` ${ num } is even .` ) ;
throw new Error ( 'Wait, what?' ) ;
catppuccin-latte
console . log ( ` ${ num } is even .` ) ;
throw new Error ( 'Wait, what?' ) ;
catppuccin-macchiato
console . log ( ` ${ num } is even .` ) ;
throw new Error ( 'Wait, what?' ) ;
catppuccin-mocha
console . log ( ` ${ num } is even .` ) ;
throw new Error ( 'Wait, what?' ) ;
dark-plus
console . log ( ` ${ num } is even .` );
throw new Error ( 'Wait, what?' );
dracula
console. log ( ` ${ num } is even .` );
throw new Error ( ' Wait, what? ' );
dracula-soft
console. log ( ` ${ num } is even .` );
throw new Error ( ' Wait, what? ' );
everforest-dark
console . log ( ` ${ num } is even .` );
throw new Error ( 'Wait, what?' );
everforest-light
console . log ( ` ${ num } is even .` );
throw new Error ( 'Wait, what?' );
github-dark
console. log ( `${ num } is even .` );
throw new Error ( 'Wait, what?' );
github-dark-default
console. log ( `${ num } is even .` );
throw new Error ( 'Wait, what?' );
github-dark-dimmed
console. log ( `${ num } is even .` );
throw new Error ( 'Wait, what?' );
github-dark-high-contrast
console. log ( `${ num } is even .` );
throw new Error ( 'Wait, what?' );
github-light
console. log ( `${ num } is even .` );
throw new Error ( 'Wait, what?' );
github-light-default
console. log ( `${ num } is even .` );
throw new Error ( 'Wait, what?' );
github-light-high-contrast
console. log ( `${ num } is even .` );
throw new Error ( 'Wait, what?' );
houston
console . log ( ` ${ num } is even .` );
throw new Error ( 'Wait, what?' );
laserwave
console . log ( `${ num } is even . ` );
throw new Error ( ' Wait, what? ' );
light-plus
console . log ( ` ${ num } is even .` );
throw new Error ( 'Wait, what?' );
material-theme
console . log ( `${ num } is even . ` ) ;
throw new Error ( ' Wait, what? ' ) ;
material-theme-darker
console . log ( `${ num } is even . ` ) ;
throw new Error ( ' Wait, what? ' ) ;
material-theme-lighter
console . log ( `${ num } is even . ` ) ;
throw new Error ( ' Wait, what? ' ) ;
material-theme-ocean
console . log ( `${ num } is even . ` ) ;
throw new Error ( ' Wait, what? ' ) ;
material-theme-palenight
console . log ( `${ num } is even . ` ) ;
throw new Error ( ' Wait, what? ' ) ;
min-dark
console .log( ` ${ num } is even .` );
throw new Error( 'Wait, what?' );
min-light
console .log ( ` ${ num } is even .` );
throw new Error ( 'Wait, what?' );
monokai
console. log ( ` ${ num } is even .` );
throw new Error ( 'Wait, what?' );
night-owl
console . log ( ` ${ num } is even . ` );
throw new Error ( ' Wait, what? ' );
nord
console . log ( ` ${ num } is even . ` ) ;
throw new Error ( ' Wait, what? ' ) ;
one-dark-pro
console . log ( ` ${ num } is even .` );
throw new Error ( 'Wait, what?' );
poimandres
console . log ( `${ num } is even . ` );
throw new Error ( ' Wait, what? ' );
red
console . log ( ` ${ num } is even .` );
throw new Error ( 'Wait, what?' );
rose-pine
console . log ( ` ${ num } is even .` ) ;
throw new Error ( 'Wait, what?' ) ;
rose-pine-dawn
console . log ( ` ${ num } is even .` ) ;
throw new Error ( 'Wait, what?' ) ;
rose-pine-moon
console . log ( ` ${ num } is even .` ) ;
throw new Error ( 'Wait, what?' ) ;
slack-dark
console . log ( ` ${ num } is even .` );
throw new Error ( 'Wait, what?' );
slack-ochin
console . log ( `${ num } is even .` );
throw new Error ( 'Wait, what?' );
snazzy-light
console . log ( `${ num } is even . ` );
throw new Error ( ' Wait, what? ' );
solarized-dark
console . log ( `${ num } is even .` );
throw new Error ( 'Wait, what?' );
solarized-light
console . log ( `${ num } is even .` );
throw new Error ( 'Wait, what?' );
synthwave-84
console . log ( ` ${ num } is even .` );
throw new Error ( 'Wait, what?' );
tokyo-night
console . log ( ` ${ num } is even . ` ) ;
throw new Error ( ' Wait, what? ' ) ;
vesper
console. log ( `${ num } is even .` );
throw new Error ( 'Wait, what?' );
vitesse-black
console . log ( ` ${ num } is even . ` );
throw new Error ( ' Wait, what? ' );
vitesse-dark
console . log ( ` ${ num } is even . ` );
throw new Error ( ' Wait, what? ' );
vitesse-light
console . log ( ` ${ num } is even . ` );
throw new Error ( ' Wait, what? ' );
Using themes from NPM
You can use any theme available on NPM with Expressive Code, provided that it exports a VS Code-compatible JSON theme object. Follow these steps:
Install the theme using your package manager of choice:
# Install any theme from NPM here, e.g. `summer-time`
# Install any theme from NPM here, e.g. `summer-time`
# Install any theme from NPM here, e.g. `summer-time`
Add the theme to your Expressive Code configuration:
import { defineConfig } from ' astro/config '
import astroExpressiveCode from ' astro-expressive-code '
// Import the theme object
import summerTime from ' summer-time/themes/summer-time-vscode-theme.json '
export default defineConfig ( {
// Pass the theme to the `themes` option
// (consider adding a dark and light theme for accessibility)
import { defineConfig } from ' astro/config '
import starlight from ' @astrojs/starlight '
// Import the theme object
import summerTime from ' summer-time/themes/summer-time-vscode-theme.json '
export default defineConfig ( {
title: ' My Starlight site ' ,
// Pass the theme to the `themes` option
// (consider adding a dark and light theme for accessibility)
import createMDX from ' @next/mdx '
import rehypeExpressiveCode from ' rehype-expressive-code '
// Import the theme object
import summerTime from ' summer-time/themes/summer-time-vscode-theme.json '
/** @type { import ( 'rehype-expressive-code' ) .RehypeExpressiveCodeOptions } */
const rehypeExpressiveCodeOptions = {
// Pass the theme to the `themes` option
// (consider adding a dark and light theme for accessibility)
/** @type { import ( 'next' ) .NextConfig } */
pageExtensions: [ " js " , " jsx " , " ts " , " tsx " , " md " , " mdx " ] ,
const withMDX = createMDX ( {
// The nested array structure is required to pass options
[ rehypeExpressiveCode, rehypeExpressiveCodeOptions ] ,
export default withMDX ( nextConfig )
Using themes from VS Code
You can export any theme from VS Code for use with Expressive Code. Follow these steps:
Open the desired theme in VS Code using any of the following methods:
Browse the VS Code Themes gallery, select a theme, and press one of the Open With
buttons to open it in VS Code.
Alternatively, start right inside VS Code by pressing Ctrl+Shift+P, running the command Preferences: Color Theme
and selecting a theme you like.
Export the theme to a file:
Inside VS Code, press Ctrl+Shift+P and run the command Generate Color Theme from Current Settings
.
Save the generated file to a folder of your website, e.g. as ./my-theme.jsonc
.
Note
VS Code saves themes in a JSONC format (JSON with comments). Most environments don’t support loading JSONC using import
, but you can use fs.readFileSync
to load it as a string and pass it to ExpressiveCodeTheme.fromJSONString
then, which automatically strips the comments for you. See the example below.
Add the theme to your Expressive Code configuration:
import { defineConfig } from ' astro/config '
import astroExpressiveCode , { ExpressiveCodeTheme } from ' astro-expressive-code '
// Load your saved theme JSONC file here and create a theme from it
const jsoncString = fs . readFileSync ( new URL ( ` ./my-theme.jsonc ` , import. meta . url ) , ' utf-8 ' )
const myTheme = ExpressiveCodeTheme . fromJSONString ( jsoncString )
export default defineConfig ( {
// Pass the theme to the `themes` option
// (consider adding a dark and light theme for accessibility)
import { defineConfig } from ' astro/config '
import starlight from ' @astrojs/starlight '
import { ExpressiveCodeTheme } from ' @astrojs/starlight/expressive-code '
// Load your saved theme JSONC file here and create a theme from it
const jsoncString = fs . readFileSync ( new URL ( ` ./my-theme.jsonc ` , import. meta . url ) , ' utf-8 ' )
const myTheme = ExpressiveCodeTheme . fromJSONString ( jsoncString )
export default defineConfig ( {
title: ' My Starlight site ' ,
// Pass the theme to the `themes` option
// (consider adding a dark and light theme for accessibility)
import createMDX from ' @next/mdx '
import rehypeExpressiveCode , { ExpressiveCodeTheme } from ' rehype-expressive-code '
// Load your saved theme JSONC file here and create a theme from it
const jsoncString = fs . readFileSync ( new URL ( ` ./my-theme.jsonc ` , import. meta . url ) , ' utf-8 ' )
const myTheme = ExpressiveCodeTheme . fromJSONString ( jsoncString )
/** @type { import ( 'rehype-expressive-code' ) .RehypeExpressiveCodeOptions } */
const rehypeExpressiveCodeOptions = {
// Pass the theme to the `themes` option
// (consider adding a dark and light theme for accessibility)
/** @type { import ( 'next' ) .NextConfig } */
pageExtensions: [ " js " , " jsx " , " ts " , " tsx " , " md " , " mdx " ] ,
const withMDX = createMDX ( {
// The nested array structure is required to pass options
[ rehypeExpressiveCode, rehypeExpressiveCodeOptions ] ,
export default withMDX ( nextConfig )