Tailwind Markdown Base is a simple plugin that adds base styling for elements generated by markdown or a wysiwyg from a cms.
# Install with NPM
npm install --save @geoffcodesthings/tailwind-md-base
# Or use Yarn
yarn add @geoffcodesthings/tailwind-md-base
// tailwind.config.js
const tailwindMdBase = require('@geoffcodesthings/tailwind-md-base');
module.exports = {
theme: {
...
},
plugins: [tailwindMdBase()],
};
By default, Tailwind Markdown Base wraps its generated styles in a .markdown
class. This, of course, is configurable in tailwind.config.js
:
// tailwind.config.js
const tailwindMdBase = require('@geoffcodesthings/tailwind-md-base');
module.exports = {
theme: {
markdownBase: {
wrapperClass: 'content',
},
},
plugins: [tailwindMdBase()],
};
The example above would wrap the styles generated by the plugin with
.content
instead of the default.markdown
.
With the exception of wrapperClass
, the default config is simply CSS-in-JS syntax. This allows you to customize the styles as much as you need in a standardized manner.
const defaultTheme = require('tailwindcss/resolveConfig')(
require('tailwindcss/defaultConfig'),
).theme;
module.exports = {
wrapperClass: 'markdown',
h1: {
fontSize: defaultTheme.fontSize['4xl'],
fontWeight: defaultTheme.fontWeight.bold,
marginTop: 0,
marginBottom: defaultTheme.spacing[2],
},
h2: {
fontSize: defaultTheme.fontSize['3xl'],
fontWeight: defaultTheme.fontWeight.bold,
marginTop: 0,
marginBottom: defaultTheme.spacing[2],
},
h3: {
fontSize: defaultTheme.fontSize['2xl'],
fontWeight: defaultTheme.fontWeight.bold,
marginTop: 0,
marginBottom: defaultTheme.spacing[2],
},
h4: {
fontSize: defaultTheme.fontSize.xl,
fontWeight: defaultTheme.fontWeight.bold,
marginTop: 0,
marginBottom: defaultTheme.spacing[2],
},
h5: {
fontSize: defaultTheme.fontSize.lg,
fontWeight: defaultTheme.fontWeight.bold,
marginTop: 0,
marginBottom: defaultTheme.spacing[2],
},
h6: {
fontSize: defaultTheme.fontSize.base,
fontWeight: defaultTheme.fontWeight.bold,
marginTop: 0,
marginBottom: defaultTheme.spacing[2],
},
p: {
marginTop: 0,
marginBottom: defaultTheme.spacing[4],
},
a: {
color: defaultTheme.colors.blue[500],
textDecoration: 'none',
'&:hover': {
color: defaultTheme.colors.blue[600],
textDecoration: 'none',
},
},
blockquote: {
borderColor: defaultTheme.colors.gray[300],
borderLeftWidth: defaultTheme.borderWidth[4],
fontWeight: defaultTheme.fontWeight.normal,
fontStyle: 'italic',
marginTop: defaultTheme.spacing[8],
marginBottom: defaultTheme.spacing[8],
paddingLeft: defaultTheme.spacing[6],
color: defaultTheme.colors.gray[800],
fontSize: defaultTheme.fontSize.lg,
},
code: {
backgroundColor: defaultTheme.colors.gray[300],
paddingLeft: defaultTheme.spacing[2],
paddingRight: defaultTheme.spacing[2],
paddingTop: defaultTheme.spacing.px,
paddingBottom: defaultTheme.spacing.px,
borderRadius: defaultTheme.borderRadius.default,
fontSize: defaultTheme.fontSize.sm,
},
hr: {
borderBottomWidth: defaultTheme.borderWidth.default,
borderColor: defaultTheme.colors.gray[300],
marginTop: defaultTheme.spacing[12],
marginBottom: defaultTheme.spacing[12],
borderRadius: defaultTheme.borderRadius.full,
},
ul: {
listStyleType: defaultTheme.listStyleType.disc,
listStylePosition: 'inside',
marginTop: defaultTheme.spacing[4],
marginBottom: defaultTheme.spacing[4],
},
ol: {
listStyleType: defaultTheme.listStyleType.decimal,
listStylePosition: 'inside',
marginTop: defaultTheme.spacing[4],
marginBottom: defaultTheme.spacing[4],
},
table: {
width: '100%',
color: defaultTheme.colors.gray[900],
marginBottom: '1rem',
padding: 0,
borderCollapse: 'collapse',
tr: {
borderTopWidth: defaultTheme.borderWidth.default,
borderColor: defaultTheme.colors.gray[700],
backgroundColor: defaultTheme.colors.white,
margin: 0,
padding: 0,
'&:nth-child(2n)': {
backgroundColor: defaultTheme.colors.gray[100],
},
th: {
fontWeight: defaultTheme.fontWeight.bold,
borderWidth: defaultTheme.borderWidth.default,
borderColor: defaultTheme.colors.gray[700],
textAlign: 'left',
margin: 0,
padding: '6px 13px',
'&:first-child': {
marginTop: 0,
},
'&:last-child': {
marginBottom: 0,
},
},
td: {
borderWidth: defaultTheme.borderWidth.default,
borderColor: defaultTheme.colors.gray[700],
textAlign: 'left',
margin: 0,
padding: '6px 13px',
'&:first-child': {
marginTop: 0,
},
'&:last-child': {
marginBottom: 0,
},
},
},
},
};
We currently only have default styles for the the most common elements generated by markdown. However, because of the CSS-in-JS syntax, you may add styling for any element in you config.
For example, if you want to style img
elements within the .markdown
namespace, you can do so like this:
// tailwind.config.js
const defaultTheme = require('tailwindcss/defaultTheme');
const tailwindMdBase = require('@geoffcodesthings/tailwind-md-base');
module.exports = {
theme: {
markdownBase: {
img: {
maxWidth: '100%',
borderWidth: defaultTheme.borderWidth.default,
borderColor: defaultTheme.colors.gray[600],
},
},
},
plugins: [tailwindMdBase()],
};
The above example would add the following to the generated CSS:
.markdown > img {
max-width: 100%;
border-width: 1px;
border-color: #718096;
}
Headings such as h1
, h2
, h3
, h4
, h5
, and h6
include some basic styling inspired by frameworks like Bootstrap and Bulma.
<h1>h1. Hello World</h1>
<h2>h2. Hello World</h2>
<h3>h3. Hello World</h3>
<h4>h4. Hello World</h4>
<h5>h5. Hello World</h5>
<h6>h6. Hello World</h6>
The CSS generated for headings by this plugin is:
.markdown h1 {
font-size: 2.25rem;
font-weight: 700;
margin-top: 0;
margin-bottom: 0.5rem;
}
.markdown h2 {
font-size: 1.875rem;
font-weight: 700;
margin-top: 0;
margin-bottom: 0.5rem;
}
.markdown h3 {
font-size: 1.5rem;
font-weight: 700;
margin-top: 0;
margin-bottom: 0.5rem;
}
.markdown h4 {
font-size: 1.25rem;
font-weight: 700;
margin-top: 0;
margin-bottom: 0.5rem;
}
.markdown h5 {
font-size: 1.125rem;
font-weight: 700;
margin-top: 0;
margin-bottom: 0.5rem;
}
.markdown h6 {
font-size: 1rem;
font-weight: 700;
margin-top: 0;
margin-bottom: 0.5rem;
}
Paragraphs receive 1rem
of margin-bottom
to provide some space between them.
Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Duis mollis, est non commodo luctus.
Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Duis mollis, est non commodo luctus.
<p>Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Duis mollis, est non commodo luctus.</p>
<p>Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Duis mollis, est non commodo luctus.</p>
The CSS generated for paragraphs by this plugin is:
.markdown p {
margin-top: 0;
margin-bottom: 1rem;
}
Links receive some base styling such as color
and text-decoration
as well as :hover
styling.
<a href="#">This is a link</a>
The CSS generated for links by this plugin is:
.markdown a {
color: #4299e1;
text-decoration: none;
}
.markdown a:hover {
color: #3182ce,
text-decoration: none;
}
Blockquotes receive base styling inspired by GitHub's markdown styles.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.
<blockquote>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.</p>
</blockquote>
The CSS generated for blockquotes by this plugin are:
.markdown blockquote {
border-color: #e2e8f0;
border-left-width: 4px;
font-weight: 400;
font-style: italic;
margin-top: 2rem;
margin-bottom: 2rem;
padding-left: 1.5rem;
color: #2d3748;
font-size: 1.125rem;
}
The code
tag is simply styled with the intention of use with inline code
. I can also be used with code blocks
if not using syntax highlighting.
This is what inline code
looks like.
<p>This is what <code>inline code</code> looks like.</p>
The CSS generated for code
tags by this plugin is:
.markdown code {
background-color: #e2e8f0;
padding-left: 0.5rem;
padding-right: 0.5rem;
padding-top: 1px;
padding-bottom: 1px;
border-radius: 0.25rem;
font-size: 0.875rem;
}
Horizontal rules receive some base styling as well. They are intentionally kept subtle.
<hr />
The CSS generated for horizontal rules by this plugin is:
.markdown hr {
border-bottom-width: 1px;
border-color: #e2e8f0;
margin-top: 3rem;
margin-bottom: 3rem;
border-radius: 9999px;
}
Lists, ul
and ol
are stripped of their styling in Tailwind. This plugin adds some of those styles back.
<!-- UNORDERED LIST -->
<ul>
<li>Apples</li>
<li>Oranges</li>
<li>Bananas</li>
</ul>
<!-- ORDERED LIST -->
<ol>
<li>Apples</li>
<li>Oranges</li>
<li>Bananas</li>
</ol>
The CSS generated for lists by this plugin is:
.markdown ul {
list-style-type: disc;
list-style-position: inside;
margin-top: 1rem;
margin-bottom: 1rem;
}
.markdown ol {
list-style-type: decimal;
list-style-position: inside:
margin-top: 1rem;
margin-bottom: 1rem;
}
Table styles are very simple with minor additions to make them look like, well... tables.
# | First | Last | Handle |
---|---|---|---|
1 | Mark | Otto | @mdo |
2 | Jacob | Thornton | @fat |
3 | Larry | the Bird |
<table>
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">1</th>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<th scope="row">2</th>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<th scope="row">3</th>
<td>Larry</td>
<td>the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
The CSS generated for tables by this plugin is:
.markdown table {
width: 100%;
color: #1a202c;
margin-bottom: 1rem;
padding: 0;
border-collapse: collapse;
}
.markdown table tr {
border-top-width: 1px;
border-color: #4a5568;
background-color: #fff;
margin: 0;
padding: 0;
}
.markdown table tr:nth-child(2n) {
background-color: #f7fafc;
}
.markdown table tr th {
font-weight: 700;
border-width: 1px;
border-color: #4a5568;
text-align: left;
margin: 0;
padding: 6px 13px;
}
.markdown table tr th:first-child {
margin-top: 0;
}
.markdown table tr th:last-child {
margin-bottom: 0;
}
.markdown table tr td {
border-width: 1px;
border-color: #4a5568;
text-align: left;
margin: 0;
padding: 6px 13px;
}
.markdown table tr td:first-child {
margin-top: 0;
}
.markdown table tr td:last-child {
margin-bottom: 0;
}
There is plenty of room for improvement (support for more base styles, other enhancements, .etc). Contributions are welcome. If you have an idea for improvement, please submit an issue with a feature proposal first for discussion. Bug fixes can be PR'd directly. Be sure to write tests for any new features and make sure all tests pass before submitting any PR.