Starlight shows code blocks in the Night Owl theme, with a dark and a light version. You can use any theme that Expressive Code knows instead. The plugin takes its colours from the theme, so markers, messages and notes match the syntax colours of the block.
Each example on this page shows the same code block in eight themes. The examples combine several features, so that one block shows many of the colours of the plugin.
Notes and line states
Section titled “Notes and line states”This block has an annotation, a footnote and a warning. The marker of the annotation and the bar of the warning take the blue and the warning colour of each theme:
Readers see
GitHub Dark (dark)
GitHub Light (light)
Dracula (dark)
Solarized Light (light)
One Dark Pro (dark)
Catppuccin Latte (light)
Nord (dark)
Min Light (light)
You write
```py title="app.py"from flask import Flask
app = Flask(__name__) # [!annotate] Creates the application object.
# [!ref] Runs this function for `GET /health`.@app.get("/health")def health(): return {"ok": True} # [!code warning] Always 200```Changes
Section titled “Changes”Word-level diff tints the words that changed with the green and the red of the terminal colours of each theme:
Readers see
GitHub Dark (dark)
client.js const timeout = 5000;const timeout = options.timeout ?? 5000;const client = createClient({retries: 3,retries: options.retries,});GitHub Light (light)
client.js const timeout = 5000;const timeout = options.timeout ?? 5000;const client = createClient({retries: 3,retries: options.retries,});Dracula (dark)
client.js const timeout = 5000;const timeout = options.timeout ?? 5000;const client = createClient({retries: 3,retries: options.retries,});Solarized Light (light)
client.js const timeout = 5000;const timeout = options.timeout ?? 5000;const client = createClient({retries: 3,retries: options.retries,});One Dark Pro (dark)
client.js const timeout = 5000;const timeout = options.timeout ?? 5000;const client = createClient({retries: 3,retries: options.retries,});Catppuccin Latte (light)
client.js const timeout = 5000;const timeout = options.timeout ?? 5000;const client = createClient({retries: 3,retries: options.retries,});Nord (dark)
client.js const timeout = 5000;const timeout = options.timeout ?? 5000;const client = createClient({retries: 3,retries: options.retries,});Min Light (light)
client.js const timeout = 5000;const timeout = options.timeout ?? 5000;const client = createClient({retries: 3,retries: options.retries,});
You write
```diff lang="js" title="client.js"-const timeout = 5000;+const timeout = options.timeout ?? 5000; const client = createClient({- retries: 3,+ retries: options.retries, });```Terminal commands
Section titled “Terminal commands”Smart shell copy colours the $ at the start of each command with the terminal cyan of each theme, and mutes the output lines:
Readers see
GitHub Dark (dark)
Terminal window $ npm install starlight-codeblocksadded 1 package in 2s$ npx astro buildGitHub Light (light)
Terminal window $ npm install starlight-codeblocksadded 1 package in 2s$ npx astro buildDracula (dark)
Terminal window $ npm install starlight-codeblocksadded 1 package in 2s$ npx astro buildSolarized Light (light)
Terminal window $ npm install starlight-codeblocksadded 1 package in 2s$ npx astro buildOne Dark Pro (dark)
Terminal window $ npm install starlight-codeblocksadded 1 package in 2s$ npx astro buildCatppuccin Latte (light)
Terminal window $ npm install starlight-codeblocksadded 1 package in 2s$ npx astro buildNord (dark)
Terminal window $ npm install starlight-codeblocksadded 1 package in 2s$ npx astro buildMin Light (light)
Terminal window $ npm install starlight-codeblocksadded 1 package in 2s$ npx astro build
You write
```sh$ npm install starlight-codeblocksadded 1 package in 2s$ npx astro build```Choose the themes of your site
Section titled “Choose the themes of your site”Give the names of a dark and a light theme in the expressiveCode option of Starlight. The theme menu of Starlight switches between them:
starlight({ expressiveCode: { themes: ['dracula', 'solarized-light'], }, plugins: [codeblocks()],});The names are the names of the themes that Shiki includes, such as github-dark or catppuccin-latte. The Expressive Code docs list them, and explain how to load a theme from a JSON file.
Change a colour
Section titled “Change a colour”The plugin takes each of its colours from a colour of the theme. For example, the accent of Min Light is grey because its terminal blue is grey. The plugin then makes each colour lighter or darker, until it has its contrast target on the code background of that theme. The accessibility page gives the targets. If a theme has no colour for a part, the plugin uses the default colour of VS Code.
Theme colour of each plugin colour
| Plugin colour | Theme colour |
|---|---|
Markers, focus rings and active states (codeblocks.accent) |
terminal.ansiBlue |
| Error, warning and info states | editorError.foreground, editorWarning.foreground, editorInfo.foreground |
| Colourised brackets | editorBracketHighlight.foreground1 to 3 |
| Word-level diff, Run output and errors | terminal.ansiGreen, terminal.ansiRed |
The $ of shell commands |
terminal.ansiCyan |
| Permalink target | terminal.ansiYellow |
| Muted text, popovers and borders | Mixes of the code colour and the code background |
To change a colour for every theme, set its style setting in the styleOverrides option of Expressive Code:
starlight({ expressiveCode: { themes: ['min-light', 'github-dark'], styleOverrides: { codeblocks: { accent: ['#58a6ff', '#0969da'] } }, }, plugins: [codeblocks()],});Each key in styleOverrides is a group of settings:
- The
codeblocksgroup has the settings that all features share, such asaccent,mutedForegroundandpopoverBackground. - Each feature has its own group. The name of the group is
codeblocksand then the name of the feature, such ascodeblocksShellCopyfor smart shell copy.
For example, the colour of the $ in shell commands is the promptForeground setting in the codeblocksShellCopy group:
styleOverrides: { codeblocksShellCopy: { promptForeground: ['#56d4dd', '#1b7c83'] } },A pair gives the dark value, then the light value. The plugin does not correct the contrast of a colour that you set. Check it against the code background of each theme.
Limitations
Section titled “Limitations”- Min Light has a grey terminal blue, so its accent is grey. Colour is never the only mark of a feature, so the blocks still work.
- Custom line states keep the colours that you give in the
lineStatesoption. - If a theme sets the code background to a CSS variable, the plugin cannot read it. It measures the contrast against the background of the theme instead.