Skip to main content
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:
globals.css
@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:
globals.css
: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:
globals.css
: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:
globals.css
.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:
nextjs-slides/styles.css
@source "./*.js";
This automatically makes library utilities available without manual configuration.

Import Order

Import the library stylesheet after Tailwind:
globals.css
@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:
1

Install Geist

npm install geist
2

Configure fonts in layout

app/layout.tsx
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>
  );
}
3

Add theme variables

globals.css
@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;
}
4

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:
app/layout.tsx
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:
globals.css
.slides-alt-deck {
  font-family: var(--font-playfair), serif;
}

Slide Transitions

The library uses React 19 <ViewTransition> with custom CSS animations:
nextjs-slides/styles.css
/* 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:
globals.css
::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

Build docs developers (and LLMs) love