Jamdesk Documentation logo

Custom CSS

Add custom CSS to override theme styles, tweak typography, or add brand-specific styling. Jamdesk exposes CSS variables for common customizations.

Add custom CSS on top of the theme defaults to match your brand or adjust specific styles.

Adding Custom CSS

Create a style.css file in your project root (the same folder as your docs.json). Jamdesk applies it to every page. No docs.json entry is needed.

Any .css file in the project root works, not only style.css. Jamdesk combines several files in alphabetical filename order.

Run jamdesk dev to preview the result locally. It renders your custom CSS the same way the published site does.

style.css
/* Your custom styles */
article h1 {
  font-size: 2.5rem;
}

CSS & JS Examples walks through recoloring the header and adding a floating button.

CSS Variables

Colors and corner radii come from CSS variables. Override them on :root. Every component that uses them follows:

style.css
:root {
  /* Page and text colors */
  --color-bg-primary: #ffffff;      /* page background */
  --color-bg-secondary: #f8fafc;    /* inputs, subtle panels */
  --color-text-primary: #0a0a0a;    /* headings */
  --color-text-secondary: #404144;  /* body text */
  --color-text-muted: #737373;      /* captions and hints */
  --color-border: #e2e8f0;

  /* Corner radius for cards, buttons and panels */
  --radius-sm: 6px;
  --radius-md: 8px;
  --radius-lg: 12px;
}

The values above are the Jam theme's defaults. Other themes start from their own values. Read any of them in your browser's dev tools on the <html> element.

Your brand colors belong in docs.json, not here. Jamdesk turns colors.primary into the accent used for links, buttons and the active sidebar item. See Custom Colors.

Fonts belong in docs.json too. The fonts field loads a Google Font or your own font file and applies it everywhere. Setting font-family in CSS only works with !important. Themes set fonts with more specific selectors. See Typography.

Common Customizations

Change the Code Font

Code blocks keep the theme's monospace font unless you override it with !important:

@import url('https://fonts.googleapis.com/css2?family=Fira+Code&display=swap');

article pre,
article pre code,
article code {
  font-family: 'Fira Code', monospace !important;
  font-variant-ligatures: common-ligatures;
}

Links inside the page body always have classes. Select them by where they sit, not with a:not([class]):

article .prose a {
  text-decoration: underline;
  text-underline-offset: 3px;
}

article .prose a:hover {
  text-decoration-thickness: 2px;
}

Adjust Heading Spacing

article .prose h2 {
  margin-top: 3rem;
  margin-bottom: 1rem;
}

article .prose h3 {
  margin-top: 2rem;
  margin-bottom: 0.75rem;
}

Style Callouts

Callouts take their colors from variables ending in -bg, -border and -text:

CalloutVariable prefix
<Note>--color-note-
<Info>--color-info-
<Warning>--color-warning-
<Tip>, <Check>--color-success-
<Danger>--color-error-
/* Warmer Note callouts */
:root {
  --color-note-bg: #fef3c7;
  --color-note-border: #f59e0b;
}

Style the Active Tab

article [role="tab"][aria-selected="true"] {
  border-bottom-width: 3px;
}

Dark Mode

Jamdesk adds the dark class to <html> in dark mode. Put dark-mode overrides under html.dark:

/* Light mode */
:root {
  --color-bg-primary: #fffdf7;
}

.custom-banner {
  background: #f0f4ff;
  color: #1e3a5f;
}

/* Dark mode */
html.dark {
  --color-bg-primary: #14110f;
}

html.dark .custom-banner {
  background: #1e293b;
  color: #e2e8f0;
}

[data-theme="dark"] never matches. data-theme on <body> holds your theme's name (jam, nebula and so on), not light or dark.

Selectors to Use

Jamdesk's class names come from Tailwind and can change in any release. These hooks are stable:

SelectorMatches
html.darkThe page while dark mode is on
body[data-theme="jam"]The active theme, by name
header[data-has-tabs]The site header
articleThe current page, including its title
article .proseThe page's body content
#content-scroll-containerThe page content column
[role="tab"][aria-selected="true"]The selected tab in a <Tabs> group
.jd-footerThe page footer
.jd-footer--embedThe smaller footer in embedded pages, such as the changelog widget
.jd-footer-columnsThe row of link columns
.jd-footer-columnOne link column
.jd-footer-column-titleA link column's heading
.jd-footer-linkA link inside a column
.jd-footer-bottomThe bottom line with social icons, copyright, and branding
.jd-footer-socialsThe group of social icons
.jd-footer-social[data-platform="github"]One social icon, by its key in footer.socials
.jd-footer-copyrightThe copyright line
.jd-footer-brandingThe "Powered by Jamdesk" link

The banner you set in docs.json has these stable hooks for your CSS:

HookMatches
.jd-bannerThe banner bar
[data-type="info"], [data-type="warning"], [data-type="danger"]The bar's type, as an attribute on .jd-banner
.jd-banner-innerThe centered row inside the bar
.jd-banner-iconThe icon on warning and danger banners
.jd-banner-contentThe banner text
.jd-banner-closeThe close button on a dismissible banner
--jd-banner-bgThe bar's background color
--jd-banner-fgThe bar's text and icon color
--jd-banner-heightThe bar's measured height, set on <html>

Set the color variables on .jd-banner, not on :root. The warning and danger types set their own values on the bar, so a value on :root never reaches them.

A plain .jd-banner rule restyles every type:

style.css
.jd-banner {
  --jd-banner-bg: #111827;
  --jd-banner-fg: #f9fafb;
}

Add the attribute to restyle one type only:

style.css
.jd-banner[data-type="danger"] {
  --jd-banner-bg: #7f1d1d;
}

If your CSS has an older rule such as [data-jd-banner] { background: ... }, it recolors every type, including warning and danger. Replace it with one of the rules above.

Use --jd-banner-height to keep your own sticky elements below the bar. It isn't set when no banner shows, so give it a 0px fallback:

style.css
.my-sticky-toolbar {
  position: sticky;
  top: var(--jd-banner-height, 0px);
}

External Fonts

Load fonts through docs.json whenever you can. The fonts field loads Google Fonts and self-hosted files, including .woff2 files in your repo. It applies them to headings and body text.

CSS is the fallback for anything fonts doesn't cover, such as the code font above or a different font on one element. Load the font with @import or @font-face, then set it with !important:

@font-face {
  font-family: 'CustomFont';
  src: url('/fonts/custom-font.woff2') format('woff2');
  font-weight: 400;
  font-display: swap;
}

article .prose blockquote {
  font-family: 'CustomFont', serif !important;
}

Responsive Styles

Use media queries for screen-size adjustments:

/* Phones */
@media (max-width: 768px) {
  article h1 {
    font-size: 1.75rem;
  }
}

Debugging

Right-click an element and choose Inspect to find what to target. Prefer the hooks in Selectors to Use, roles such as role="tab", and CSS variables over long Tailwind class names. If a rule doesn't apply, check the Styles panel for a theme rule that wins on specificity or uses !important.

Limitations

  • CSS applies globally. Use specific selectors to avoid conflicts
  • Some theme styles, including fonts and the Jam header background, use !important or very specific selectors. You may need !important to override them
  • Local preview (jamdesk dev) applies edits to your CSS file(s) on browser refresh. The published site picks up changes on the next build

What's Next?

Theming

Choose and configure themes

CSS & JS Examples

A branded header and a floating Ask AI button