nextjs-slides inherits your app’s theme and works with any Tailwind v4 setup. Customize code blocks, syntax highlighting, and fonts using CSS variables.
CSS Variables
The library uses standard Tailwind color variables that are compatible with shadcn/ui and other Tailwind v4 themes:
@theme inline {
--foreground: #0a0a0a;
--background: #ffffff;
--muted-foreground: #737373;
--muted: #f5f5f5;
--border: #e5e5e5;
--primary: #0a0a0a;
--primary-foreground: #fafafa;
}
.dark {
--foreground: #ededed;
--background: #0a0a0a;
--muted-foreground: #a1a1a1;
--muted: #171717;
--border: #262626;
--primary: #fafafa;
--primary-foreground: #0a0a0a;
}
Slide primitives use Tailwind utilities that resolve to these variables:
text-foreground / bg-background — main text and backgrounds
text-muted-foreground — secondary text (SlideSubtitle, SlideNote)
border-border — borders on Slide, SlideCode
bg-primary text-primary-foreground — badges and accent elements
Code Block Customization
Override code block styling with --nxs-code-* variables:
:root {
--nxs-code-bg: #ffffff;
--nxs-code-border: #eaeaea;
--nxs-code-text: #24292e;
}
.dark {
--nxs-code-bg: #0a0a0a;
--nxs-code-border: #262626;
--nxs-code-text: #ededed;
}
These control the <SlideCode> block container (background, border, default text color).
Syntax Highlighting
Customize highlight.js token colors with --sh-* variables. The library provides a Vercel-inspired theme by default:
:root {
--sh-keyword: #d73a49; /* if, const, function */
--sh-string: #032f62; /* 'Hello' */
--sh-property: #005cc5; /* object.property */
--sh-class: #6f42c1; /* ClassName */
--sh-entity: #6f42c1; /* functionName */
--sh-tag: #22863a; /* <Component> */
--sh-identifier: #24292e; /* variables */
--sh-literal: #005cc5; /* true, false, null */
--sh-comment: #6a737d; /* // comment */
--sh-sign: #24292e; /* punctuation */
}
.dark {
--sh-keyword: #ff7b72;
--sh-string: #a5d6ff;
--sh-property: #79c0ff;
--sh-class: #d2a8ff;
--sh-entity: #d2a8ff;
--sh-tag: #7ee787;
--sh-identifier: #ededed;
--sh-literal: #79c0ff;
--sh-comment: #7a7a7a;
--sh-sign: #ededed;
}
Dracula Theme Example
For a Dracula-inspired syntax theme:
.slides-alt-deck {
--nxs-code-bg: #282a36;
--nxs-code-border: #44475a;
--nxs-code-text: #f8f8f2;
--sh-keyword: #ff79c6;
--sh-string: #f1fa8c;
--sh-property: #8be9fd;
--sh-class: #bd93f9;
--sh-entity: #50fa7b;
--sh-tag: #50fa7b;
--sh-identifier: #f8f8f2;
--sh-literal: #bd93f9;
--sh-comment: #6272a4;
--sh-sign: #f8f8f2;
}
Apply via className on SlideDeck (see Multiple Decks).
Tailwind Integration
The library stylesheet includes an @source directive that tells Tailwind v4 to scan component files:
This automatically makes library utilities available without manual configuration.
Import Order
Import the library stylesheet after Tailwind:
@import 'tailwindcss';
@import 'nextjs-slides/styles.css';
This ensures:
- Tailwind utilities are available to slide components
- Library CSS variables override defaults
- Utility classes aren’t overridden by layer ordering
Don’t wrap the library import in @layer. Layered imports can be overridden by Tailwind utilities, breaking responsive layouts.
Geist Fonts
Optionally use Vercel’s Geist font family for a polished look:
Configure fonts in layout
import { GeistSans } from 'geist/font/sans';
import { GeistMono } from 'geist/font/mono';
import { GeistPixelSquare } from 'geist/font/pixel';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html
lang="en"
className={`${GeistSans.variable} ${GeistMono.variable} ${GeistPixelSquare.variable}`}
>
<body className={GeistSans.className}>{children}</body>
</html>
);
}
Add theme variables
@theme inline {
--font-sans: var(--font-geist-sans), ui-sans-serif, system-ui, sans-serif;
--font-mono: var(--font-geist-mono), ui-monospace, monospace;
--font-pixel: var(--font-geist-pixel-square), var(--font-geist-sans), ui-sans-serif, system-ui, sans-serif;
}
Use pixel font on specific slides
<Slide key="title">
<SlideTitle className="font-pixel">nextjs-slides</SlideTitle>
<SlideSubtitle>Composable slide deck primitives</SlideSubtitle>
</Slide>
Apply font-pixel via className only on specific slides (title, closing). Body text uses Geist Sans by default.
Custom Fonts
Use any font via next/font:
import { Playfair_Display } from 'next/font/google';
const playfair = Playfair_Display({
subsets: ['latin'],
variable: '--font-playfair',
});
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" className={playfair.variable}>
<body className={playfair.className}>{children}</body>
</html>
);
}
Or scope to a specific deck:
.slides-alt-deck {
font-family: var(--font-playfair), serif;
}
Slide Transitions
The library uses React 19 <ViewTransition> with custom CSS animations:
/* Forward navigation */
::view-transition-new(.slide-from-right) {
--nxs-slide-offset: 60px;
animation: nxs-slide-in 200ms ease-out both;
}
::view-transition-old(.slide-to-left) {
--nxs-slide-offset: -60px;
animation: nxs-slide-out 200ms ease-out both;
}
/* Backward navigation */
::view-transition-new(.slide-from-left) {
--nxs-slide-offset: -60px;
animation: nxs-slide-in 200ms ease-out both;
}
::view-transition-old(.slide-to-right) {
--nxs-slide-offset: 60px;
animation: nxs-slide-out 200ms ease-out both;
}
/* Deck exit animation */
::view-transition-old(.deck-unveil) {
animation: nxs-deck-unveil 300ms ease-out both;
}
Override these in your own CSS to customize transitions:
::view-transition-new(.slide-from-right) {
animation: custom-slide-in 400ms ease-in-out;
}
@keyframes custom-slide-in {
from {
opacity: 0;
transform: translateY(20px) scale(0.95);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
Troubleshooting
SlideCode syntax highlighting looks broken
- Ensure
nextjs-slides/styles.css is imported after Tailwind
- Check that
--sh-* variables are defined in :root or .dark
Split layout not stacking on mobile
- Don’t wrap the import in
@layer
- Import library CSS after Tailwind
- As a fallback, add
@source "../node_modules/nextjs-slides/dist" manually
Slide utility classes not applying
- The
@source directive should auto-scan component files
- If that fails, manually add the dist path to your CSS
Custom font not loading
- Verify the CSS variable is defined in
@theme
- Apply via
className on specific components
- Check Network tab for font file 404s