Using TailwindCSS In The World Of React

…where most components come with built-in CSS.

Alan Kesselmann
5 min readDec 17, 2021

I don’t consider myself a developer. I’ve worked as one, but I’ve also worked as product owner, project manager, technical team lead and even as a manager in sales. Programming is an exciting pastime, and I like to keep myself up to date with specific tools so if the need arises, I can contribute to projects.

So if you see that something in this text does not make sense at all — please tell me so. I’d love to learn how to do things better, but here’s something I’ve learned about using TailwindCSS, React, NextJs and other tools recently.

I was introduced to the world of TailwindCSS by a friend who acted in a role of a startup CTO back then — and was my boss. Upon the introduction, I did not find Tailwind to be anything special. Rather than just another tool to work with, I decided to go with Bootstrap since I was under the pressure of time back then.

But I did decide to use TailwindCSS with my next project, and I’ve grown to love it since then. So much so that I’ve used it in all of my projects since then, and when I decided to take a deeper look into NextJs, I first added TailwindCSS to my project.

I’ve noticed that using TailwindCSS, you don’t often want to use the CSS that some ready-to-use React components come with. But you usually can’t add your TailwindCSS classes to the code of components either. So I found that the best way to overcome this issue is to use CSS components. One thing that is awesome about NextJs is that it supports CSS modules out of the box (https://nextjs.org/docs/basic-features/built-in-css-support#adding-component-level-css).

So to my use case — I wanted to display the markdown acquired from the API in the front end. Enter react-markdown, which can display markdown just fine:

import ReactMarkdown from 'react-markdown';
...
<ReactMarkdown children={children} />
Html showed by RemarkDown component without any additional styling.

But notice how it’s just one wall of text with ~ characters in there when the HTML has many different elements:

<p>Lorem <strong>IPSUM IS SIMPLY</strong> dummy <del>text of the printing</del> and typesetting industry.<em>Lorem Ipsum has</em> been the industry’s standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</p>
<blockquote>
<p>Lorem ipsum dolor Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet .Lorem ipsum dolor sit amet Lorem ipsum dolor sit amet</p>
</blockquote>
<h1>Lorem ipsum dolor sit amet</h1>
<h2>Lorem ipsum dolor sit amet</h2>
<h3>Lorem ipsum dolor sit amet</h3>
<h4>Lorem ipsum dolor sit amet</h4>
<h5>Lorem ipsum dolor sit amet</h5>
<h6>Lorem ipsum dolor sit amet</h6>
<p>Lorem <code>ipsum</code> dolor sit amet</p>

It is straightforward to pass some styles to the ReactMarkdown component:

<ReactMarkdown children={children} className="my-markdown" />

And once you do that, you’ll notice how all the HTML generated by the component is wrapped inside the <div> with the given CSS class. But you can’t have single a classname fix all the styles for all the different elements. You could go and pass props per each component (https://github.com/remarkjs/react-markdown#appendix-b-components), but that sounds like too much work. Enter solution in the form of css modules:

// styles/components/markdown.module.css
.md {
ul {
@apply list-disc pl-4 my-3;
}

ol {
@apply list-decimal pl-4 my-3;
}

a {
@apply text-blue-500;
}

p {
@apply my-3;
}

h1 {
@apply text-xl mb-8 leading-tight;
}

h2 {
@apply text-lg mb-6 leading-tight;
}

h3 {
@apply text-base mb-4 leading-tight font-bold;
}

h4 {
@apply text-base mb-4 leading-tight;
}

h5 {
@apply text-sm mb-2 leading-tight;
}

h6 {
@apply text-xs mb-2 leading-tight;
}

code {
@apply p-0.5 border border-red-200 rounded-sm text-red-400 bg-gray-200;
}

blockquote {
@apply px-2 py-1.5 bg-gray-200 border-l-4 border-gray-400 mb-4;
}
}

Add small update to the way you use the component:

import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import styles from '../../styles/components/markdown.module.css';
...
<ReactMarkdown remarkPlugins={[remarkGfm]} className={styles.md} children={children} />

And your HTML will look much better already:

Same HTML styled by TailwindCSS and CSS components

To get around writing this much boilerplate code every time I want to use the component, I also created my wrapper around ReactMarkdown, which looks like this:

import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';

import { childrenType } from '../../types/meta';
import styles from '../../styles/components/markdown.module.css';

const ReMark = function ({ children }) {
// eslint-disable-next-line react/no-children-prop
return <ReactMarkdown remarkPlugins={[remarkGfm]} className={styles.md} children={children} />;
};

ReMark.defaultProps = {
children: () => {},
};

ReMark.propTypes = {
children: childrenType,
};

export default ReMark;

This allows me to use markdown by writing much less repeated code:

<ReMark>{my_markdown_string}</ReMark>

I’ve found creating CSS modules to be the easiest way to style existing React components in the world of TailwindCSS.

As you’ve noticed, I did not go into the details of my setup (TailwindCSS, PostCSS, DaisyUI, NextJS) and how to set it up. I’ve found that with the help of some googling, it was straightforward — most of the mentioned packages have adequate instructions for setting them up. If you need my help, though, just let me know, and I’ll do what I can to help you.

Please do let me know what you think of my approach. If you think there’s room for improvement, please let me know. I’m always eager to produce better code.

--

--