惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Recent Commits to openclaw:main
Recent Commits to openclaw:main
L
LangChain Blog
月光博客
月光博客
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 【当耐特】
宝玉的分享
宝玉的分享
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Last Week in AI
Last Week in AI
人人都是产品经理
人人都是产品经理
博客园_首页
T
Tailwind CSS Blog
P
Proofpoint News Feed
雷峰网
雷峰网
D
Darknet – Hacking Tools, Hacker News & Cyber Security
IT之家
IT之家
V
Vulnerabilities – Threatpost
阮一峰的网络日志
阮一峰的网络日志
C
CERT Recently Published Vulnerability Notes
Attack and Defense Labs
Attack and Defense Labs
S
Schneier on Security
Security Archives - TechRepublic
Security Archives - TechRepublic
L
Lohrmann on Cybersecurity
V
Visual Studio Blog
云风的 BLOG
云风的 BLOG
WordPress大学
WordPress大学
The Register - Security
The Register - Security
N
Netflix TechBlog - Medium
Hugging Face - Blog
Hugging Face - Blog
Project Zero
Project Zero
博客园 - 叶小钗
F
Full Disclosure
大猫的无限游戏
大猫的无限游戏
Latest news
Latest news
S
SegmentFault 最新的问题
C
Cyber Attacks, Cyber Crime and Cyber Security
Google Online Security Blog
Google Online Security Blog
Recorded Future
Recorded Future
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Hacker News - Newest:
Hacker News - Newest: "LLM"
腾讯CDC
L
LINUX DO - 最新话题
Google DeepMind News
Google DeepMind News
P
Privacy International News Feed
I
InfoQ
F
Fortinet All Blogs
Vercel News
Vercel News
H
Hackread – Cybersecurity News, Data Breaches, AI and More
T
Threatpost
T
Tenable Blog
B
Blog RSS Feed

Max Stoiber's Essays

Save polish for where it matters How I get things done How I run gratitude circles How to present to executives Message me whenever How I manage my todos as a CEO How to run recurring virtual meetings efficiently How to have great taste How to be great at storytelling How we make brainstorming work How do you invent the future? Being unreasonably responsive has made my projects more successful Why I'm vigorous about giving feedback How to ship faster How to be better at making decisions How I tend to my digital garden David Cain: Do Quests, Not Goals Deliberate practice beats every other form of training, even via transfer learning How we foster deeper connections in our remote team Why I don't compliment people for their talent How can you slow down life? (which is perceptually half over by 23) 1:1s are for personal connection, not project updates Developer tools startups are playing on hard mode Developer tools are different than tools for any other profession You probably don't need GraphQL Margin considered harmful I am joining Gatsby Why I Write CSS in JavaScript Tech Choices I Regret at Spectrum Streaming Server-Side Rendering and Caching
Why I Love Tailwind
Max Stoiber · 2020-12-07 · via Max Stoiber's Essays

Tailwind is an atomic CSS framework that has taken the frontend world by storm. It gives developers without a deep understanding of design the ability to build visually gorgeous, modern user interfaces.

If you have not seen it before, here is the canonical Tailwind example from their original homepage:

<div class="shadow-lg flex bg-white rounded-lg p-6 leading-normal">
<img class="h-24 w-24 rounded-full mx-0 mr-6" src="avatar.jpg" />
<div class="text-left">
<h1 class="text-lg">Erin Lindford</h1>
<h2 class="text-purple-500">Customer Support</h2>
<p class="text-slate-600">erinlindford@example.com</p>
<p class="text-slate-600">(555) 765-4321</p>
</div>
</div>

Avatar of Erin Lindford

Erin Lindford

Customer Support

erinlindford@example.com

(555) 765-4321

Many people think Tailwind is cool because it uses atomic CSS. Here is the thing though: Tailwind is awesome despite using atomic CSS, not because of it.

Hear me out.

The key to Tailwind

We have had atomic CSS frameworks for almost a decade but none of them have been as critically acclaimed as Tailwind. What makes it different?

The key to Tailwind's popularity is the painstakingly constructed system of design tokens at the core of the framework. The system's carefully selected constraints give developers just the right guardrails. They make it obvious whether a choice is good or bad by offering only discrete steps.

