原载于我的独立博客: https://lutaonan.com/blog/what-is-tailwindcss-and-how-did-i-apply-it-on-my-blog
如您所见,本博客在前不久进行了微小的改版,改版的目的是做一个可以承载更多元内容的版式,如无意外,在未来的不久,我会增加「摄影」和「乐评」两个新的版块。
但本文想要讨论的是 Tailwind CSS 这个框架,我用 Tailwind CSS 重写了整个博客的 UI, 减少了 90% 的 CSS 代码,开发时间加起来只有短短数小时,就完成了这个 Mobile First 的 Redesign (如果这也算 design 的话).
传统的 CSS 框架 —— 如 Bulma 之流,会预设很多组件样式,例如你只需给 <button>
一个 btn
的 class name, 你就能得到一个好看的 button. 但 Tailwind 不同,它没有提供任何的预设样式,
所以 Tailwind CSS 声称自己为:
A utility-first CSS framework for rapidly building custom designs.
Instead of opinionated predesigned components, Tailwind provides low-level utility classes that let you build completely custom designs without ever leaving your HTML.
—— Tailwind CSS 官网
可以看出,Tailwind CSS 的目的不是直接把设计过的东西给你,而是帮助你更快地实现你的设计。我想大家或多或少也有对流行 UI 框架审美疲劳的感受,Tailwind CSS 就是为此而设的。
为了解释 utility-first 的含义,我想了很久 utility 如何翻译比较信达雅,但我没有想到。所以下面我将通过亲身体验来解释 utility-first 这一词。
一直以来我很怕写 CSS, 一是我没有什么设计天赋,我只有审美天赋 —— 我知道什么是好看,但不知道怎么做才会好看。二是写 CSS 很无聊 —— 为了给一个元素定位,我需要给 HTML 元素命名,然后到样式文件写一堆无聊又重复的 CSS, 但又不想用现有框架写好的设计。 最怕的是写响应式的页面,一想到 media query 我就很头疼。
写自己博客的 CSS,时常遇到多个元素的样式有些交集:
<div class="foo">
字体颜色是黑色,需要加粗且文本居中
</div>
<div class="footer">
字体颜色是灰色,需要加粗且文本居中
</div>
遇到这种情况,我有以下选择:
.foo
.footer
都写上 font-weight: bold; text-align: center;
font-weight: bold; text-align: center;
font-weight: bold; text-align: center;
单独写成一个 class, 应用到两个 div 上这些选择我都不喜欢,我更喜欢像这样:
<style>
.text-center {
text-align: center
}
.font-bold {
font-weight: bold;
}
</style>
<div class="foo text-center font-bold">
字体颜色是黑色,需要加粗且文本居中
</div>
<div class="footer text-center font-bold">
字体颜色是灰色,需要加粗且文本居中
</div>
我喜欢像这样把一些常用的 CSS 原子化,这样可以直接通过 class name 复用到任何的元素。这些原子化的通用的 class 我们可以称为 utility. Tailwind CSS 提供的就是一些 utility, 这就是 utility-first 的含义。
在我博客首页有一个这样的导航:
HTML 结构如下:
<nav>
<div>
<div :key="navItem.title" v-for="navItem in $themeConfig.navs">
<a class="hover:text-gray-900 text-center" :href="navItem.url">
<div>{{ navItem.title }}</div>
<div>{{ navItem.alias }}</div>
</a>
</div>
</div>
</nav>
使用 Tailwind CSS, 我不必费神给几个 div 命名,也不用给 div 写一堆 flex 布局,Tailwind CSS 提供了 flex 而已要用到的预设:
<nav>
<div class="flex flex-col sm:flex-row w-full justify-center p-8">
<div :key="navItem.title" v-for="navItem in $themeConfig.navs" class="mt-6 sm:mt-0 sm:ml-6 sm:mr-6 text-gray-600">
<a class="hover:text-gray-900 text-center" :href="navItem.url">
<div>{{ navItem.title }}</div>
<div class="text-center text-sm font-serif">{{ navItem.alias.toUpperCase() }}</div>
</a>
</div>
</div>
</nav>
如果你没看过 Tailwind CSS 的文档,你可能对这些 class 比较模糊,在这里我按顺序稍作解释:
flex
: 声明这是一个 flexflex-col
: 声明 flex-direction
为 column
justify-center
: 声明 justify-content
为 center
p-8
: padding 为 8 个单位mt
: margint-top / ml
: margin-left / mr
: margin-right几个 class 就能完成 flex 布局。
你还会注意到有 hover:text-gray-900
, 这代表在 hover 的时候,color 为 gray.
这个导航在小屏幕时会变成竖向:
在上面的代码可以看到,这是通过 sm:flex-flow
实现的,意思是当屏幕大小超过 sm
时,就用 flex-flow
. 在 Tailwind CSS 的 Responsive utility 里,预设了 sm
, md
, lg
, xl
几个大小。这个 utility 减少了非常多的响应式设计代码量。
除了自己博客的例子,我特意到 dribbble 随便搜了一个设计来实现:
Codepen: https://codepen.io/djyde-1474473388/pen/RwwYPEv?editors=1000#0
Tailwind CSS 满足了我几点:
第二点很重要,也是为什么使用 Tailwind CSS 可以很容易做到好看的设计。读过 Refactoring UI 这本小书里面提到,Bad design 有时候是因为间距大小,字体大小,颜色的不统一导致的。如果没有一个固定的 Design system 规定了可以选用的这些参数,设计容易变得混乱。例如一个页面里面如果同时有 12px, 11px, 10px, 9px 大小的字,就会很难看。
Tailwind CSS 的 utility 对大小都有预设,像字体大小有 text-sm
, text-md
, text-lg
等等,颜色有 gray
, pink
, orange
等等(当然有可以自行扩展),这其实已经是一个很好的 Design system.
但 Tailwind CSS 毕竟不是一个组件框架,开发现代 Web App 的时候,只有 CSS 显然是不够的。如果选择 Tailwind CSS, 那就代表很有可能很多 (React, Vue) 组件需要自己动手实现。
另一个需要注意的地方是使用 Tailwind CSS 有一定的学习曲线,刚开始不可避免要不断翻文档,但是用她做一个页面之后基本就记住了,我的经验是用了一两天就不太需要看文档了。有点像学习 vim, 如果因为有一定的学习曲线所以错过这么好的东西,那未免太可惜了。
强烈推荐对 UI 设计感兴趣的朋友读一读 Refactoring UI, Refactoring UI 的两位作者,一个是 Tailwind CSS 的作者,一个是 Tailwind CSS Design system 的设计。
如果觉得这本书太贵,那至少读一读这篇 7 Practical Tips for Cheating at Design.
1
momocraft 2019-11-12 21:44:35 +08:00
我也在用 tailwind css, 比较香
这里的 utility 可能比较接近经济学的效用? |
2
hoyixi 2019-11-12 21:44:49 +08:00
也在用,现在写东西,最讨厌的就是写 CSS
|
3
buddie 2019-11-12 21:46:07 +08:00
本来新项目中要用,结果 team leader 一句 “我不想学别人的命名规范” 就被否了,撸纯的 css instead 😂
|
4
agdhole 2019-11-12 22:00:40 +08:00
像 sm:xx hover:xx 这种 classname 在 css 里面是怎么取的呢?
|
5
hoyixi 2019-11-12 22:01:33 +08:00
@buddie #3
这的确也是个考虑点,因为写就是一时,后面的维护才是长期的,一旦上船,想下船就能费心费力 现在我都越来越不想用那些时髦框架了,一升级,各种项目的维护扑面而来。虽说框架起到了灵活和降低复杂度的作用,但是如果框架本身折腾,带来的好处又大打折扣了 怀念 jQuery 的日子,一个字:稳 |
6
maomaomao001 2019-11-12 22:58:55 +08:00
这个好像有点像 atomic design 吧,
实践过 BEM,css modules 感觉都不是很好用 |
7
encro 2019-11-12 23:22:00 +08:00
前一阵子留意了下这个框架,发现不错,
大部分场景 bs4 已经够用了. |
8
molvqingtai 2019-11-12 23:34:01 +08:00 via Android
这篇文章有毒,会让我手机闪退 bug
|
9
April5 2019-11-13 09:10:49 +08:00
哇擦,华软的师兄,师弟?我 13 级的哈哈哈
|
10
ssshooter 2019-11-13 09:15:12 +08:00
有意思,感谢分享
|
11
feehey 2019-11-13 10:07:40 +08:00
如果文章列表采用左对齐或许可读性更好一些...
|
12
orozot 2019-11-13 10:47:08 +08:00
这个就是之前流行过的 css 原子化吧,感觉原子化用来做定位布局是很合适的,但是不太适合组件内部细节处理
|
13
zhuoyan 2019-11-13 17:25:19 +08:00
css 原子类早就不推荐了啊
|
14
widdy 2019-11-13 19:31:27 +08:00
唉我们前端圈咋这么复古。
|
16
Sapp 2020-12-18 17:09:25 +08:00
@buddie 可以尝试 css in js,然后把这些常用的样式封装成函数,直接调用函数,库会自动生成 class,解决了 class 取名问题,又有非常灵活的定制性,而且还不担心 css 污染,举个栗子
<div css = {{ ...flex(), // 自动设置 flex 相关 css ...background(url), // 自动设置类似 position,repeat 这些属性 fontWeight: 500 // 手写样式 }} >xxx</div> 最后生成的 html 大概是 <div class={xxxx-组件名-xxxx}>xxx</div> 会是一串随机字符加你的组件名,可以设置生产环节不显示组件名,就完全是一段随机字符了,css 会自动插入 这个方案和 Tailwind 应该是一个思路,并且还能利用起来编辑器给 js/ts 做的类型推导和语法提示,同时还可以在一些需要定制的时候直接写 css,不用单独再头疼写个 class 怎么命名 |
17
djyde OP @Sapp #16 你说的是 styled-system 吗 https://styled-system.com/
|