Tailwind CSS didn't render markdown in Next.js
Issue
When I initially made this static blog with Next.js following this tutorial — Static Blog With Next.js and Markdown — below /[slug].js
code didn't render markdown properly.
// pages/post/[slug].js
import { marked } from "marked"
export default function PostPage({ ..., content }) {
return <div className="" dangerouslySetInnerHTML={{ __html: marked(content) }}></div>
}
Upon inspecting elements, I noted that markdown contents are rendered with appropriate HTML tags.
// Inspecting by logging and looking at Elements in Chrome Developer Tools
console.log(marked(content))
This markdown blog post...
<!-- markdown post -->
# title1
will turn into this HTML
<!-- HTML rendered in DOM -->
<h1>title1</h1>
But the respective CSS for the HTML elements were not applied as I was using Tailwind CSS.
Turns out Tailwind CSS negates the defaults styles and you need to specify each elements how it should look.
<h1>title1</h1>
will just be a text with default font size.
Solution
Usage
Install plugin package
npm i -D @tailwindcss/typography
Configure
// tailwind.config.js
module.exports = {
// ...
plugins: [require("@tailwindcss/typography")],
// ...
}
Add prose
class
// pages/post/[slug].js
<div className="prose" dangerouslySetInnerHTML={{ __html: marked(content) }}></div>
That's it.
What is prose
prose
class adds pre-defined set of styles for all that come inside the scope.
For example,
h1
tag in <h1>title1</h1>
will have following css applied behind the scene.
.prose :where(h1):not(:where([class~="not-prose"] *)) {
color: var(--tw-prose-headings);
font-weight: 800;
font-size: 2.25em;
margin-top: 0;
margin-bottom: 0.8888889em;
line-height: 1.1111111;
}
You can tweak prose
class by adding additional classes related to prose
like so
// pages/post/[slug].js
<div className="prose prose-lg" dangerouslySetInnerHTML={{ __html: marked(content) }}></div>
<h1>title1</h1>
will then have following styles instead
.prose-lg :where(h1):not(:where([class~="not-prose"] *)) {
font-size: 2.6666667em;
margin-top: 0;
margin-bottom: 0.8333333em;
line-height: 1;
}
You can customize further by applying more of provided class names or overriding the CSS entirely in your css file like so
// pages/post/[slug].js
<div className="prose prose-lg prose-pre:p-0" dangerouslySetInnerHTML={{ __html: marked(content) }}></div>
/* styles/globals.css */
.prose :not(pre *):where(code):not(:where([class~="not-prose"] *)) {
margin: 0;
}
.prose :where(a):not(:where([class~="not-prose"] *)) {
@apply text-blue-700 !important;
}