likes
comments
collection
share

Tailwind css 实践指南

作者站长头像
站长
· 阅读数 11

问题

前端开发过程中写CSS通常是一件很头疼的事情,大家都不愿意去写,有的公司甚至专门招实习生过来替自己写CSS,为什么大家都讨厌或者说不愿意去写CSS呢?主要有一下几个原因

  1. 写CSS费事费力,而且还没有技术上的提升
  • 上下文切换太麻烦,通常CSS是一个文件,我们给标签写类名的时候通常又是另一个文件,文件的来回切换很麻烦;或者当我们在Vue的style里面写CSS的时候,只要文件有点规模,上下文的切换也会显得很麻烦,体验非常糟糕
  • 写CSS通常是一件重复性的工作,有大量的重复性的代码,给人的感觉就是忙了一天又好像什么也没干,花费了大量的时间而且没有技术上的提升
  1. 需要自己想好合适的类名,类名不能太随便不能过长不能......

tailwindcss为解决这些问题带来了福音

我们首先来看个案例:

我们平时写 css :

<template>
<div class="text">我是一个div</div>
</template>
......
<style>
.text{
  	font-size: 16px;
    border: 1px solid #000;
    padding: 4px;
}
</style>
<template>
<div class="text">我是一个div</div>
</template>
......
<style>
.text{
  	font-size: 16px;
    border: 1px solid #000;
    padding: 4px;
}
</style>

使用tailwindcss:

<div className="text-base p-1 border border-black border-solid"></div><div className="text-base p-1 border border-black border-solid"></div>

就这一行就足够了,解释一下里面类名代表着什么:

.text-base {
    font-size: 16px;
}
.p-1 {
    padding: 4px;
}
.border {
    border-width: 1px;
}
.border-black {
    border-color: black;
}
.border-solid {
    border-style: solid;
}
.text-base {
    font-size: 16px;
}
.p-1 {
    padding: 4px;
}
.border {
    border-width: 1px;
}
.border-black {
    border-color: black;
}
.border-solid {
    border-style: solid;
}

这些CSS class不需要我们自己去写,这些都是tailwindcss给我们的,我们只需要在className里面写相应的类名就足够了,这就是原子化CSS带给我们的便利。

下面来讲一讲tailwindcss的优点、安装以及我在给一个React+Vite+Less的项目引入tailwindcss时遇到的问题

新世纪福音--tailwindcss

我们先来了解一下它自身的一些特点再来看看它的一些高级玩法吧

  1. tailwindcss给我们这么多可用的CSS类,那打包的时候不是会造成CSS文件更大吗?

在v2版本的时候,确实是这样的,在v2版本的时候我们通常要在配置中配置如下选项来避免这种情况的发生:

// tailwind.config.js
module.exports = {
  purge: [
    './src/**/*.html',
    './src/**/*.vue',
    './src/**/*.jsx',
  ],
  theme: {},
  variants: {},
  plugins: [],
}// tailwind.config.js
module.exports = {
  purge: [
    './src/**/*.html',
    './src/**/*.vue',
    './src/**/*.jsx',
  ],
  theme: {},
  variants: {},
  plugins: [],
}

在生产环境下会默认匹配这些文件并进行tree sharking,如果想要手动开启删除未使用的CSS功能的话,可以如下配置:

// tailwind.config.js
module.exports = {
  purge: {
    enabled: true,
    content: ['./src/**/*.html'],
  },
  // ...
}// tailwind.config.js
module.exports = {
  purge: {
    enabled: true,
    content: ['./src/**/*.html'],
  },
  // ...
}

在为生产而构建时,应始终使用 Tailwind purge 的选项来tree sharking未使用的样式并优化最终构建大小。当使用Tailwind删除未使用的样式时,很难得到超过10kb的压缩CSS。

它底层使用PurgeCSS在HTML中查找类。它不会尝试解析你的 HTML 并查找类属性或动态执行你的 JavaScript — 它只是在整个文件中查找与此正则表达式匹配的任何字符串:

/[^<>"'`\s]*[^<>"'`\s:]/g/[^<>"'`\s]*[^<>"'`\s:]/g

这意味着避免使用字符串串联在模板中动态创建类字符串非常重要,否则 PurgeCSS 将不知道保留这些类。例如:

错误写法:

<div class="text-{{  error  ?  'red'  :  'green'  }}-600"></div><div class="text-{{  error  ?  'red'  :  'green'  }}-600"></div>

正确写法:

<div class="{{  error  ?  'text-red-600'  :  'text-green-600'  }}"></div><div class="{{  error  ?  'text-red-600'  :  'text-green-600'  }}"></div>

v2版本的tailwindcss还有很多需要优化的点,这里就不过多一一介绍了,具体请查看文档:tailwindcss

在v3版本的tailwindcss已经不需要处理这些问题了。

v3版本已经按需处理了这些CSS类,只有在程序中用到的样式才会包含在编译后的CSS中,官网原话:

Removing unused custom CSS

Any custom styles you add to the base, components, or utilities layers will only be included in your compiled CSS if those styles are actually used in your HTML.

