Fully customize your docs

Add custom CSS, global JavaScript, and UI components.
View as Markdown

This page covers CSS and JavaScript customization:

  • CSS for styling, visual changes, and hiding elements
  • JavaScript for client-side behavior, third-party integrations, and widgets

For server-rendered reusable elements in your MDX content, see Custom React components. To replace Fern’s default header or footer, see Custom header and footer.

You can also customize many things directly in your docs.yml file, including colors, typography, navbar links, layout, analytics, and metadata. Try these built-in options first before adding custom code.

Custom CSS

You can add custom CSS to your docs to further customize the look and feel. The defined class names are applied across all MDX files. See the CSS selectors reference for a complete list of available .fern-* selectors.

1

Create styles.css

Add a styles.css file and include it in your fern/ project:

Add the styles.css file
$ fern/
$ ├─ openapi/
$ ├─ pages/
$ ├─ images/
$ ├─ styles.css
$ ├─ docs.yml
$ └─ fern.config.json
2

Edit docs.yml

In docs.yml, specify the path to the styles.css file:

docs.yml
1css: ./styles.css
3

Add multiple custom CSS files (optional)

You can specify any number of custom CSS files:

docs.yml
1css:
2 - ./css/header-styles.css
3 - ./css/footer-styles.css

For customizing the background, logo, font, and layout of your Docs via Fern’s built-in styling, check out the Global Configuration.

Built-in CSS color variables

Fern automatically generates CSS variables from your docs.yml colors configuration and makes them available as CSS custom properties in your stylesheets. Colors are converted to oklch for consistent color management, with hex fallbacks for unsupported browsers. These variables adapt automatically between light and dark modes — light mode uses the .light and :root selectors, while dark mode uses the .dark selector.

  • --accent-1 through --accent-12 — accent color scale (generated from accent-primary)
  • --accent-a1 through --accent-a12 — accent color scale with alpha transparency
  • --grayscale-1 through --grayscale-12 — grayscale color scale
  • --grayscale-a1 through --grayscale-a12 — grayscale with alpha transparency

Fern also generates named color scales that follow Radix UI’s step paradigms. These match your accent-primary hue and include scales like --red-1 through --red-12, --blue-1 through --blue-12, and so on for other colors.

  • --background — page background color
  • --card-background — card background color
  • --border — border color
  • --sidebar-background — sidebar background color
  • --header-background — header background color
  • --accent — primary accent color

The accordions below show common patterns for using these variables to theme backgrounds, cards, text, and images.

Use CSS variables to create backgrounds that automatically adapt to the theme. Override with .dark selector only when you need theme-specific styling.

1/* Auto-adapts using Fern variables */
2.fern-background-image {
3 background-color: var(--background);
4 background-image: linear-gradient(
5 to bottom,
6 color-mix(in srgb, var(--accent-9), var(--background) 85%) 0%,
7 var(--background) 100%
8 );
9}
10
11/* Explicit dark mode override for different gradient direction */
12.dark .fern-background-image {
13 background-image: linear-gradient(
14 to bottom,
15 var(--background) 0%,
16 color-mix(in srgb, var(--accent-9), var(--background) 85%) 100%
17 );
18}

Cards automatically adapt to theme changes when using CSS variables. Add explicit dark mode overrides only for properties like shadows that need theme-specific values.

1/* Plant catalog card that adapts to theme */
2.fern-card.plant-card {
3 background-color: var(--card-background);
4 border-color: var(--border);
5 color: var(--grayscale-12);
6 box-shadow: 0 1px 2px var(--grayscale-a3);
7}
8
9.fern-card.plant-card.interactive:hover {
10 box-shadow: 0 4px 12px var(--accent-a6);
11}
12
13/* Dark mode shadow adjustment */
14.dark .fern-card.plant-card {
15 box-shadow: 0 2px 6px var(--grayscale-a4);
16}

Text colors automatically adapt when using Fern’s grayscale and accent variables. Use --grayscale-12 for primary text, --grayscale-a11 for secondary text, and --accent-11 for links.

1/* Plant species content */
2.plant-content {
3 color: var(--grayscale-12);
4}
5
6.plant-content .description {
7 color: var(--grayscale-a11);
8}
9
10.plant-content a {
11 color: var(--accent-11);
12 text-decoration-color: color-mix(in srgb, var(--accent-11), transparent 50%);
13}
14
15.plant-content a:hover {
16 color: var(--accent-12);
17}

There are multiple approaches for adapting images to light and dark modes.

SVG icons with currentColor (recommended):

HTML
1<svg class="plant-icon" width="24" height="24" fill="currentColor">
2 <!-- SVG paths -->
3</svg>
CSS
1.plant-icon {
2 color: var(--grayscale-11);
3}
4
5.plant-icon.accent {
6 color: var(--accent-11);
7}

Swapping background images:

