这么多年你还没用上Tailwind CSS?(附独家秘法)

7,829 阅读10分钟

Tailwind CSS是什么?

Tailwind CSS是utility-first(功能类优先)的CSS框架,功能类优先是指在一组受约束的原始功能类的基础上构建复杂的组件,Tailwind CSS内置了很多CSS类,直接放在HTML class属性中,以代替CSS。

项目中安装配置Tailwind CSS很简单,这里不再赘述,看官网文档即可。使用Tailwind CSS后,我们不再去写内联样式或者css文件,而是在html标签的class属性中写一连串类名就行了。如图:

ezgif.com-optimize.gif

为什么使用Tailwind CSS?

最主要的我觉得有4个:

  1. 有利于样式维护,可以看看作者写的这篇文章,CSS Utility Classes and "Separation of Concerns"
  2. 减少了命名负担,写的样式的时候不用花大量时间考虑class命名了,提高了工作效率。
  3. Tailwind CSS使用了JIT技术,使得打包出来的样式文件体积很小。
  4. 非常易用的设计系统API。可以很容易地适配任何设计系统。大型网站一般都有设计系统,设计系统就是一套design token和UI规范,design token限制了样式能用的值是在一个范围内甚至是枚举的。Tailwind CSS是有限的原子功能类集合,所以它天然切合设计系统。

Tailwind CSS 原理

Tailwind CSS设计的很巧妙,它在螺蛳壳里造道场,利用class属性就实现了整套css语法。 细心的你肯定想到了,class属性只是css众多选择器中的一个,css语法中还有类型、ID 选择器、属性选择器、伪类和伪元素、关系选择器、媒体查询等,那么Tailwind CSS是怎么实现的呢?

答案是变体,它满足css中class语法外的其他需求,比如伪类、伪元素。底层原理是Tailwind CSS是postcss插件,它可以利用postcss的能力,扫描到使用的变体,生成相应名称的功能类。 比如:伪类hover变体,语法为:

<button class="bg-sky-500 hover:bg-sky-700">
  Save changes
</button>

其背后的功能类是:

.bg-sky-500 {
  background-color: #0ea5e9;
}
.hover\:bg-sky-700:hover {
  background-color: #0369a1;
}

变体分为固定变体和动态变体2种。

固定变体

固定变体的语法为, 可以理解为条件语法,在满足条件的时候,对应的class才会生效。

使用变体后,你可以不用去关心css语法有哪些选择器,不用去记忆属性选择器、伪类和伪元素等等,你只要关心我想要用什么条件去匹配html元素。👀变体速查表

响应式

Tailwind CSS的响应式是通过响应断点变体,它是基于媒体查询的:

Breakpoint prefixMinimum widthCSS
sm640px@media (min-width: 640px) { ... }
md768px@media (min-width: 768px) { ... }
lg1024px@media (min-width: 1024px) { ... }
xl1280px@media (min-width: 1280px) { ... }
2xl1536px@media (min-width: 1536px) { ... }

所有功能类都支持响应断点变体,例如:

<!-- Width of 16 by default, 32 on medium screens, and 48 on large screens -|
<img class="w-16 md:w-32 lg:w-48" src="...">

动态变体

还有一种动态变体,作用是在万不得已的时候让你使用任意值的方式,语法为[], 例如:

<div class="grid grid-cols-[fit-content(theme(spacing.32))]">
  <!-- ... -->
</div>

甚至Tailwind CSS中没有对应css属性的类时,也能用[]

<div class="[mask-type:luminance]">
  <!-- ... -->
</div>

甚至你想在class类中达到使用自定义选择器的效果

