Skip to content

Code Component

In addition to rendering fenced code blocks in markdown & MDX documents, the Expressive Code Astro & Starlight integrations also provide a <Code> component that can be used in .mdx and .astro files.

In contrast to static fenced code blocks, the <Code> component allows you to dynamically define a code block’s contents using props. This makes it possible to render code blocks from variables or data coming from external sources like files, databases or APIs.

Basic usage

To use the <Code> component, you must first import it into your file. The location and syntax of the import statement depend on the file type and integration you’re using:

Usage in .mdx files

To get started, add an import statement to the content section of your .mdx file (the part below the frontmatter block). You can then use the component anywhere in the content.

src/content/docs/example.mdx
---
title: My example page
---
import { Code } from 'astro-expressive-code/components'
<Code code="console.log('Hello world!')" lang="js" />

The code above generates the following on the page:

console.log('Hello world!')

Usage in .astro files

The <Code> component enables you to render code blocks in .astro files. This allows you to use all features of Expressive Code in your pages, and even creating custom components that wrap the <Code> component to provide additional functionality.

Using the component in .astro files works just like in .mdx files, except that you need to place the import statement inside the frontmatter block:

src/pages/index.astro
---
import MainLayout from '../layouts/MainLayout.astro'
import { Code } from 'astro-expressive-code/components'
---
<MainLayout>
<h1>My example page</h1>
<p>Here is some interesting code:</p>
<Code code="console.log('Hello world!')" lang="js" />
</MainLayout>

Using props to define code blocks

The true power of the <Code> component lies in its ability to render code blocks from variables or data coming from external sources like files, databases or APIs.

To do this, set the component’s props like code, lang, title etc. to variables instead of static values.

src/content/docs/example.mdx
---
title: My example page
---
import { Code } from 'astro-expressive-code/components'
export const exampleCode = `console.log('This could come from a file or CMS!');`
export const fileName = 'example.js'
export const highlights = ['file', 'CMS']
<Code code={exampleCode} lang="js" title={fileName} mark={highlights} />

The code above generates the following on the page:

example.js
console.log('This could come from a file or CMS!');

Importing code from files

Use Vite’s ?raw import suffix to import any code file as a string. You can then pass this imported string to the <Code> component to include it on your page.

This is especially useful when documenting a project, as your code examples will always be up-to-date with the actual code.

You can also use this feature to create reusable snippets and include them in multiple code blocks on your site.

src/content/docs/example.mdx
import { Code } from 'astro-expressive-code/components';
import importedCode from '/src/env.d.ts?raw';
<Code code={importedCode} lang="ts" title="src/env.d.ts" />

The code above generates the following on the page:

src/env.d.ts
/* eslint-disable @typescript-eslint/triple-slash-reference */
/// <reference path="../.astro/types.d.ts" />
/// <reference types="astro/client" />

Using an ec.config.mjs file

The <Code> component is designed to automatically pick up the Expressive Code configuration options from your project’s Astro config file without requiring any additional setup.

Due to the way Astro works, the Expressive Code integration can only share its configuration with the component by serializing it to JSON. In some situations, this is not possible, e.g. when your configuration includes custom plugins or functions that are not serializable to JSON.

In these cases, you will receive the following error message when trying to use the <Code> component:

[ERROR] Failed to render a <Code> component on page […]:

Your Astro config file contains Expressive Code options that are not serializable to JSON. To use the <Code> component, please create a separate config file called ec.config.mjs in your project root, move your Expressive Code options object into the config file, and export it as the default export.

As instructed by the error message, you can fix this issue by creating a separate ec.config.mjs file in your project root and moving your Expressive Code options object into the config file. Here is an example of how this file could look like if you’re using the collapsible sections plugin:

ec.config.mjs
import { defineEcConfig } from 'astro-expressive-code'
import { pluginCollapsibleSections } from '@expressive-code/plugin-collapsible-sections'
export default defineEcConfig({
// Example: Using a custom plugin (which makes this `ec.config.mjs` file necessary)
plugins: [pluginCollapsibleSections()],
// ... any other options you want to configure
})

Available props

You can find a list of all default props that can be used with the <Code> component below.

code

Type: string

The plaintext contents of the code block. This property is required and must be set to a non-empty string.

lang

Type: string | undefined Default: undefined

The code block’s language.

Please use a valid language identifier to ensure proper syntax highlighting.

meta

Type: string | undefined Default: undefined

An optional meta string. In markdown or MDX documents, this is the part of the code block’s opening fence that comes after the language name.

locale

Type: string | undefined Default: undefined

The code block’s locale (e.g. en-US or de-DE). This is used by plugins to display localized strings depending on the language of the containing page.

If no locale is defined here, most Expressive Code integrations will attempt to auto-detect the block locale using the configured getBlockLocale function, and finally fall back to the configured defaultLocale.

title

Type: string | undefined Default: undefined

The code block’s title.

Depending on the frame type (code or terminal), this title is displayed by the frames plugin either as an open file tab label or as a terminal window title.

frame

Type: 'auto' | 'code' | 'terminal' | 'none' | undefined Default: 'auto'

The code block’s frame type.

mark / ins / del

Type: MarkerDefinition | MarkerDefinition[] Default: undefined

Defines the code block’s text & line markers.

You can either pass a single marker definition or an array of them.

class

Type: string | undefined Default: undefined

The CSS class name(s) to apply to the code block’s container element.

wrap

Type: boolean Default: false

If true, word wrapping will be enabled for the code block, causing lines that exceed the available width to wrap to the next line. You can use the preserveIndent option to control how wrapped lines are indented.

If false, lines that exceed the available width will cause a horizontal scrollbar to appear.

preserveIndent

Type: boolean Default: true

If true, wrapped parts of long lines will be aligned with their line’s indentation level, making the wrapped code appear to start at the same column. This increases readability of the wrapped code and can be especially useful for languages where indentation is significant, e.g. Python.

If false, wrapped parts of long lines will always start at column 1. This can be useful to reproduce terminal output.