前端的CSS发展经历了许多方案, 从早期的无序到后面的BEM,从自写到bootstrap
的火爆,从 single css file
到 css module
到 css in js
我想说说为什么我选择tailwind
, 以及为什么我觉得tailwind
这种提供工具的方式是我理想的解决方案
体积
因为tailwind
几乎不会有冗余代码,那么tailwind
项目的样式大小是可控的。此外它也不会引入无用的样式, 因为它会根据代码进行摇树优化。
可维护性与可控性
如果做过在一个现有的UI框架上进行一些覆盖样式,那么就会知道为什么说可维护性是多么重要。
因为这些工作往往是一个全局的样式。而当项目越来越复杂以后,你很难维护一个全局样式,因为你光看代码完全不知道这些代码的适用范围。当一个样式代码被越来越多人接手过后,你会发现他的可维护性越来越低 —— 因为你不敢删除任意一行代码,因为你不知道他会影响那些地方,那么你所能做的就是往上不断增加权重,不断覆盖,就如你的前人一样。
无需结构
可能很多初学者会认为BEM
很清晰,比如tree__item
就表示这是一个树的子项。但仔细想一想,你真的理解么? item
到底是什么? 他是处于一颗dom树的哪个节点? 我必须得在他的父级增加一个名为<div class="tree"></div>
的节点他的行为才是正确的么?
是的,对于BEM来说,如果是按照他的文档上所写的示例来复制的话, 这种固有的结构性是清晰的。但是如果想要深度进行一些定制的化,就显得有些力不从心了。
比如你想要修改树子项的字体大小:
1 | <div class="tree"> |
如果你不想增加行内样式, 那么你可以这样实现
1 | .tree .tree__item { |
那如果想要增加作用域, 那可能会这样实现
1 | <div class="tree foo"> |
1 | .tree.foo .tree__item { |
是的,这是一种理想情况。但是想象一下,这种方式,真的可维护么? 你可能会写出这样的代码:
1 | .tree.foo { |
看上去好像没什么问题,但是你要了解,现实情况可能更加复杂, 类名可能会有多套规则。而当我们为了修改一些样式,我们需要构造一套复杂的树形结构。这套结构是完整的,不可被破坏的。一点点的改动可能会引起整个结构树的崩溃 —— 到那时候,你真的能理解之前的代码想要表达什么意思么?
Tailwind
就不需要考虑这些问题。因为他几乎不需要额外的样式文件。当BEM在迭代中膨胀HTML与CSS时, tailwindcss
只膨胀HTML
清晰
见名知意。学习成本低,阅读成本低。和直接写inline style一样但是更加优雅与可读。
性能
越长的CSS选择器查询越慢, 没有比tailwind更快的了。因为它的选择结构最多2层, 对于一个大型的前端应用来说,无数细微的性能优势最终也有产生有价值的点。
工具类样式库
我自己也在刚学react-native
的时候写了个类似的样式库react-native-style-block。不过虽然我当时可能没有这么深刻的体会,只是本能的选择了这条路。从现在看来,这个方向完全是正确的。我相信工具类样式更加能够满足前端多变的需求。