---
title: Themes
---

import ConfigVariants from '@components/ConfigVariants.astro'
import PackageManagers from '@components/PackageManagers.astro'
import PropertySignature from '@components/PropertySignature.astro'
import { Tabs, TabItem } from '@astrojs/starlight/components'

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](#using-bundled-themes), import [themes from NPM](#using-themes-from-npm), or export [themes from VS Code](#using-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:

<ConfigVariants
  settings={`
    // Replace the default themes with a custom set of bundled themes:
    // "dracula" (a dark theme) and "solarized-light"
    themes: ['dracula', 'solarized-light'],
  `}
/>

### Available themes

import BundledThemes from '../../../components/BundledThemes.astro'

<BundledThemes/>

### Configuration

#### removeUnusedThemes

<PropertySignature>
- Type: boolean
- Default: true
- Availability: Astro and Starlight integrations only
</PropertySignature>

In Astro and Starlight, Expressive Code automatically removes any themes from the full Shiki bundle that are not used by your configuration. This reduces the SSR bundle size by over 1 MB. You can control this behavior with the `removeUnusedThemes` option.

:::note[Only for advanced use cases]
Most sites **do not need to set this option**, as it already defaults to `true`, which is the optimal setting.
:::

If you really need to disable this automatic optimization because of an advanced use case that requires access all bundled Shiki themes, you can set this option to `false`.

<ConfigVariants
  imports={`
    import cloudflare from '@astrojs/cloudflare // no-ins'
  `}
  settings={`
    // This example uses non-default themes, but unused theme removal
    // also works with the default themes ['github-dark', 'github-light']
    themes: ['catppuccin-macchiato', 'catppuccin-latte'], // no-ins
    // Disable automatic removal of unused themes from the bundle,
    // allowing access to other themes than the ones specified
    // in the \`themes\` option
    removeUnusedThemes: false,
  `}
  nonIntegrationSettings={`
    // This example uses server-side rendering (SSR)
    // with the Cloudflare adapter
    output: 'server',
    adapter: cloudflare(),
  `}
  noNextJs
/>

## 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:

1. Install the theme using your package manager of choice:
  
    <PackageManagers pkg="summer-time" prefix="# Install any theme from NPM here, e.g. `summer-time`" />

2. Add the theme to your Expressive Code configuration:

    <ConfigVariants
      imports={`
        // Import the theme object
        import summerTime from 'summer-time/themes/summer-time-vscode-theme.json'
      `}
      settings={`
        // Pass the theme to the \`themes\` option
        // (consider adding a dark and light theme for accessibility)
        themes: [summerTime],
      `}
    />

## Using themes from VS Code

You can export any theme from VS Code for use with Expressive Code. Follow these steps:

1. Open the desired theme in VS Code using any of the following methods:
    - Browse the [VS Code Themes](https://vscodethemes.com/) 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.

2. 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.
      :::

3. Add the theme to your Expressive Code configuration:
    <ConfigVariants
      namedImports={['ExpressiveCodeTheme']}
      imports={`
        import fs from 'node:fs'

        // 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)
      `}
      settings={`
        // Pass the theme to the \`themes\` option
        // (consider adding a dark and light theme for accessibility)
        themes: [myTheme],
      `}
    />
