I don’t spend a lot of time blogging or thinking about CSS much. For many years, there wasn’t that much interesting happening in the CSS world to me personally as a developer. The spec advanced, but it was just a layer of paint I splashed on at some point in the development cycle.
Something changed however, when I discovered Tailwind CSS. Tailwind launched it’s first alpha back in November 2017. The official v1.0 was released May 13, 2019. It came a cross my radar sometime in late 2019 as my network started chatting about it. Tailwind UI1 was a paid product that launched to tremendous success in early 2020. This success allowed the core developers to build a business and hire a small team around the parent company Tailwind Labs.
I started learning and using Tailwind shortly after Tailwind UI was released in 2020. Tailwind CSS v2.0 arrived in November 2020. The project momentum is strong, and as far as I can tell, still growing.
It should be obvious by now that I believe Tailwind CSS to be an amazing project and I think it can be one of those development points of leverage. That is to say, investing in Tailwind CSS has a transformative ROI. Not many technologies can make that claim.
The biggest issue with CSS is that it’s hard to compartmentalize. It’s designed for side effects2 and that makes it so most usage of CSS is quite fragile.
Tailwind kind of rejects half of traditional CSS. The tagline is “Utility-First” which kind of means: never style with id
s, only style with class
es. In addition, Tailwind also rewrites a good chuck of the classic css syntax into more usable, composable chunks for the modern web.
Thus:
All I can say is don’t worry about it, because they essentially took a fragile yet essential piece of web tech and somehow massaged it into something beautiful. And as an Engineer, I don’t mean beautiful aesthetically, but beautiful in that you can build great looking web components that don’t break other parts of the page as you layer them in.
In other words, properly using Tailwind CSS results in high product velocity. And as Engineering Manager and Entrepreneur, that’s really the best thing I can get out of my tech stack.
To be clear I don’t mean just shipping features fast. Embedded in the notion of high product velocity is that you not only launch quickly, but also that you have low defect rates, tech debt accumulation and mental trauma over the lifetime of the code you write. Unlike any other CSS framework, library or ecosystem I’ve come across, Tailwind achieves this.
I’ve been doing a lot of Tailwind recently. I’ve launched two web apps using it and very recently redid the CSS on this very site. The original CSS was probably from back in 2011 or so. You can see what it used to look like here.
I’m going to go over some of the more creative chunks of design I was able to pull off with Tailwind.
This site is statically generated from markdown, so the first thing was to set up a build process to pull all that html into the tailwind app so that purgeCSS can do it’s thing. You can read about how to do plain old HTML and tailwind here.
I don’t know why, but I’m particuarly keen on how blockquotes look here. The original design idea wan’t mine, but I remember seeing something like it a decade ago and coming up with my own spin on it:
Immature poets imitate; mature poets steal; bad poets deface what they take, and good poets make it into something better, or at least something different. ― T.S. Eliot, The Sacred Wood
We make heavy use of the prose
class from @tailwindcss/typography
.
The trick to this one is to extend the typography classes in tailwind.config.js
like so:
Again, since we make heavy use of prose
and its responsive size variantes, we can’t do this one in style.css.
We have to extend the default theme via the config file. the big double quote from the blockquote:before
declaration. We choose a nice serif font, escape the double-quote character ("\\201C"
) make it big and massage the margins to give a bit of offset and even break the frame a little.
We have to make sure the sizes and margin adjustments look reasonable at all the size classes we use.
I did a lot of hand tuning on this one and liberally borrowing from the default styles helped quite a bit.
A code fence from markdown looks like this:
"scripts": {
"debug": "postcss site/static/css/input.css --verbose --config debug --output site/static/css/style.css",
"build": "postcss site/static/css/input.css --verbose --config build --output site/static/css/style.css"
},
In the initial transition to Tailwind CSS, the scroll bar on the fence was white and the gray was the system gray.
I wanted the background of the scroll bar to look like the rest of the code fence and the scroll bar thumb to match the Tailwind CSS color palette.
This one just took a bit of Googling. In your input.css
or style.css
file add the following lines:
This is a great example of customizing the source input.css
file rather than tailwind.config.js
.
It’s just CSS. You can put anything you need in there.
I’m not sure why this isn’t baked into either TailwindCSS or @tailwind/typography, but there is no support for superscript <sup>
or subscript <sub>
as of 2.0 that I can find. I typically use this for math stuff like my explanation of the 1% phenomenon: 1.01365 is about 37.7 vs 0.99365 is 0.0188.
This one is easy. we just add support for <sup>
and <sub>
in input.css
or style.css
, whichever is your base css file.
Sometimes I want my links to pop out and grab the user’s attention.
Sometimes I want a quiet list of resources. you can still hover overthem, but the lack of color and underline indicates they aren’t the real focus of the content. I also use this trick for footnotes and the TOC at the top of this page as well. It’s still fairly discoverable with a mouse pointer due to the hover
state. It’s not very mobile friendly, so I do use this sparingly, especially within the main content.
We have to rely on the dreaded !important
tag for this one. If any CSS or Tailwind experts can let me know why .prose a
seems to have priority over the inner class quiet-tag
I’d love to hear why.
.quiet-link {
@apply text-gray-200 hover:bg-gray-400 hover:text-black !important;
@apply no-underline !important;
}
Also, you can’t use markdown links. You have to manually (gasp!) craft the anchor tag so you can put the quiet-link
class in there.
Footnotes are a goofy beast in plain markdown. While some markdown variants have support for them, I’ve decided to do them manually.
This is an example of mixing two Tailwind customization techniques together. This particular implementation is basically squishing tricks 3 and 4 into a couple of helper classes.
We will extend utilities
with a new class, fgoto
. This allows us to put some plain old CSS into the class.
Additionally, we use the @apply
to add in some tailwind keywords into the class.
Note the use of the !important
decorator. I couldn’t get it to work because
.prose a
kept overriding the fgoto
and freturn
styling. I couldn’t figure out how to do it without it. IF you can shed light on that, please let me know on twitter.
Using footnotes looks like this:
<a name="b3158542291"></a>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc
maximus nunc velit, sit amet scelerisque lectus consequat ut. Ut
fringilla orci nec ultrices luctus. Phasellus justo nibh,
porttitor sed varius at, posuere a arcu. Nam porta metus at elit
molestie commodo.<a href="#3158542291" class="fgoto">1</a>
Praesent aliquet mattis tempor. Curabitur leo ante, varius eget
lectus non, convallis consectetur ligula.
---
Footnotes:
<a name="3158542291"></a>
1. FOOTNOTE_CONTENTS.<a href="#b3158542291" class="freturn">↩</a>
I just use random numbers as the anchor tags but feel free to use whatever.3
You may recognize some of the css in this one. It’s basically lifted from the superscript section. I didn’t want to rely on both sup
and the fgoto
and freturn
so a bit of duplication. If this offends your sensibilities (and it reasonably might), feel free to remove the utility extension and wrap your fgoto
anchor tag with the <sup>
tag.
!important
nonsense.↩