翻译过来就是:

添加到 basecomponentsutilities 图层的任何自定义样式只有在 HTML 中实际使用这些样式时才会包含在编译的 CSS 中。

如果要添加一些应始终包含的自定义 CSS,请将其添加到样式表中而不使用 @layer 指令,如:

@tailwind base;
@tailwind components;

/* This will always be included in your compiled CSS */
.card {
  /* ... */
}

@tailwind utilities;@tailwind base;
@tailwind components;

/* This will always be included in your compiled CSS */
.card {
  /* ... */
}

@tailwind utilities;

可见v3着重在性能方面下了很大的手笔,现在已经不需要自己去自定义配置去做"删除未使用的CSS"这部分工作了,官方已经给我们做了

高级玩法与疑问解答

1. 你可能会比较疑惑,这些CSS classes是从哪里来的呢?

实际上我们写的这些tailwindcss指令就是给我们带来这些classes的关键:

@tailwind base;
@tailwind components;
@tailwind utilities;@tailwind base;
@tailwind components;
@tailwind utilities;

为什么这简简单单的三行指令就能给我们带来那么多的css classes呢?这得益于tailwindcss的即时编译模式(JIT)

JIT模式是Tailwind CSS 2.x系列中引入的一项功能,它可以在构建时动态地生成仅包含项目中实际使用的样式,从而大大减小生成的 CSS 文件的大小。

指令是在你的HTML或CSS中使用的特殊注释,用于告诉Tailwind CSS的JIT编译器生成相应的样式。通过使用指令,你可以引用特定的Tailwind CSS类,而无需在HTML或CSS中实际使用它们。

使用JIT模式和指令可以帮助你更好地控制生成的样式,并减小最终的CSS文件大小。这对于大型项目和性能敏感的应用程序特别有用。

2. 它给了这么多的类名,我哪能记住这么多啊?

这个问题可以通过VS code插件来解决,推荐VS code插件:

Tailwind css 实践指南

该插件会在你写className时给你提示,并且你写完类名后可以吧鼠标悬浮在类名上面就能看到该类名具体代表的样式

3. 这么多类名,那它会不会变得难以调试呢?

答案是不会的,反而用浏览器调试的时候会更加清晰,因为每个类名都担任这特定的角色:

Tailwind css 实践指南

4. 类名太长了而且重复多次怎么办

可以通过tailwindcss的指令来解决,通过@layer @apply 指令来扩展类名:

Tailwind css 实践指南

像这样,以后 .btn-primary 这一个类名就包括了@apply后面这些了

同时,如果想要跨项目复用,可以将其开发为一个插件:

const plugin = require('tailwindcss/plugin');

module.exports = plugin(function({ addUtilities }) {
    addUtilities({
        '.colorAbout': {
            background: 'blue',
            color: 'red'
        },
        '.textAbout': {
            'font-size': '20px'
        }
    })
})
const plugin = require('tailwindcss/plugin');

module.exports = plugin(function({ addUtilities }) {
    addUtilities({
        '.colorAbout': {
            background: 'blue',
            color: 'red'
        },
        '.textAbout': {
            'font-size': '20px'
        }
    })
})

之后在tailwindcss.config.ts里面的plugin里引入就行了

5. 我在已有项目中引入tailwindcss,那我的类名和它的类名冲突了怎么办?

这个tailwindcss已有解决方案,可以通过添加一个前缀来解决:

Tailwind css 实践指南

不过之后写class的时候都需要加上这个前缀,例如本来是‘border’,现在要写成‘ho-border’

相关链接:tailwindcss.com/docs/config…

看法

tailwindcss之所以现在这么火是除了上面说到的几个点之外,还因为

  • 它复用和组合的颗粒度更小,同一个样式可以被复用很多次,复用率极高,可以大大减少CSS的大小,具有极低的代码冗余率
  • 对于需要多端适配的场景,Tailwind提供了一些内置的锚点,也可以自己定义,为这些场景编写特定样式只需在样式前面加上该锚点和冒号就可以实现特定场景下的样式生效,(例如:
<div class="text-center sm:text-left"></div><div class="text-center sm:text-left"></div>

  • 开箱什么组件和样式库都没有提供,一切都需要自己 DIY:你需要自行去为每个页面元素设计样式,然后组合使用 Tailwind 提供的工具集 class(每个 class 通常只负责设置单个属性,而不是像 Bootstrap 那样包含一堆属性)达到最终的渲染效果。
  • Tailwind 的优点正好弥补了 Bootstrap 的不足:对于一些长期维护的、面向用户的、需要有定制样式风格的项目,你不需要去加载和覆盖框架内置的样式属性,就可以轻松设计定制出自己独特风格的样式代码,从而很好地与自有系统相配合

Tailwind看起来很棒,但也并不是适合所有场景的,像如果做通用型组件库,写组件给别人用的话就不太合适了,因为使用者可能还有一些定制化需求,要根据class来调整样式;Tailwind需要编译,并且支持不同的编译配置,很难要求使用方和自己的配置一样