Add Syntax Highlighting, Line Numbers and Styling to Your MDX Blog
In this continuation of my previous post, where I demonstrated the integration of MDX into my Next.js site, we dive deeper into styling, syntax highlighting for your code blocks, line numbers and more.
Installing Dependencies
Let's start things off by installing neessary dependencies:
npm install rehype-pretty-code shiki @tailwindcss/typographyConfiguring rehype-pretty-code
Now, it's time to configure rehype-pretty-code to enable syntax highlighting and prettify your code blocks. Navigate to your utils.ts file and implement the following changes:
import rehypePrettyCode from "rehype-pretty-code"
export const getPostDataBySlug = async (slug: string): Promise<Post> => {
// Your existing code here
const { content, frontmatter } = await compileMDX({
source: file,
options: { parseFrontmatter: true,
mdxOptions: {
rehypePlugins: [
// @ts-expect-error
[rehypePrettyCode,
{
theme: 'one-dark-pro',
keepBackground: false,
filterMetaString: (string: string) =>
string.replace(/filename="[^"]*"/, ""),
}]
]
}
}
})
return {
// Your existing code here
}For more options, refer to the official documentation
Now you should be able to see syntax highlighting in your code blocks.
Example MDX
```js title="src/app/blogs/[slug]/page.tsx"
const Page = async ({ params }: { params: { slug: string } }) => {
const post = await getPostDataBySlug(params.slug)
return (
<div className="prose">{post.content}</div>
)
}
```This would render as:
const Page = async ({ params }: { params: { slug: string } }) => {
const post = await getPostDataBySlug(params.slug)
return (
<div className="prose">{post.content}</div>
)
}Adding Line Numbers
To further improve code readability, let's add line numbers to our code blocks. Start by creating a CSS file:
code {
counter-reset: line;
}
code > [data-line]::before {
counter-increment: line;
content: counter(line);
/* Other styling */
display: inline-block;
width: 1rem;
margin-right: 2rem;
text-align: right;
color: gray;
}
code[data-line-numbers-max-digits="2"] > [data-line]::before {
width: 2rem;
}
code[data-line-numbers-max-digits="3"] > [data-line]::before {
width: 3rem;
}Then, import this CSS file into your globals.css:
@import "./syntax-highlisht.css";Now, your code blocks will display line numbers alongside syntax highlighting.
Example MDX
```js title="src/app/blogs/[slug]/page.tsx"
const Page = async ({ params }: { params: { slug: string } }) => {
const post = await getPostDataBySlug(params.slug)
return (
<div className="prose">{post.content}</div>
)
}
```This would render as:
const Page = async ({ params }: { params: { slug: string } }) => {
const post = await getPostDataBySlug(params.slug)
return (
<div className="prose">{post.content}</div>
)
}Styling MDX
To style MDX we can use the @tailwindcss/typography plugin.
Add this plugin in your tailwind.config.ts file:
plugins: [require('@tailwindcss/typography'),],Now, you can apply styles by adding className="prose" to the parent element.
Which for me, is present in src/app/blogs/[slug]/page.tsx:
const Page = async ({ params }: { params: { slug: string } }) => {
const post = await getPostDataBySlug(params.slug)
return (
<div className="prose">{post.content}</div>
)
}Feel free to customize the styles further by targeting specific elements. For example, you can target the <h1> tag by adding prose-h1:text-white to the classes.
Refer to the modifiers documentation.
Resources
Thank you for following along with this blog post. I hope you found the information helpful.