This does require some design taste, but most frontend engineers I know have developed that over the years of building user interfaces. Tailwind's system lets them turn that taste into implementation without requiring a lot of design skill — it helps them cross "the gap".

Tailwind's system is a masterpiece of design. I, and many other developers all around the world, feel empowered by and love it.

The problem with Tailwind

The atomic CSS framework is basically a delivery mechanism that allows developers to apply the system to their UIs. It's undeniable that it has a fantastic developer experience: once you get used to the custom vocabulary you feel like you are flying!

However, we have learned over the past decade that atomic CSS has downsides:

  • Users still have to add a separate setup for the custom CSS they inevitably need (coined "bailwind"). You cannot get by on just Tailwind in the real world. Not having a dedicated place for custom styles in the same system can cause maintenance issues down the line.
  • Due to file-size considerations, Tailwind does not include all variants (e.g. hover:, sm:) for all utilities by default. It leaves it to you to manually configure which ones you need for every single CSS property.
  • Atomic CSS is not ideal for performance. No tooling can extract the per-page critical CSS, so you end up shipping more CSS to the browser than necessary. The bigger and more dynamic the app, the more unnecessary code you will ship.[^1]

Tailwind without the downsides

Brent Jackson, the creator of one of the original atomic CSS libraries, said it best in his post on atomic CSS:

“This methodology was created before React was released and was intended for use in template-based user interfaces, including Rails and PHP. It was never designed for functional component-based UI and doesn't take advantage of this new paradigm.”

Now, here is the thing: you can have your cake and eat it too. You can use Tailwind's marvelous system and fantastic developer experience without the downsides of atomic CSS.

How? twin.macro.

Let me illustrate. Here is the canonical Tailwind example built with twin.macro and React:

import 'twin.macro'

const Card = () => (
<div tw="shadow-lg md:flex bg-white rounded-lg p-6 leading-normal">
<img
tw="h-16 w-16 md:h-24 md:w-24 rounded-full mx-auto md:mx-0 md:mr-6"
src="avatar.jpg"
/>
<div tw="text-center md:text-left">
<h1 tw="text-lg">Erin Lindford</h1>
<h2 tw="text-purple-500">Customer Support</h2>
<p tw="text-slate-600">erinlindford@example.com</p>
<p tw="text-slate-600">(555) 765-4321</p>
</div>
</div>
)

Avatar of Erin Lindford

Erin Lindford

Customer Support

erinlindford@example.com

(555) 765-4321

Unsurprisingly, the result looks identical — we are still using the same system after all. Even the code looks the same, except that we use the tw prop instead of the class attribute!

However, under the hood this automatically compiles the class names to the actual CSS they refer to (with the css prop):

import 'twin.macro'

;<div tw="text-center md:text-left" />

// ↓↓↓↓↓ turns into ↓↓↓↓↓

import 'styled-components/macro'

;<div
css={{
textAlign: 'center',
'@media (min-width: 768px)': {
textAlign: 'left',
},
}}
/>

You get to use Tailwind's system and developer experience and take advantage of all the benefits of CSS-in-JS:

  • Extending your elements with custom styles is as simple as using the css prop, no extra separate setup required to "bailwind":

    import "twin.macro"

    <div
    tw="text-center md:text-left"
    css={{`
    &:hover {
    background-image: url("/bg.png");
    }
    `}}
    />

  • You can use all variants in all combinations with all utilities allowing for even more expression within the system. Since twin.macro runs at build-time, you don't have to worry about configuration or file size:

    import 'twin.macro'

    ;<div tw="sm:hover:first:bg-black">...</div>

  • You get fully automatic critical CSS extraction and code splitting. Users will only load exactly the styles they need for the page they requested — nothing more and nothing less! CSS performance does not get better.[^1]

The ideal setup for both developer and user experience!

Lesson: use twin.macro to leverage Tailwind's marvelous system and developer experience without the downsides of atomic CSS.

Rather than taking two steps forward with Tailwind's system and one step backward with atomic CSS, let's take five steps forward. Together.

[^1]: CSS-in-JS automatically extracts the critical CSS for the requested page and inlines it into a