Layout and Styling in MDX Posts

2025-04-14

📐 Layout Wrappers for MDX Content

To keep your MDX content visually consistent with the rest of your site, wrap it in a styled <article> using Tailwind’s prose utilities. This gives you clean typographic defaults, while still allowing full control through your MDX component overrides.

<article className="prose dark:prose-invert max-w-3xl mx-auto py-10">
  <Content />
</article>

This wrapper ensures your MDX content is readable, centered, and styled consistently across light and dark themes.


🌬️ Breathing Room & Vertical Rhythm

While prose handles default spacing, JSX components you define in useMDXComponents need intentional spacing to maintain flow—especially for headings and paragraphs.

Use mt-* Tailwind utilities to restore vertical rhythm:

h2: (props) => <h2 className="mt-6 text-4xl" {...props} />,

Here’s an example of a well-structured useMDXComponents config:

import type { MDXComponents } from "mdx/types";
import { Button } from "@/components/ui/button";

export function useMDXComponents(
  components: MDXComponents = {}
): MDXComponents {
  return {
    h1: (props) => <h1 className="mt-10 text-6xl font-bold" {...props} />,
    h2: (props) => <h2 className="mt-8 text-4xl font-bold" {...props} />,
    h3: (props) => <h3 className="mt-6 text-2xl font-bold" {...props} />,
    h4: (props) => <h4 className="mt-5 text-xl font-bold" {...props} />,
    h5: (props) => <h5 className="mt-4 text-lg font-bold" {...props} />,
    h6: (props) => <h6 className="mt-3 text-base font-bold" {...props} />,
    p: (props) => <p className="mt-4 text-base leading-relaxed" {...props} />,
    div: (props) => <div className="mt-4" {...props} />,
    hr: (props) => <hr className="my-4" {...props} />,
    code: (props) => (
      <code
        className="px-1.5 py-0.5 rounded bg-zinc-100 dark:bg-zinc-800 text-sm font-mono text-pink-600"
        {...props}
      />
    ),
    pre: (props) => (
      <pre
        className="my-6 overflow-x-auto rounded bg-zinc-100 dark:bg-zinc-900 p-4 text-sm leading-relaxed"
        {...props}
      />
    ),
    Button: (props) => <Button {...props} />,
    ...components,
  };
}