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

推荐订阅源

人人都是产品经理
人人都是产品经理
D
Docker
GbyAI
GbyAI
B
Blog RSS Feed
博客园 - 司徒正美
博客园 - Franky
美团技术团队
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
aimingoo的专栏
aimingoo的专栏
C
Check Point Blog
IT之家
IT之家
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
www.infosecurity-magazine.com
www.infosecurity-magazine.com
AI
AI
O
OpenAI News
Attack and Defense Labs
Attack and Defense Labs
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
T
Tailwind CSS Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
S
Secure Thoughts
博客园 - 聂微东
L
LINUX DO - 最新话题
U
Unit 42
SecWiki News
SecWiki News
A
Arctic Wolf
Schneier on Security
Schneier on Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
V
Visual Studio Blog
量子位
The Cloudflare Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
大猫的无限游戏
大猫的无限游戏
Google DeepMind News
Google DeepMind News
G
Google Developers Blog
T
Threat Research - Cisco Blogs
TaoSecurity Blog
TaoSecurity Blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
B
Blog
博客园 - 【当耐特】
C
CERT Recently Published Vulnerability Notes
Scott Helme
Scott Helme
Last Week in AI
Last Week in AI
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Microsoft Security Blog
Microsoft Security Blog
Apple Machine Learning Research
Apple Machine Learning Research
F
Full Disclosure
Hacker News: Ask HN
Hacker News: Ask HN
A
About on SuperTechFans
博客园 - 三生石上(FineUI控件)
Latest news
Latest news

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