2022-04-26

Why Tailwind CSS doesn't render markdown in React/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

@tailwindcss/typography

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 }