CSS
Nocturne's styles live in one main file: src/css/nocturne.css.
This page explains its structure and how to customize it.
File Location
src/css/nocturne.css
Imported in docusaurus.config.ts:
theme: {
customCss: './src/css/nocturne.css',
},
File Structure
Nocturne's CSS is organized into 10 sections:
/* 1. Font imports */
@import url('...');
/* 2. Root variables (dark mode) */
:root { ... }
/* 3. Light mode variables */
[data-theme='light'] { ... }
/* 4. Base styles */
html, body { ... }
h1, h2, h3 { ... }
/* 5. Navbar */
.atelier-navbar { ... }
/* 6. Sidebar */
.theme-doc-sidebar-container { ... }
/* 7. Pagination */
.pagination-nav { ... }
/* 8. Code blocks */
pre { ... }
/* 9. Homepage sections */
.home-hero { ... }
.home-section { ... }
/* 10. Responsive */
@media(max-width: 960px) { ... }
CSS Variables
Nocturne uses CSS variables for everything. Change one variable, update the entire site.
Dark Mode (Default)
:root {
--atelier-bg: #0A0A0B;
--atelier-fg: #EDE8D8;
--atelier-muted: #9A9590;
--atelier-border: #1E1E20;
--atelier-card: #111113;
--atelier-card-hover: #151517;
--atelier-pill-bg: #EDE8D8;
--atelier-pill-fg: #0A0A0B;
--atelier-code-bg: #111113;
}
| Variable | Purpose |
|---|---|
--atelier-bg | Main background |
--atelier-fg | Main foreground (text) |
--atelier-muted | Secondary text |
--atelier-border | Borders |
--atelier-card | Card background |
--atelier-card-hover | Card hover state |
--atelier-pill-bg | Pill button background |
--atelier-pill-fg | Pill button text |
--atelier-code-bg | Code block background |
Light Mode
[data-theme='light'] {
--atelier-bg: #FAF8F2;
--atelier-fg: #0A0A0B;
--atelier-muted: #6B6660;
--atelier-border: #EAE6DE;
--atelier-card: #FFFFFF;
}
To change light mode, edit this block. To change dark mode, edit :root.
Fonts
Nocturne uses three font families:
:root {
--ifm-font-family-base: 'Inter', sans-serif;
--ifm-heading-font-family: 'Playfair Display', serif;
--ifm-code-font-family: 'JetBrains Mono', monospace;
}
| Font | Used For |
|---|---|
| Inter | Body text |
| Playfair Display | Headings |
| JetBrains Mono | Code, labels, badges |
Loading Fonts
Fonts are imported at the top of nocturne.css:
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Playfair+Display:ital,wght@0,700;1,400&family=JetBrains+Mono:wght@400;500&display=swap');
To change fonts:
- Update the
@importURL - Update the font family variables
Example — swap Playfair for Cormorant:
@import url('https://fonts.googleapis.com/css2?family=Cormorant+Garamond:wght@400;600&display=swap');
:root {
--ifm-heading-font-family: 'Cormorant Garamond', serif;
}
Class Naming
Nocturne uses the atelier- prefix to avoid conflicts with Docusaurus classes:
| Prefix | Used For |
|---|---|
.atelier-navbar | Navbar |
.atelier-pill | Pill buttons |
.atelier-card | Cards |
.atelier-drawer | Mobile drawer |
.home-hero | Homepage hero |
.home-section | Homepage sections |
Always use the prefix when adding custom classes.
Dark Mode
Nocturne uses dark mode by default. To change:
In docusaurus.config.ts:
themeConfig: {
colorMode: {
defaultMode: 'dark',
disableSwitch: false,
respectPrefersColorScheme: true,
},
},
In nocturne.css:
Target light mode with [data-theme='light']:
/* Dark: default */
.card {
background: var(--atelier-card);
}
/* Light: override */
[data-theme='light'] .card {
background: #FFFFFF;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
Test both modes after every change.
Responsive Breakpoints
Nocturne uses mobile-first breakpoints:
/* Mobile: default */
.home-hero {
grid-template-columns: 1fr;
}
/* Tablet and up: 960px */
@media(min-width: 960px) {
.home-hero {
grid-template-columns: 1.15fr 0.85fr;
}
}
| Breakpoint | Width |
|---|---|
| Mobile | < 960px |
| Desktop | ≥ 960px |
Common Customizations
Change Accent Color
:root {
--atelier-fg: #D4A574; /* from cream to gold */
}
Change Border Radius
:root {
--radius-lg: 12px;
--radius-xl: 16px;
}
Remove Hover Effects
.card:hover {
transform: none;
box-shadow: none;
}
Adding Custom Styles
Add new styles at the bottom of the file:
/* ───── Custom Styles ───── */
.my-custom-section {
padding: 4rem 2rem;
background: var(--atelier-card);
border-radius: var(--radius-lg);
}
Use a comment to separate your additions. Makes upgrades easier.
Overriding Defaults
Avoid !important unless necessary. Use specific selectors instead:
Wrong:
.navbar {
height: 80px !important;
}
Right:
.navbar__inner {
height: 80px;
}
When you must use !important, document why with a comment.
Best Practices
- Use CSS variables — not hardcoded values
- Use the
atelier-prefix — avoid conflicts - Test in both themes — dark and light
- Test on mobile — not just desktop
- Comment custom additions — easier to upgrade
- Avoid
!important— use specific selectors
Troubleshooting
Style doesn't apply
- Check the class name — must match exactly
- Check specificity — maybe another rule overrides it
- Check DevTools → Elements → Styles
- Refresh with
Ctrl + Shift + R
Light mode looks broken
- Check
[data-theme='light']rules - Check contrast ratios
- Test with the theme toggle
CSS file not loading
- Check the import in
docusaurus.config.ts - Check that the file exists at
src/css/nocturne.css - Check the terminal for errors
Styles work locally but not in production
- Run
npm run buildlocally - Check the build output
- Clear the browser cache