Next.js Discord

Discord Forum

Next-mdx - How to only apply "prose" style to <pre>?

Answered
Chum salmon posted this in #help-forum
Open in Discord
Chum salmonOP
Issues:
Currently I'm using the prose style from tailwind typography on the main <div>. So it applies to the whole page (not just the code block).

Goal:
Only apply "prose" styling to the code block (<pre> tag).

If anybody knows how can I configure this, please give me a hand.

Installed libraries in this test:
    "@mdx-js/loader": "^3.1.0",
    "@mdx-js/react": "^3.1.0",
    "@next/mdx": "^15.3.2",
    "@types/mdx": "^2.0.13",
    "next": "15.3.2",
    "next-mdx-remote-client": "^2.1.2",
    "rehype-pretty-code": "^0.14.1",
    "remark-gfm": "^4.0.1",
    "shiki": "^3.4.2"
    "@tailwindcss/typography": "^0.5.16",


root/mdx-components.tsx
import type { MDXComponents } from 'mdx/types'
import CopyButton from './app/components/ui/buttons/CopyButton'
 
export function useMDXComponents(components: MDXComponents): MDXComponents {
  return {
    ...components,
    pre: (props) => {
        return (
            <div className="relative">
                <pre {...props}></pre>
                <CopyButton />
            </div>
        )
    }
    
  }
}
Answered by Chum salmon
oh man today is a good day. I found what I did wrong.
I'm glad I reread next mdx docs and next-mdx-remote-client docs.

At first I couldn't change global style for mdx files because I didn't set it up correctly with the next-mdx-remote-client.

It works out of the box if you don't use mdx-remote. But if you do, you have to import mdx-components.tsx, and use it inside <MDXRemote> props

import { getMDXComponents } from '@/mdx-components';
const components = getMDXComponents({});
        <MDXRemote 
          source={source} 
          options={options} 
          components={components}
        />
View full answer

7 Replies

Chum salmonOP
app/test/[...slug]/page.tsx
import { promises as fs } from 'fs';
import path from 'path';
import { Suspense } from 'react';
import { MDXRemote, type MDXRemoteOptions } from 'next-mdx-remote-client/rsc';
import remarkGfm from 'remark-gfm';
import rehypePrettyCode from 'rehype-pretty-code';

export default async function TutorialPostPage(props: {
  params: Promise<{ slug: string[] }>;
}) {
  const { slug } = await props.params;
  const slugPath = slug.join('/');
  const source = await fs.readFile(
    path.join(process.cwd(), 'content', `${slugPath}.mdx`),
    'utf8'
  );

  const options: MDXRemoteOptions = {
    mdxOptions: {
      remarkPlugins: [remarkGfm],
      rehypePlugins: [rehypePrettyCode],
    },
    parseFrontmatter: true,
  };

  return (
    <div className="prose mx-auto py-8">
      <Suspense fallback={<div>Loading...</div>}>
        <MDXRemote source={source} options={options} />
      </Suspense>
    </div>
  );
}


next-config.ts
import remarkGfm from 'remark-gfm'
import createMDX from '@next/mdx'
import rehypePrettyCode from "rehype-pretty-code";
 
/** @type {import('next').NextConfig} */
const nextConfig = {
  // Allow .mdx extensions for files
  pageExtensions: ['js', 'jsx', 'md', 'mdx', 'ts', 'tsx'],
  // Optionally, add any other Next.js config below
}
 
const withMDX = createMDX({
  // Add markdown plugins here, as desired
  options: {
    remarkPlugins: [remarkGfm],
    rehypePlugins: [rehypePrettyCode],
  },
})
 
// Combine MDX and Next.js config
export default withMDX(nextConfig)
Chum salmonOP
Currently I'm using a workaround by giving the "pre" tag a style similar to prose in global.css 😦
American black bear
here are a few possible things you can do. I don't exactly understand what you are trying to do but something here might help:

1. you can just do something similar to what you are already doing in globals.css
pre {
  @apply prose
}


2. or I think this might work as well in parent rendering rich text:
return (
  <div className="prose-pre">
    ...
  </div>
)


3. remove styles from other elements
return (
  <div className="prose prose-headings:prose-none prose-p:prose-none ... prose-pre:prose">
    ...
  </div>
)


4. if you can just add prose to your pre tag or prose-none to things you don't want prose
return (
  <pre className="prose">
    ...
  </pre>
)
Chum salmonOP
oh man today is a good day. I found what I did wrong.
I'm glad I reread next mdx docs and next-mdx-remote-client docs.

At first I couldn't change global style for mdx files because I didn't set it up correctly with the next-mdx-remote-client.

It works out of the box if you don't use mdx-remote. But if you do, you have to import mdx-components.tsx, and use it inside <MDXRemote> props

import { getMDXComponents } from '@/mdx-components';
const components = getMDXComponents({});
        <MDXRemote 
          source={source} 
          options={options} 
          components={components}
        />
Answer
This makes no sense to use prose but apply it to one element. You do know it brings in basically its own packed style sheet and does not treeshake?