<ul role="list">
  {#each items as item}
    <li class="[&:nth-child(3)]:underline">{item}</li>
  {/each}
</ul>

背后会生成相应的class

.\[\&\:nth-child\(3\)\]\:underline:nth-child(3) {
  text-decoration-style: underline
}

Tailwind CSS类的记忆规律

Tailwind CSS就感觉学习了一遍英语,我们知道背英语单词其实是一件很痛苦的事情,所以很多人最后放弃了Tailwind CSS。最近我尝尝在思考有没有什么方式减轻记忆 Tailwind CSS的负担,遗忘的越慢我们才能真正的把Tailwind CSS用起来。

Tailwind CSS类是功能类,以功能去索引查询逐渐忘却css属性,才是 Tailwind CSS原汁原味食用方式。但是作为前端切图仔,我们实际工作中一般都是拿到了UI设计稿会有标注并且有css代码,即使某些情况下我们去抄别的网站的样式,通过浏览器devtools看到的也是css代码。所以实际工作场景中,我们需要做一次人肉转换,看到css代码 再将其转化为 Tailwind CSS类,当然有些UI工具已经不需要这层转换了,比如figma有Tailwind CSS插件,可以直接copy Tailwind CSS类而不是 css代码。

Tailwind CSS需要以class类表示样式,那么必然得用<名称>-<值>的形式才能表达出一个具体的css属性和属性值,当然有少数是名称就表达了css属性和属性值。我统计了Tailwind CSS的功能类,可以分为6个类别的<名称>-<值>形式。嫌麻烦的可以直接滚动到最后看记忆规律结论。

1. 属性值

ClassProperties
block 等display: block;
static 等position: static;
visible 等visibility: visible;
isolate 等isolation: isolate;
antialiased 等-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;
italic 等font-style: italic;
ordinal 等font-variant-numeric: ordinal;
underline 等text-decoration-line: underline;
uppercase 等text-transform: uppercase;

2. 前缀 + 属性值

3个单词属性名变2个单词做前缀,2个单词属性名变1个单词做前缀。

Class举例Properties
aspect-{value}aspect-squareaspect-ratio: 1 / 1;
columns-{number}columns-1columns: 1;
break-after-{value}break-after-autobreak-after: auto;
break-before-{value}break-before-autobreak-before: auto;
break-inside-{value}break-inside-autobreak-inside: auto;
box-decoration-{value}box-decoration-clonebox-decoration-break: clone;
box-{value}box-borderbox-sizing: border-box;
float-{value}float-rightfloat: right;
clear-{value}clear-leftclear: left;
overflow-{value}overflow-autooverflow: auto;
overflow-x-{value}overflow-x-autooverflow-x: auto;
overscroll-{auto,contain,none}overscroll-autooverscroll-behavior: auto;
overscroll-x-{auto,contain,none}overscroll-x-autooverscroll-behavior-x: auto;
{top,right,bottom,left,inset}-{size}inset-0inset: 0px;
z-{number}z-0z-index: 0;
order-{number}order-1order: 1;
gap-{size}gap-0gap: 0px;
justify-{value}justify-normaljustify-content: normal;
justify-items-{value}justify-items-startjustify-items: start;
justify-self-{value}justify-self-autojustify-self: auto;
place-content-{value}place-content-centerplace-content: center;
place-items-{value}place-items-startplace-items: start;
place-self-{value}place-self-autoplace-self: auto;
whitespace-{value}whitespace-normalwhite-space: normal;
hyphens-{value}hyphens-nonehyphens: none;
content-{value}content-nonecontent: none;
bg-clip-{keyword}bg-clip-borderbackground-clip: border-box;
bg-repeat-{keyword}bg-repeatbackground-repeat: repeat;
bg-origin-{keyword}bg-origin-borderbackground-origin: border-box;
opacity-{percentage}opacity-0opacity: 0;
mix-blend-{value}mix-blend-normalmix-blend-mode: normal;
bg-blend-{value}bg-blend-normalbackground-blend-mode: normal;
border-{collapse,separate}border-collapseborder-collapse: collapse;
border-spacing-{size}border-spacing-0border-spacing: 0px 0px;
table-{auto,fixed}table-autotable-layout: auto;
caption-{top,bottom}caption-topcaption-side: top;
accent-{color}accent-currentaccent-color: currentColor;
cursor-{value}cursor-autocursor: auto;
caret-{color}caret-currentcaret-color: currentColor;
pointer-events-{none,auto}pointer-events-nonepointer-events: none;
scroll-{auto,smooth}scroll-autoscroll-behavior: auto;
touch-{value}touch-autotouch-action: auto;
will-change-{value}will-change-autowill-change: auto;

3. 后缀 + 属性值

Class举例Properties
start-{size}start-0inset-inline-start: 0px;
end-{size}end-0inset-inline-end: 0px;
basis-{size}basis-0flex-basis: 0px;
grow-{number}grow-0flex-grow: 0;
shrink-{number}shrink-0flex-shrink: 0;
row-span-{number}row-span-1grid-row: span 1 / span 1;
row-start-{number}row-start-1grid-row-start: 1;
row-end-{number}row-end-1grid-row-end: 1;
content-{value}content-normalalign-content: normal;
items-{value}items-startalign-items: flex-start;
self-{value}self-autoalign-self: auto;
underline-offset-{size}underline-offset-0text-underline-offset: 0px;
indent-{size}indent-0text-indent: 0px;
align-{value}align-baselinevertical-align: baseline;
scale-{percentage}scale-0transform: scale(0);
rotate-{angle}rotate-0transform: rotate(0deg);
translate-x-{size}translate-x-0transform: translateX(0px);
skew-x-{angle}skew-x-0transform: skewX(0deg);
origin-{value}origin-centertransform-origin: center;
select-{value}select-noneuser-select: none;

4. 替换词

Tailwind CSS将一些属性中的单词进行了简写和替换。

简写全拼
mmargin
ppadding
ttop
rright
bbottom
lleft
xleft & right
ytop & bottom
sinline-start
einline-end
px1px
colcolumn
full100%
minmin-content
maxmax-content
fitfit-content
screen100vw
leadingline-height
bgbackground
roundedborder-radius
Class举例Properties
p{t,r,b,l,x,y,s,e}-{size}p-0padding: 0px;
m{t,r,b,l,x,y,s,e}-{size}m-0margin: 0px;
w-{size}w-0width: 0px;
min-w-{size}min-w-0min-width: 0px;
max-w-{size}max-w-0max-width: 0rem;
h-{size}h-0height: 0px;
min-h-{size}min-h-0min-height: 0px;
max-h-{size}max-h-0max-height: 0rem;
grid-cols-{number}grid-cols-1grid-template-columns: repeat(1, minmax(0, 1fr));
grid-rows-{number}grid-rows-1grid-template-rows: repeat(1, minmax(0, 1fr));
col-span-{number}col-span-1grid-column: span 1 / span 1;
auto-cols-{size}auto-cols-autogrid-auto-columns: auto;
auto-rows-{size}auto-rows-autogrid-auto-rows: auto;
tracking-{size}tracking-tighterletter-spacing: -0.05em;
leading-{size}leading-1line-height: .25rem;
scroll-m{t,r,b,l,x,y,s,e}-{size}scroll-m-0scroll-margin: 0px;
scroll-p{t,r,b,l,x,y,s,e}-{size}scroll-p-0scroll-padding: 0px;

5. 多态

多态是指一种模式对应多个属性。

Class举例Properties
object-{value}object-containobject-fit: contain;
object-{side}object-bottomobject-position: bottom;
flex-{direction}flex-rowflex-direction: row;
flex-{value}flex-wrapflex-wrap: wrap;
flex-{number}flex-1flex: 1 1 0%;
font-{sans,serif,mono}font-seriffont-family: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;
font-{weight}font-thinfont-weight: 100;
list-{value}list-insidelist-style-position: inside;
list-{value}list-disclist-style-type: disc;
text-{size}text-xsfont-size: 0.75rem; line-height: 1rem;
text-{side}text-lefttext-align: left;
text-{color}text-blackcolor: rgb(0 0 0);
text-{ellipsis,clip}text-ellipsistext-overflow: ellipsis;
decoration-{color}decoration-currenttext-decoration-color: currentColor;
decoration-{value}decoration-solidtext-decoration-style: solid;
decoration-{size}decoration-0text-decoration-thickness: 0px;
bg-{attachment}bg-fixedbackground-attachment: fixed;
bg-{color}bg-currentbackground-color: currentColor;
bg-{side}bg-bottombackground-position: bottom;
bg-{auto,cover,contain}bg-autobackground-size: auto;
border-{size}border-0border-width: 0px;
border-{color}border-blackborder-color: rgb(0 0 0);
border-{value}border-dashedborder-style: dashed;
outline-{size}outline-0outline-width: 0px;
outline-{color}outline-currentoutline-color: currentColor;
outline-{value}outline-dashedoutline-style: dashed;
outline-{size}outline-offset-0outline-offset: 0px;
shadow-{size}shadow-smbox-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
shadow-{color}shadow-black--tw-shadow-color: #000;
snap-{value}snap-startscroll-snap-align: start;
snap-{normal,always}snap-normalscroll-snap-stop: normal;
snap-{value}snap-xscroll-snap-type: x var(--tw-scroll-snap-strictness);

6. 其他

Class举例Properties
isolation-autoisolation: auto;
invisiblevisibility: hidden;
flex-1flex: 1 1 0%;
flex-autoflex: 1 1 auto;
flex-initialflex: 0 1 auto;
growflex-grow: 1;
shrinkflex-shrink: 1;
order-firstorder: -9999;
order-lastorder: 9999;
order-noneorder: 0;
row-autogrid-row: auto;
row-span-fullgrid-row: 1 / -1;
gap-x-{size}gap-x-0column-gap: 0px;
gap-y-{size}gap-y-0row-gap: 0px;
subpixel-antialiased-webkit-font-smoothing: auto;
not-italicfont-style: normal;
normal-numsfont-variant-numeric: normal;
list-image-nonelist-style-image: none;
no-underlinetext-decoration-line: none;
normal-casetext-transform: none;
truncateoverflow: hidden;text-overflow: ellipsis;white-space: nowrap;
break-normaloverflow-wrap: normal;word-break: normal;
break-wordsoverflow-wrap: break-word;
break-keepword-break: keep-all;
inset-x-{size}inset-x-0left: 0px;right: 0px;
inset-y-{size}inset-y-0top: 0px;bottom: 0px;
line-clamp-{number}line-clamp-1overflow: hidden;display: -webkit-box;-webkit-box-orient: vertical;-webkit-line-clamp: 1;
bg-no-repeatbackground-repeat: no-repeat;
bg-gradient-{direction}bg-gradient-to-tbackground-image: linear-gradient(to top, var(--tw-gradient-stops));
outline-noneoutline: 2px solid transparent;outline-offset: 2px;
outlineoutline-style: solid;
resize-yresize: vertical;
resize-xresize: horizontal;
resizeresize: both;
snap-align-nonescroll-snap-align: none;

总结

虽然Tailwind CSS有6种命名方式,看起来很多很杂,但是我们使用代码编辑器的时候,一般都有提示器可以极度减少记忆,比如vscode插件Tailwind CSS IntelliSense。Tailwind CSS命名占比最多的是前缀 + 属性值,多态也基本可以算作前缀 + 属性值,也就是当我们敲出属性名的前几个词的时候,一般能出现提示,如果没有则尝试后缀 + 属性值, 如果还没有出现提示则尝试属性值。最后替换词其他,可以提前记忆一下,替换词大部分是常用的width、height、top等数量不多,其他大部分是容易命名冲突的属性默认值或者简化命名功能类。

未命名文件.png