CSS
1.hero-plant {
2 background-image: url('/assets/plants/hero-light.png');
3 background-size: cover;
4 background-position: center;
5}
6
7.dark .hero-plant {
8 background-image: url('/assets/plants/hero-dark.png');
9}

Using picture element with prefers-color-scheme:

HTML
1<picture>
2 <source srcset="/assets/plants/hero-dark.png" media="(prefers-color-scheme: dark)">
3 <img src="/assets/plants/hero-light.png" alt="Plant species">
4</picture>

The prefers-color-scheme media query follows the operating system theme preference and may not match a manual theme toggle on your site. For perfect alignment with Fern’s theme switcher, use the .dark selector approach instead.

Using CSS filters (last resort):

CSS
1.logo-monochrome {
2 filter: grayscale(1);
3}
4
5.dark .logo-monochrome {
6 filter: invert(1) grayscale(1);
7}

Avoid hardcoding hex colors in your custom CSS. Always use Fern’s CSS variables to maintain proper contrast and theme consistency.

Common use cases

You can use custom CSS to hide specific Fern docs components that you don’t want to display.

styles.css
1.fern-layout-footer-toolbar { # Hides Fern feedback widget
2 display: none !important;
3}

You can target other Fern UI components using their CSS class names. See the CSS selectors reference for all available selectors, or use your browser’s developer tools to inspect elements.

You can use custom CSS to create brand-specific styling for tables, components, and other elements in your documentation.

styles.css
1.petstore-table {
2 background-color: white;
3 border: 1px solid #DEDEE1;
4 border-radius: 4px;
5}
6
7.dark .petstore-table {
8 background-color: #1e1e1e;
9 border: 1px solid #2e2e2e;
10}
11
12.petstore-table thead {
13 position: sticky;
14 top: 0;
15}
16
17.petstore-table thead tr {
18 background-color: #edecee;
19 border: 1px solid #DEDEE1;
20 border-radius: 4px 4px 0px 0px;
21}
22
23.dark .petstore-table thead tr {
24 background-color: #2e2e2e;
25 border: 1px solid #2e2e2e;
26}
27
28.petstore-table th {
29 padding: 6px;
30}
31
32.petstore-table tbody td {
33 padding: 6px;
34}
35
36.petstore-table tbody tr:nth-child(odd) {
37 border: 1px solid #DEDEE1;
38}
39.petstore-table tbody tr:nth-child(even) {
40 border: 1px solid #DEDEE1;
41 background-color: #f7f6f8;
42}
43
44.dark .petstore-table tbody tr:nth-child(odd) {
45 border: 1px solid #2e2e2e;
46}
47
48.dark .petstore-table tbody tr:nth-child(even) {
49 border: 1px solid #2e2e2e;
50 background-color: #2e2e2e;
51}

Inline CSS on MDX pages

You can add CSS directly within an MDX page using a <style> tag. This is useful for page-specific styles that don’t need to be applied globally.

page.mdx
1---
2title: My page
3---
4
5<style>
6{`
7.tropical-callout {
8 background: linear-gradient(135deg, #2d5016 0%, #4a7c23 100%);
9 border-radius: 8px;
10 padding: 16px;
11 color: white;
12}
13
14.dark .tropical-callout {
15 background: linear-gradient(135deg, #1a3009 0%, #2d5016 100%);
16}
17`}
18</style>
19
20<div className="tropical-callout">
21 Monstera deliciosa thrives in bright, indirect light.
22</div>

The CSS must be wrapped in curly braces and backticks ({``}) to be valid JSX. Use the .dark selector prefix to define styles for dark mode.

Custom JavaScript

Customize the behavior of your Docs site by injecting custom JavaScript globally.Add a custom.js file and include it in your fern/ project:

Add the custom.js file
$ fern/
$ ├─ openapi/
$ ├─ pages/
$ ├─ images/
$ ├─ custom.js
$ ├─ docs.yml
$ └─ fern.config.json

In docs.yml, specify the path to the custom.js file:

docs.yml
1js: ./custom.js

You can also specify multiple custom JS files stored locally and remote:

docs.yml
1js:
2 - path/to/js/file.js
3 - path: path/to/another/js/file.js
4 strategy: beforeInteractive
5 - url: https://example.com/path/to/js/file.js

We use path for local sources and url for remote sources.

Strategy

Optionally, specify the strategy for each custom JavaScript file. Choose from beforeInteractive, afterInteractive (default), and lazyOnload.

docs.yml
1js:
2 - path: path/to/another/js/file.js
3 strategy: beforeInteractive

Common use cases

  • Third-party integrations: For tools not natively supported in docs.yml, add analytics, session recording, support widgets, or tag managers by pasting their embed snippets into your custom JS file. See Integrating third-party tools for supported tools and examples.

  • Custom search: Implement custom search (also requires your Algolia credentials)

  • Scripts and widgets: Insert any client-side scripts or embeddable widgets