简短的概括:
发现问题:项目中css代码痛点
.mock {
margin: auto;
font-size: 16px;
// ...
}
<div class='mock'>mock</div>
复制代码
以上代码就是举个例子,大部分情况应该都是写一个类,然后整一堆样式进去。这种方式写多了以后,会感受到一些痛点,比如说:
1) 取名困难,节点结构一多,取名真的是个难事。当然了,我们可以用一些规范或者选择器的方式去规避一些取名问题。
-
需要用 JS 控制样式的时候又得多写一个类,尤其交互多的场景。
-
组件复用大家都懂,但是样式复用少之又少,这样就造成了冗余代码变多。
-
全局污染,这个其实现在挺多工具都能帮我们自动解决了。
-
死代码问题。JS 我们通过 tree shaking 的方式去除用不到的代码减少文件体积,但是 CSS 该怎么去除?尤其当项目变大以后,无用 CSS 代码总会出现。
-
样式表的插入顺序影响了 CSS 到底是如何生效的。
一、Tailwind CSS 介绍
Tailwind 能够快速将样式添加到 HTML 元素中,并提供了大量的开箱即用的设计样式。
tailwindcss 基于比组件更小、更灵活的工具类思想的 CSS 框架。这个思想简单来说就是用 class 保证灵活、便于自定义组件,而不是在组件基础上实现个性化。
如果你从来没见过 Tailwind 的实际应用,可以看这个:
<div class="bg-gray-100 rounded-xl p-8">Hello World</div>
复制代码
这里的类名就反映了 Tailwind 的定义:一个包含多个预定义类(所谓的工具类)的集合。你并不需要编写基础的 CSS 样式规则,只需要直接在 HTML 中应用已经事先定义好的类名。
这样的类名还有很多。下面这个列表展示了部分类别和对应的例子:
1)背景 (bg-gray-200, bg-gradient-to-bl)
2)弹性布局 (flex-1, flex-row)
3)网格布局 (grid-cols-1, col-span-4)
4)内边距 (p-0, p-1)
5)尺寸 (w-1, h-1)
开发大型应用的时候,每一个 HTML 元素都充斥着一大堆 Tailwind 的工具类名。
<div class="sm:w-4 md:w-6 lg:w-10 xl:w-full sm:text-sm md:text-base lg:text-base xl:text-2xl flex-1 sm:flex-none bg-black sm:bg-white rounded-md sm:rounded-none">
hello world
</div>
复制代码
问题:
要怎么组织这些类名呢?也许我们要创建并遵循某个排序规则。
解决方案:
部分 HTML 元素会使用非常多的样式,这种情况下应该考虑将样式与 HTML 标签进行分离,单独放到某个文件里。这样,我们就可以组织样式并增强其可读性。你不能把 CSS 的所有功能”塞到“ class 这一个 HTML 标签属性里,Tailwind 也不能。这样做只会让 HTML 结构越发臃肿。
@apply
针对上面提到的问题,Tailwind 允许我们在单个 CSS 文件中使用它们的类名:
.header { @apply bg-red-200 w-4 text-gray-400 rounded-sm border-2;}
复制代码
比如说项目中的按钮都是存在通用的圆角、内边距、字体等,这样我们就可以封装出这样一个类:
.btn { @apply p-8 rounded-xl font-semibold;}
复制代码
二、使用 Tailwind CSS 的理由
1、超小的文件尺寸 = 令人难以置信的性能
在开发模式下,Tailwind的输出尺寸非常大。这是设计使然:在此阶段生成每个可能的类,因此当你想要使用某些东西时,无需等待完成构建的过程。
但是,一旦Tailwind CSS进入生产模式,就会清除所有未与PurgeCSS工具一起使用的类。这是通过在项目文件中搜索类的名称来实现的,只保留那些使用过的。你可以在purge数组中的tailwind.config.js中配置将搜索哪些文件路径。
// tailwind.config.jsmodule.exports = { purge: [ "./src/**/*.html", "./src/**/*.vue", './src/**/*.js' ], theme: {}, variants: {}, plugins: [],}
复制代码
2、原型和快速构建
使用常规SCSS,需要为页面上的每个元素编写自定义类。这样虽然可以提供更好的控制,但编写自定义类需要花费大量时间:你必须在HTML中添加类,然后在CSS中创建,再以长格式写出每个属性。你必须等待CSS构建后才能看到结果——并且,如果你需要进行更多更改,则每次都需要重新构建,这可能会花费几秒钟时间并中断你的流程。
Tailwind CSS取消了这些额外的步骤,并在为元素设置样式时提供了简单、爽快的开发体验。可以看到想要设置样式的元素,使用简写方式添加需要的属性,不需要等待CSS文件束就能很快出现改变。因此只要专注于一个地方即可,不用频繁切换到不同的文件,整个过程感觉很流畅。
<div class="bg-white rounded p-4"> <h1 class="text-24 font-heading underline"> Foobar </h1> <p class="text-16 font-body> Hello world! </p></div>
复制代码
3、消除范围泄漏
人们喜欢BEM以及它能在今天如此流行的原因是,命名系统类的构建是为了表示组件的结构。在使其易于阅读和理解的同时,开发人员还受益于这种结构:由于布局易于理解,因而可以在不使用CSS选择器的情况下编写类。如下:
// this.block { &__element { ... } &__element--modifier { ... }}// not this.block { & > .element { &.modifier { ... } }}
复制代码
CSS选择器的问题在于它们给CSS带来了复杂性:组件变得非常依赖于特定的HTML结构。由于通用CSS类,例如.container,可以重复多次,所以使用这些名称可能会导致重叠,因此更改一个类将影响许多其他的类。这是我们使用BEM的主要原因之一,因为它使得结构清晰,并将每个类扁平化到顶级范围,这样就不会互相依赖。如果没有像这样的CSS方法,那么开发工作可能会让人头疼,并且其简单性意味着其他人可以更容易地理解它。
三、Tailwindcss 为何大受欢迎
NPM.DEVTOOL 中 tailwind 标签大全
地址:npm.devtool.tech/tailwindcss
现在项目开发用的 TailwindCSS,在这里谈一点感受,TailwindCSS 因为一个 class 代表一个 CSS 属性这种原子化 CSS (Atomic CSS),这种细粒度的 CSS 方案备受争议。
1、四种粒度
<div style="{ borderRadius: '0.5rem', padding: '1rem' }"> Click </div><div class="rounded-lg p-4"> Click </div><div class="button"> Click </div><Button> Click </Button>
复制代码
越往下封装的粒度就越大,越抽象,灵活性就越低,但是灵活性往往是和开发工作量成反比的,灵活性越高也就意味着更多的工作需要开发者自己去处理,如何平衡开发工作量与灵活度之间的关系就显得尤为重要。
因为这涉及到css库的选择,其中BootStrap库更多的是提供颗粒度3的形式,给定一个固定的样式,开发者需要自定义样式的话必须去重写样式,而tailwind则是提供颗粒度2形式的原子样式,更多的是提供一种规范,然后将更大的自由度交由开发者,由开发者来进行样式的组装。
2、一些问题的解答
Tailwindcss 为啥受欢迎,无非是更好用的原子化的 CSS。在国外如火如荼,但是在国内论坛上争议很大,前几天看的前端大佬博客上写了一篇关于 Tailwindcss 的文章,但是底下评论很多了各种问题,总结一下
Q1: tailwind的写法和行内 CSS 有何区别,不就少写几个字吗?
大部分人的想法应该是这样的: 仅仅对于 text-center 而言,虽然提供了些许方便,但是不足以拉开差距。
如果说它仅仅是简单的原子化 CSS,好用却不亮眼。但是它却不仅仅止于此。
1. 方便性: text-center、grid-cols-3
或许一个 text-center 不足以使你觉得提供了多大的方便性,但对于一个三等分的 Grid 属性来说,一个 grid-cols-3 和 shadow 绝对方便。
.grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr));}
复制代码
2. 语义化: text-lg、text-white、ring、animate-spin`
text-lg,一个较大字体,如果设置行内样式,肯定有诸多麻烦的事: 我想设计一个较大的字体,那我应该设计多大尺寸、使用什么单位。
同样还有:
text-white: 白色的色值是哪个来着?
ring: 我想给这个按钮加一个圈圈?
animate-spin: 怎么做一个动画?
3. 响应式:
先来看一个在工作中会遇到的响应式布局问题,这也是我上一次在头条面试时的一道题目
响应式布局,一大堆子元素,在大屏幕三等分,中等屏幕二等分,小屏幕一等分?
<div class="container"> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div> <div class="item"></div></div>
复制代码
通过 grid 布局很容易实现,但未免繁琐
@media (min-width: 1024px) { .container { grid-template-columns: repeat(3,minmax(0,1fr)); }}@media (min-width: 768px) { .container { grid-template-columns: repeat(2,minmax(0,1fr)); }}.conainer { display: grid; gap: 1rem;}
复制代码
那使用 tailwind 呢? 只要一行,就问你高效不高效。
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"></div>
复制代码
4. 修饰符
把修饰符,如各种伪类、暗黑模式、响应式设计至于前缀的设计简直深得我心。
<div class="focus:ring-2 hover:bg-red-700 dark:bg-gray-800"></div>
复制代码
Q2: 既然 TailwindCSS 这么好用,那岂不是可以摆脱手写 CSS 了
很遗憾,不能。不过虽然你无法摆脱手写 CSS,但是你基本上也写不了几行,说以下几种很常用的情况。
1. 复杂选择器
当父级元素鼠标悬浮时的,子级元素的样式控制
.container:hover .item {}
复制代码
2. CSS function
.body { height: calc(100vh - 6rem)}
复制代码
3. 多种属性复用
.item { @apply p-2 border-b flex justify-between font-mono;}
复制代码
Q3: 造成新的记忆负担
这个问题就仁者见仁智者见智了,在 Vue 的 template 语法中也经常出现此类问题,很多人会对一些命名上的约定,特别是自己不太喜欢的约定天然排斥,这也无可厚非。
在初期确实会一边开发网页,一边瞅着文档全局搜索: TailwindCSS 属性查找,现在借助浏览器插件及熟能生巧的经验已经不太需要翻文档了。
1. Tailwind CSS IntelliSense (vscode)
智能补全
代码提示
初期经常花时间翻文档而不手写 CSS,而其中的原因不外乎两个:
1、多写几个字母,确实有点嫌麻烦,有这时间还不如看看文档,全局搜索下也不费事;
2、自己设置一个 fontSize,padding、margin 实在不知道设置多少尺寸,tailwindcss 有较大的约束;
过了多久就会觉得: 嗯,真香。
四、Tailwindcss 项目实践
原本传统的写法是定义一个类,然后写上需要的样式:
.class1 { font-size: 18px; margin: 10px;}.class2 { font-size: 16px; color: red; margin: 10px;}
复制代码
这种写法是存在一部分样式重复的,换成 Atom CSS 就能减少一部分代码的冗余。
把 CSS 当成组件来写。大家乍一看 tailwindcss 官网肯定会觉得我在 HTML 里写个样式要敲那么多类不好吧。
<figure class="md:flex bg-gray-100 rounded-xl p-8 md:p-0"> <img class="w-32 h-32 md:w-48 md:h-auto md:rounded-none rounded-full mx-auto" src="/sarah-dayan.jpg" alt="" width="384" height="512"> <div class="pt-6 md:p-8 text-center md:text-left space-y-4"> <blockquote> <p class="text-lg font-semibold"> “Tailwind CSS is the only framework that I've seen scale on large teams. It’s easy to customize, adapts to any design, and the build size is tiny.” </p> </blockquote> <figcaption class="font-medium"> <div class="text-cyan-600"> Sarah Dayan </div> <div class="text-gray-500"> Staff Engineer, Algolia </div> </figcaption> </div></figure>
复制代码
其实我们是可以利用 Atom CSS 一次只干一件事的特性,将这些类随意组装成我们想要的类,这样就可以提供出来一个更上层的通用样式来复用。
tailwind.confing.js 配置文件
/** * 定制配置 * 默认配置请参考 https://unpkg.com/browse/[email protected]/stubs/defaultConfig.stub.js */module.exports = { purge: [ "./src/**/*.html", "./src/**/*.vue", './src/**/*.jsx' ], theme: { extend: { fontFamily: { sans: ["Inter", "Roboto", '"Segoe UI"'], dincond: ["DINCond-Black"] }, fontSize: { '2.5': '0.625rem', // 10px '3': '0.375rem', // 12px '5.5xl': '3.25rem', // 52px '4.5xl': '2.5rem', //40px }, width: { '4.5': '1.125rem', //18px '10.5': '2.65rem', //42px '15': '3.75rem', // 60px '18': '4.5rem', // 74px '18.5': '4.625rem', // 74px '23': '5.75rem' // 92px }, lineHeight: { '12': '3rem', // 48px '15': '3.875rem', // 62px '16': '4rem', //64px '14': '3.5rem', //56px "18" : "4.625rem" //74px }, padding: { '0.5': '0.125rem', // 2px '5.5': '1.375rem', // 22px '4.5': '1.125rem', //18px '0.75': '0.1875rem', //3px '7.5': '1.875rem' //30px }, paddingBottom:{ '4.5': '1.375rem' //22px }, margin: { '4.5': '1.125rem', //18px '15': '3.75rem', // 60px '21.25': '5.3125rem', // 85px '11.5': '2.875rem', // 46px '19': '4.75rem', //76px }, marginTop: { '6.5': '1.625rem', // 26px }, spacing: { '3.5': '0.875rem', // 14px '7.5': '1.875rem', //30px '9.5': '2.375rem', // 38px // '15': '3.375rem', // 54px '11.5': '2.875rem', // 46px '23': '5.75rem', // 92px '28': '7rem', // 112px '98': '39rem', // 624px }, height: { '0.25': '0.0625rem', //1px '0.75': '0.1875rem', // 3px '14': '3.5rem', // 56px '10.5': '2.65rem' //42px }, backgroundColor: { 'primary-a100': 'rgba(43, 121, 255, 0.1)', }, borderRadius: { '5.5': '1.375rem' }, //22px zIndex: { '6': 6 // z-index: 6 }, screens:{ '3xl': '1664px', '4xl': '1792px' }, scale: { '85': '.85', // 0.85rem } } }, plugins: [ require("tailwindcss-theming")({ variants: { light: true } }) ]};
复制代码
至此,我们已经了解了什么是 Tailwind CSS?如何使用 Tailwind CSS?Tailwind CSS 定制以及插件的使用,相信大家对Tailwind CSS已经有一个全面的认识。