欢迎大家来到IT世界,在知识的湖畔探索吧!
写在前文
最近我自己也体验了一下 tailwindcss,作为一个很喜欢写 CSS 的人,体验完之后,说实话还是觉得有点儿不太顺手,但是我确实因为它不愿意再新建一个 CSS 文件了。这种有点儿难受又有点儿爽的心态让我继续沉迷于 tailwindcss 。恰好昨晚看到我的好朋友在知乎上写了一些关于它的文章,情不自禁转来分享大家。
下面是原文:
经过一段时间的使用,tailwindcss 方案已经能够很流畅的使用了,没有想象中的不适感,整体设计风格很统一,熟练之后能够很流畅地写出复杂样式,和传统的css、less相比,明显的感受是上下文切换变少了,和 css-in-js 相比,敲键盘次数变少了,原以为只是一个 css 工具集,但它的强大超出我的预期,一些复杂的联动效果也能轻松完成。
能点击进来看到本文的应该都多多少少听过 tailwindcss,本文会结合我的使用体验,将tailwindcss方案的核心思想梳理一番。
官方在线 Playground 地址: Tailwind Play(https://play.tailwindcss.com/)
背景
一直以来一个项目的 css 方案都是让前端开发者头痛的问题,相似结构的重复样式导致冗余[1]、样式和内容耦合导致内容变动后样式也对应修改、大量无意义元素取名困难、大型项目容易命名冲突,缺少和JS类似的模块化方案,css语义不清晰阅读困难、缺少嵌套支持等。
传统的方案例如语义化 CSS 追求的是内容优先,例如 CSS 禅意花园: CSS 设计之美(https://www.csszengarden.com/tr/zh-cn/) ,这种规范以 HTML 内容优先,HTML无关样式,通过样式表让HTML具有不同的风格,这是早期人们对样式表的理解。优点是内容无关样式,但是缺点同样地导致样式非常和内容相关,内容变动导致样式需要大量修改。
BEM 方案通过给HTML增加大量类名,优点是依然保留的上面的语义化,HTML 可读性好,而且可以避免类名重复,缺点对应的是类名膨胀,尤其是在书写具有相似结构的组件时,会产生大量冗余的类名,在面对一些无意义元素时也需要对其命名。
为了解决BEM, 自定义类名等方案带来的问题,使用工具类能有效地减少css冗余、样式复用等问题,于是作者以工具类优先的原则开发了 tailwindcss。
使用
tailwindcss 本体是一个 Postcss 插件, 支持命令行启动,其核心工作流程如下[2]。
tailwindcss是一个postcss插件,工作流如图 tailwind 会将生成的样式表插入到对应的插槽中。所以我们必须有一个css文件包含下面三句,否则tailwindcss不会产生任何效果。
@tailwind base;
@tailwind components;
@tailwind utilities;
欢迎大家来到IT世界,在知识的湖畔探索吧!
其中 tailwind base 相当于一份重置样式表,包含了最基础的样式。tailwind components 包含了一些组件类, 组件相当于复合样式,tailwind utilities 包含了工具类,也就是 flex mx-auto 这些内置样式。
这么划分的原因是因为 css 的优先级规则,tailwindcss 全部都是一级样式,在类名权重相等的情况,下面的样式可以覆盖上面的样式,所以工具类优先,组件类次之,基础样式兜底,生成的样式顺序尤为重要,所以 上面三句指令的顺序非必须建议不要修改。
类名规则
tailwindcss 内置了大量工具类名,理论上可以做到100%使用内置方案覆盖,下面看一些具体的命名规则:
tailwindcss 的命名规范很统一,具有唯一性的样式属性会直接作为对应的类名,例如 block, absolute, flex, top-0, overflow-hidden, whitespace-nowrap, border, border-black 只看名称就能唯一确定属性,符合开发直觉。
- block -> display: block
- absolute -> position: absolute
- m-auto -> margin: auto
- p-auto -> padding: auto
- mx-2 -> margin-left: 0.5rem; margin-right: 0.5rem
对于一些 css 通用名称,tailwindcss提供了统一的规范。例如 left, right, top, bottom, 分别对应 l, r, t, b。left-right 对应 x, top-bottom 对应 y。 所以产生了下面的类名:
- ml-[2px] -> margin-left: 2px;
- mr-[2px] -> margin-right: 2px;
- mx-[2px] -> margin-left: 2px; margin-right: 2px;
- pt-2 -> padding-top: 0.5rem;
- pb-2 -> padding-bottom: 0.5rem;
- border-r -> border-right-width: 1px;
- border-b -> border-bottom-width: 1px;
所以如果想写一个上边框黑色,上下外边距 2px, 上内边距10px,可以如下:
<div class=”border-t border-black my-[2px] pt-[10px] “/>
其他简写也会符合越常用越简写的原则,来看一些案例
- bg-black-> background: black
- bg-[url(/img.png)]-> background: url(/img.png)
- bg-norepeat -> background: no-repeat
- text-[#333] -> color: #333
- w-[200px] -> width: 200px
- h-[200px] -> height: 200px
- whitespace-nowrap -> white-space: nowrap
- transition-opacity -> transition-property: opacity;transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);transition-duration: 150ms;
所以我想写一个宽高 200, 黑底白字,过渡效果为背景色,过渡时间为 300ms,可以如下
<div class=”w-[200px] h-[200px] bg-black text-white transition-bg duration-[300ms]”>
再有一些类名也大致满足如上规则,前期需要对照文档查每个属性的类名,习惯之后可以凭借记忆和规则猜出类名。
修改器 hover, focus, before, after, group, important
在 tailwindcss 中,修改器语法为 修改器:类名 修改器的种类很多且可扩展。内置的修改器如下:
- 伪类选择器: hover, focus, active
- 子选择器: first, last, even, odd
- 父状态选择器: group <- tailwindcss 特有
- 伪元素: before, after
- !important修改器
案例 1:hover:bg-sky-500 当 hover 时应用此类名
<div class=”hover:bg-sky-500 w-[200px] h-[200px] bg-black text-white transition-bg duration-[300ms]”>
案例2:first:bg-sky-500 第一个子元素
欢迎大家来到IT世界,在知识的湖畔探索吧!<div>
<div class="w-[20px] h-[20px] mt-[10px] bg-gray-300 first:bg-sky-500"/>
<div class="w-[20px] h-[20px] mt-[10px] bg-gray-300 first:bg-sky-500"/>
<div class="w-[20px] h-[20px] mt-[10px] bg-gray-300 first:bg-sky-500"/>
</div>Ï
案例3: group, group-hover 父状态选择器,当父组件 hover 时,子元素高亮
<div class="group border-b whitespace-nowrap text-gray-300">
<div class="w-[20px] h-[20px] mt-[10px] bg-gray-300"> pick me </div>
<div class="w-[20px] h-[20px] mt-[10px] bg-gray-300 group-hover:text-sky-500">
pick me
</div>
<div class="w-[20px] h-[20px] mt-[10px] bg-gray-300"> pick me</div>
</div>
案例4: !, important 修改器。
由于权重问题,有时我们的的确确添加了两个相同功能类名,例如 bg-white, bg-black, 此时我们想强制让某一个生效,则可以使用 ! 修改器。这种情况可能出现在你想覆盖某个组件内样式的场景。
<div class=”bg-white !bg-black”/>
任意属性值
在 tailwindcss 3.x 之后,tailwindcss 默认开启了JIT模式,该模式能够让我们书写动态 CSS 样式,不再受到静态规则集的限制。除了内置了一些常用属性值, 例如 ml-2 表示 margin-left: 0.5rem , 有时我们需要一些特定的值,tailwindcss 对这种情况提供了很好的支持,任何需要自定义值的属性,可以使用方括号来表示。例如
- w-full -> width: 100%
- w-[100px] -> width: 100px
- text-[#333]
- top-[10px]
- bg-[#999]
JIT模式的支持解决了传统 class 方案的不灵活的问题,从此再也不需要添加自定义样式。
响应式设计
对于一些需要 media query 实现的响应式样式,tailwindcss 提供了一组默认规则,使用 min-width 实现的断点功能实现响应式方案。默认的几个断点如下
min-width 表示当屏幕尺寸大于等于该值则应用此规则。所以 tailwindcss 的规则是基于 大于等于 做判断, 下图可以直观感受下每个选择器的范围。
这样的特性使得,我们的基础样式必须为小屏幕手机的才可以,所以 tailwindcss 具有移动端优先的特点。
<div className=”flex flex-wrap sm:flex-nowrap”/>
上面的样式为:在小屏幕手机上应用 flex flex-wrap, 在大屏幕上应用 flex-nowrap.
自定义样式类
如果想在项目内添加自己实现的类,例如如下
欢迎大家来到IT世界,在知识的湖畔探索吧!.article {
position: relative;
color: orange;
line-height: 1.2;
font-family: ...;
@apply text-ellipsis;
}
这里 tailwind 建议写在主文件(具有tailwind指令的文件)并放在对应的 layer 下,所以需要改成如下
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
.article {
position: relative;
color: orange;
line-height: 1.2;
font-family: ...;
@apply text-ellipsis;
}
}
原因是因为 css 类名都是一级类名,权重相同,只能使用顺序来确保覆盖规则,使用这个指令可以让生成的最终css文件内, article 类名在 utilities之前,这样当我们写如下样式
<div class=”article absolute”/>
才能保证工具类名(absolute)正确覆盖组件类名(article)。放在 layer 代码块之内还有一个好处,tailwindcss 会自动帮我们剔除没有用到的类名,如果放在普通 css 代码块内则没有这种效果。
总结
我已经有好几个个人应用完全使用 tailwindcss 了,期间没有写过一行 css,经过实践验证目前的版本已经足够好用了(相比于2.x)。个人感觉该方案的书写便利程度远超 css-in-js, css module 等方案,推荐各位尝试,相信不会令大家失望。
参考
- CSS Utility Classes and “Separation of Concerns”: https://adamwathan.me/css-utility-classes-and-separation-of-concerns/
- https://github.com/tailwindlabs/tailwindcss
作者:龙背上的骑兵
来源:微信公众号:相学长
出处:https://mp.weixin.qq.com/s/YH3RCYGdvd67jkmN8DPIgg
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://itzsg.com/22345.html