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.
/* 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:
: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;
}
Customize Link Styles
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:
| Callout | Variable 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:
| Selector | Matches |
|---|---|
html.dark | The page while dark mode is on |
body[data-theme="jam"] | The active theme, by name |
header[data-has-tabs] | The site header |
article | The current page, including its title |
article .prose | The page's body content |
#content-scroll-container | The page content column |
[role="tab"][aria-selected="true"] | The selected tab in a <Tabs> group |
.jd-footer | The page footer |
.jd-footer--embed | The smaller footer in embedded pages, such as the changelog widget |
.jd-footer-columns | The row of link columns |
.jd-footer-column | One link column |
.jd-footer-column-title | A link column's heading |
.jd-footer-link | A link inside a column |
.jd-footer-bottom | The bottom line with social icons, copyright, and branding |
.jd-footer-socials | The group of social icons |
.jd-footer-social[data-platform="github"] | One social icon, by its key in footer.socials |
.jd-footer-copyright | The copyright line |
.jd-footer-branding | The "Powered by Jamdesk" link |
Banner
The banner you set in docs.json has these stable hooks for your CSS:
| Hook | Matches |
|---|---|
.jd-banner | The banner bar |
[data-type="info"], [data-type="warning"], [data-type="danger"] | The bar's type, as an attribute on .jd-banner |
.jd-banner-inner | The centered row inside the bar |
.jd-banner-icon | The icon on warning and danger banners |
.jd-banner-content | The banner text |
.jd-banner-close | The close button on a dismissible banner |
--jd-banner-bg | The bar's background color |
--jd-banner-fg | The bar's text and icon color |
--jd-banner-height | The 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:
.jd-banner {
--jd-banner-bg: #111827;
--jd-banner-fg: #f9fafb;
}Add the attribute to restyle one type only:
.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:
.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
!importantor very specific selectors. You may need!importantto 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
