tailwind 是一个流行的原子化 css 框架。本质上是一个工具集,包含了大量类似 flex、 pt-4、 text-center 以及 rotate-90 等工具类,可以组合使用并直接在 HTML 代码上实现任何 UI 设计。
下方法是Vite + Vue模式下的安装方法,其他脚手架与框架的使用同理。
// 创建项目
npm create vite app --template vue
// 安装必要依赖
npm i -D tailwindcss postcss autoprefixer
// 使用tailwindcss的初始化命令创建TailwindCSS配置文件
npx tailwindcss init -p
为了打包时TailwindCSS能生成对应的样式文件,需要在tailwind.config.js中正确配置content字段,如以下配置将扫描 src 目录下所有以 vue/js/ts/jsx/tsx 结尾的文件。
// tailwind.config.js
module.exports = {
content: [
'./src/**/*.{vue,js,ts,jsx,tsx}'
],
theme: {
extend: {},
},
plugins: [],
}
注意:TailwindCSS并不会生成一个全量的样式包,而是根据具体使用到的语法生成对应的样式代码,这样可以确保打包产生的样式包是最小的。
/* tailwind.css */
/* tailwind base 相当于一份重置样式表,包含了最基础的样式。 */
@tailwind base;
/* tailwind components 包含了一些组件类, 组件相当于复合样式 */
@tailwind components;
/* tailwind utilities 包含了工具类,也就是 flex mx-auto 这些内置样式 */
@tailwind utilities;
/*
这么划分的原因是因为 css 的优先级规则,tailwindcss 全部都是一级样式,在类名权重相等的情况,
下面的样式可以覆盖上面的样式,所以工具类优先,组件类次之,基础样式兜底,生成的样式顺序尤为重要,
所以 上面三句指令的顺序非必须建议不要修改。
*/
传统上,当我们需要在网络上设计某些内容时,都会编写 CSS。
// 传统方案
<script setup>
</script>
<template>
<div class="chat-notification">
<div class="chat-notification-logo-wrapper">
<svg class="h-12 w-12" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="a"><stop stop-color="#2397B3" offset="0%"></stop><stop stop-color="#13577E" offset="100%"></stop></linearGradient><linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="b"><stop stop-color="#73DFF2" offset="0%"></stop><stop stop-color="#47B1EB" offset="100%"></stop></linearGradient></defs><g fill="none" fill-rule="evenodd"><path d="M28.872 22.096c.084.622.128 1.258.128 1.904 0 7.732-6.268 14-14 14-2.176 0-4.236-.496-6.073-1.382l-6.022 2.007c-1.564.521-3.051-.966-2.53-2.53l2.007-6.022A13.944 13.944 0 0 1 1 24c0-7.331 5.635-13.346 12.81-13.95A9.967 9.967 0 0 0 13 14c0 5.523 4.477 10 10 10a9.955 9.955 0 0 0 5.872-1.904z" fill="url(#a)" transform="translate(1 1)"></path><path d="M35.618 20.073l2.007 6.022c.521 1.564-.966 3.051-2.53 2.53l-6.022-2.007A13.944 13.944 0 0 1 23 28c-7.732 0-14-6.268-14-14S15.268 0 23 0s14 6.268 14 14c0 2.176-.496 4.236-1.382 6.073z" fill="url(#b)" transform="translate(1 1)"></path><path d="M18 17a2 2 0 1 0 0-4 2 2 0 0 0 0 4zM24 17a2 2 0 1 0 0-4 2 2 0 0 0 0 4zM30 17a2 2 0 1 0 0-4 2 2 0 0 0 0 4z" fill="#FFF"></path></g></svg>
</div>
<div class="chat-notification-content">
<h4 class="chat-notification-title">ChitChat</h4>
<p class="chat-notification-message">You have a new message!</p>
</div>
</div>
</template>
<style>
.chat-notification {
display: flex;
max-width: 24rem;
margin: 0 auto;
padding: 1.5rem;
border-radius: 0.5rem;
background-color: #fff;
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
}
.chat-notification-logo-wrapper {
flex-shrink: 0;
}
.chat-notification-logo {
height: 3rem;
width: 3rem;
}
.chat-notification-content {
margin-left: 1.5rem;
padding-top: 0.25rem;
}
.chat-notification-title {
color: #1a202c;
font-size: 1.25rem;
line-height: 1.25;
}
.chat-notification-message {
color: #718096;
font-size: 1rem;
line-height: 1.5;
}
</style>
使用 Tailwind,您可以通过直接在 HTML 中应用预先存在的类来设置元素样式。
// Tailwind方案
<script setup></script>
<template>
<div class="p-6 max-w-sm mx-auto bg-white rounded-xl shadow-lg flex items-center space-x-4">
<div class="shrink-0">
<svg class="h-12 w-12" viewBox="0 0 40 40" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="a"><stop stop-color="#2397B3" offset="0%"></stop><stop stop-color="#13577E" offset="100%"></stop></linearGradient><linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="b"><stop stop-color="#73DFF2" offset="0%"></stop><stop stop-color="#47B1EB" offset="100%"></stop></linearGradient></defs><g fill="none" fill-rule="evenodd"><path d="M28.872 22.096c.084.622.128 1.258.128 1.904 0 7.732-6.268 14-14 14-2.176 0-4.236-.496-6.073-1.382l-6.022 2.007c-1.564.521-3.051-.966-2.53-2.53l2.007-6.022A13.944 13.944 0 0 1 1 24c0-7.331 5.635-13.346 12.81-13.95A9.967 9.967 0 0 0 13 14c0 5.523 4.477 10 10 10a9.955 9.955 0 0 0 5.872-1.904z" fill="url(#a)" transform="translate(1 1)"></path><path d="M35.618 20.073l2.007 6.022c.521 1.564-.966 3.051-2.53 2.53l-6.022-2.007A13.944 13.944 0 0 1 23 28c-7.732 0-14-6.268-14-14S15.268 0 23 0s14 6.268 14 14c0 2.176-.496 4.236-1.382 6.073z" fill="url(#b)" transform="translate(1 1)"></path><path d="M18 17a2 2 0 1 0 0-4 2 2 0 0 0 0 4zM24 17a2 2 0 1 0 0-4 2 2 0 0 0 0 4zM30 17a2 2 0 1 0 0-4 2 2 0 0 0 0 4z" fill="#FFF"></path></g></svg>
</div>
<div>
<div class="text-xl font-medium text-black">ChitChat</div>
<p class="text-slate-500">You have a new message!</p>
</div>
</div>
</template>
<style></style>
在上面的例子中,使用了
能够实现完全自定义的组件设计,而无需编写一行自定义 CSS。
TailwindCSS语法检索技巧 TailwindCSS的基本原则是将每一个style语法转换为一个class,因此,在官网检索想要的样式class时,按照样式的语法来检索是效率最高的。如想要获取圆角的语法,只需要搜索Border Radius即可
<template>
<div class="text-base p-1 border border-black border-solid"></div>
</template>
<style>
.text-base {
font-size: 16px;
}
.p-1 {
padding: 4px;
}
.border {
border-width: 1px;
}
.border-black {
border-color: black;
}
.border-solid {
border-style: solid;
}
</style>
<script setup>
import { reactive } from 'vue';
const data = reactive({
list: [
{
name: '克里斯汀·拉莫斯',
email: 'kristen.ramos@example.com',
imageUrl: 'https://images.unsplash.com/photo-1550525811-e5869dd03032?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80'
},
{
name: '弗洛伊德·迈尔斯',
email: 'kristen.ramos@example.com',
imageUrl: 'https://images.unsplash.com/photo-1550525811-e5869dd03032?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80'
},
{
name: '考特尼·亨利',
email: 'kristen.ramos@example.com',
imageUrl: 'https://images.unsplash.com/photo-1550525811-e5869dd03032?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80'
},
{
name: '特德·福克斯',
email: 'kristen.ramos@example.com',
imageUrl: 'https://images.unsplash.com/photo-1550525811-e5869dd03032?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80'
},
],
});
</script>
<template>
<!--
hover:
active:
focus:ring(带有盒子阴影的轮廓环)
-->
<button class="bg-violet-500 hover:bg-violet-600 active:bg-violet-700 focus:outline-none focus:ring focus:ring-violet-300">保存</button>
<!-- 第一个、最后一个、奇数和偶数 -->
<div class="max-w-md mx-auto bg-white shadow my-8">
<ul role="list" class="p-6 divide-y divide-slate-200">
<li class="flex py-4 first:pt-0 last:pb-0 odd:bg-white even:bg-slate-50" v-for="(item, index) in data.list" :key="index">
<img referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" class="h-10 w-10 rounded-full" :src="item.imageUrl" alt="" />
<div class="ml-3 overflow-hidden">
<p class="text-sm font-medium text-slate-900">{{item.name}}</p>
<p class="text-sm text-slate-500 truncate">{{item.email}}</p>
</div>
</li>
</ul>
</div>
</template>
```
### 响应式设计
Tailwind 中的每个实用程序类都可以在不同的断点处有条件地应用,这使得构建复杂的响应式界面变得轻而易举,而无需离开 HTML。
受常见设备分辨率的启发,默认有五个断点:

```html
<div class="max-w-md mx-auto bg-white rounded-xl shadow-md overflow-hidden md:max-w-2xl">
<div class="md:flex">
<div class="md:shrink-0">
<img referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" class="h-48 w-full object-cover md:h-full md:w-48" src="/img/building.jpg" alt="Modern building architecture">
</div>
<div class="p-8">
<div class="uppercase tracking-wide text-sm text-indigo-500 font-semibold">Company retreats</div>
<a href="#" class="block mt-1 text-lg leading-tight font-medium text-black hover:underline">Incredible accommodation for your team</a>
<p class="mt-2 text-slate-500">Looking to take your team away on a retreat to enjoy awesome food and take in some sunshine? We have a list of places to do just that.</p>
</div>
</div>
</div>
比如要实现一个媒体查询,根据不同的屏幕宽度实现不同的图片宽度。
按照之前的写法,可能得这么干
@media only screen and (max-width:1280px) {
.img {
width:196px;
}
}
@media only screen and (max-width: 760px) {
.img {
width:128px;
}
}
// tailwind方案
<img referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" class="w-16 md:w-32 lg:w-48" src="...">
Tailwind 提供了一个dark变体,可在启用暗模式时以不同的方式设计网站
<div class="bg-white dark:bg-slate-800 rounded-lg px-6 py-8 ring-1 ring-slate-900/5 shadow-xl">
<div>
<span class="inline-flex items-center justify-center p-2 bg-indigo-500 rounded-md shadow-lg">
<svg class="h-6 w-6 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true"><!-- ... --></svg>
</span>
</div>
<h3 class="text-slate-900 dark:text-white mt-5 text-base font-medium tracking-tight">Writes Upside-Down</h3>
<p class="text-slate-500 dark:text-slate-400 mt-2 text-sm">
The Zero Gravity Pen can be used to write in any orientation, including upside-down. It even works in outer space.
</p>
</div>
<div>
<div class="mt-3 flex -space-x-2 overflow-hidden">
<img referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" class="inline-block h-12 w-12 rounded-full ring-2 ring-white" src="https://images.unsplash.com/photo-1491528323818-fdd1faba62cc?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt=""/>
<img referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" class="inline-block h-12 w-12 rounded-full ring-2 ring-white" src="https://images.unsplash.com/photo-1550525811-e5869dd03032?ixlib=rb-1.2.1&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt=""/>
<img referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" class="inline-block h-12 w-12 rounded-full ring-2 ring-white" src="https://images.unsplash.com/photo-1500648767791-00dcc994a43e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2.25&w=256&h=256&q=80" alt=""/>
<img referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" class="inline-block h-12 w-12 rounded-full ring-2 ring-white" src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt=""/>
<img referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" class="inline-block h-12 w-12 rounded-full ring-2 ring-white" src="https://images.unsplash.com/photo-1517365830460-955ce3ccd263?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt=""/>
</div>
</div>
每个头像的程序类重复了5次
<script setup></script>
<template>
<div>
<div class="mt-3 flex -space-x-2 overflow-hidden">
<img referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" class="avator" src="https://images.unsplash.com/photo-1491528323818-fdd1faba62cc?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt=""/>
<img referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" class="avator" src="https://images.unsplash.com/photo-1550525811-e5869dd03032?ixlib=rb-1.2.1&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt=""/>
<img referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" class="avator" src="https://images.unsplash.com/photo-1500648767791-00dcc994a43e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2.25&w=256&h=256&q=80" alt=""/>
<img referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" class="avator" src="https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt=""/>
<img referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" referrerPolicy="no-referrer" class="avator" src="https://images.unsplash.com/photo-1517365830460-955ce3ccd263?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80" alt=""/>
</div>
</div>
</template>
<style scoped>
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
.avator-primary {
@apply inline-block h-12 w-12 rounded-full ring-2 ring-white;
}
}
</style>
使用@tailwind指令可以向css添加tailwind的base、component、utilities样式
/**
* This injects Tailwind's base styles and any base styles registered by
* plugins.
*/
@tailwind base;
/**
* This injects Tailwind's component classes and any component classes
* registered by plugins.
*/
@tailwind components;
/**
* This injects Tailwind's utility classes and any utility classes registered
* by plugins.
*/
@tailwind utilities;
使用 @apply 将任何现存的功能类内联到自定义 CSS 中。如上面重复样式的例子所用的方式。
使用 @layer 指令告诉 Tailwind 一组自定义样式应该属于哪个 “bucket”。可用的层有 base, components 和 utilities。
@tailwind base;
@tailwind components;
@tailwind utilities;
/*
如果想为特定 HTML 元素添加自己的默认基本样式,使用指令@layer将这些样式添加到 Tailwind
的base图层中
*/
@layer base {
h1 {
@apply text-2xl;
}
h2 {
@apply text-xl;
}
}
/*
component更适合用于复杂的、需要在多个地方重复使用的样式
*/
@layer components {
.btn-blue {
@apply bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded;
}
}
/*
utilities更适合用于快速创建简单的、仅在特定场景使用的样式。
*/
@layer utilities {
@variants hover, focus {
.filter-none {
filter: none;
}
.filter-grayscale {
filter: grayscale(100%);
}
}
}
@screen 指令允许创建通过名称引用断点的媒体查询,而不是在 CSS 中复制他们的值。
/* 假设有一个名为 sm 的 640px 的断点,只需要写一些自定义的指向这个断点的 CSS。 */
/* 而不是编写一个复制那些值的原始的媒体查询,如下所示: */
@media (min-width: 640px) {
/* ... */
}
@screen sm {
/* ... */
}
screen 函数接受像 md 这样的屏幕名称并生成相应的媒体特征表达式:
/* Input */
@media screen(sm) {
/* ... */
}
/* Output */
@media (min-width: 640px) {
/* ... */
}
使用 theme() 函数可以通过点符号来获取 Tailwind 配置的值。 当想要引用一个主题配置中的一部分声明的值时
@tailwind utilities;
@layer utilities {
.div {
border: 1px solid theme('colors.cyan');
}
}
tailwind.config.js配置任何自定义项:内容、主题、屏幕、颜色、间距、插件、预设
// tailwind.config.js
module.exports = {
// 内容
content: ['./src/**/*.{html,js}'],
// 主题
theme: {
// 屏幕
screens: {
sm: '480px',
md: '768px',
lg: '976px',
xl: '1440px',
},
// 颜色
colors: {
'blue': '#1fb6ff',
'purple': '#7e5bef',
'pink': '#ff49db',
'orange': '#ff7849',
'green': '#13ce66',
'yellow': '#ffc82c',
'gray-dark': '#273444',
'gray': '#8492a6',
'gray-light': '#d3dce6',
},
// 间距
spacing: {
'1': '8px',
'2': '12px',
'3': '16px',
'4': '24px',
'5': '32px',
'6': '48px',
},
fontFamily: {
sans: ['Graphik', 'sans-serif'],
serif: ['Merriweather', 'serif'],
},
extend: {
// 扩展默认间距比例
spacing: {
'13': '3.25rem',
'15': '3.75rem',
'128': '32rem',
'144': '36rem',
},
borderRadius: {
'4xl': '2rem',
}
}
},
/*
使用可重用的第三方插件扩展 Tailwind。插件允许为 Tailwind 注册新样式
*/
plugins: [
require('@tailwindcss/line-clamp'),
],
}
从TaiWindCss实践的使用场景上来看,我们以 PostCSS 插件的形式安装TaiWindCss,本质上讲TaiWindCss是一个postCss的插件。 对于PostCSS的插件使用,我们在使用的过程中一般都需要如下步骤:
// `postcss-import`:用于处理 PostCSS 的规范插件
npm install postcss-import
// postcss.config.js
// 然后把它作为 PostCSS 配置中的第一个插件:
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
通俗的讲法:postCss 就是一个开发工具,是一个用 JavaScript 工具和插件转换 CSS 代码的工具。支持变量,混入,未来 CSS 语法,内联图像等等。
PostCSS 包括 CSS 解析器,CSS 节点树 API,一个源映射生成器和一个节点树 stringifier。
PostCSS 主要的原理核心工作流:
在PostCSS中有几个关键的处理机制:(详细看postcss文档)
Source string → Tokenizer(分词器) → Parser(解析器) → AST → Processor (处理器)→ Stringifier(弦化器)->new css
基本的步骤:
tailwindcss 大多作为 postcss plugin 来使用的,它源码里自己实现了一个文件读取机制(也就是 tailwind.config.js 中的 content 配置项 ),来对我们编写的代码进行提取。
// 转换前
@layer components{
@variants responsive{
.container{
width: 100%
}
}
}
// 转换后
{
"raws": {
"semicolon": false,
"after": "\\n\\n"
},
"type": "root",
"nodes": [
{
"raws": {
"before": "",
"between": "",
"afterName": " ",
"semicolon": false,
"after": "\\n"
},
"type": "atrule",
"name": "layer",
"source": {
"start": {
"line": 1,
"column": 1
},
"input": {
"css": "@layer components{\\n @variants responsive{\\n .container{\\n width: 100%\\n }\\n }\\n}\\n\\n",
"hasBOM": false,
"id": "<input css 17>"
},
"end": {
"line": 7,
"column": 1
}
},
"params": "components",
"nodes": [
{
"raws": {
"before": "\\n ",
"between": "",
"afterName": " ",
"semicolon": false,
"after": "\\n "
},
"type": "atrule",
"name": "variants",
"source": {
"start": {
"line": 2,
"column": 3
},
"input": {
"css": "@layer components{\\n @variants responsive{\\n .container{\\n width: 100%\\n }\\n }\\n}\\n\\n",
"hasBOM": false,
"id": "<input css 17>"
},
"end": {
"line": 6,
"column": 3
}
},
"params": "responsive",
"nodes": [
{
"raws": {
"before": "\\n ",
"between": "",
"semicolon": false,
"after": "\\n "
},
"type": "rule",
"nodes": [
{
"raws": {
"before": "\\n ",
"between": ": "
},
"type": "decl",
"source": {
"start": {
"line": 4,
"column": 7
},
"input": {
"css": "@layer components{\\n @variants responsive{\\n .container{\\n width: 100%\\n }\\n }\\n}\\n\\n",
"hasBOM": false,
"id": "<input css 17>"
},
"end": {
"line": 4,
"column": 17
}
},
"prop": "width",
"value": "100%"
}
],
"source": {
"start": {
"line": 3,
"column": 5
},
"input": {
"css": "@layer components{\\n @variants responsive{\\n .container{\\n width: 100%\\n }\\n }\\n}\\n\\n",
"hasBOM": false,
"id": "<input css 17>"
},
"end": {
"line": 5,
"column": 5
}
},
"selector": ".container"
}
]
}
]
}
],
"source": {
"input": {
"css": "@layer components{\\n @variants responsive{\\n .container{\\n width: 100%\\n }\\n }\\n}\\n\\n",
"hasBOM": false,
"id": "<input css 17>"
},
"start": {
"line": 1,
"column": 1
}
}
}
许多人会想到 CSS 框架,有很多,例如 Bootstrap、Bulma 和 Material UI。Bootstrap 和 Bulma 等框架利用预先准备好的组件(例如按钮、菜单和面包屑)进行设计。在 Tailwind CSS 中,没有准备任何组件,而是使用Utilize Class来创建和设计自己的组件。 原来Bootstrap等框架可以通过提前准备组件集合来高效地设计网站,但是有一个缺点,就是因为使用了相同的设计,所以没有原创性。相比之下,Tailwind CSS 没有组件集合,所以即使你创建一个名为相同按钮的组件,每个人都会应用不同的Utilize Class创建它,可以创建出一个高度原创的网站。
两者都有优点和缺点,所以使用哪一个取决于个人,但使用 Tailwind CSS 的人数正在稳步增加
例如,如果要使用 Bootstrap 创建按钮,请将class设置为btn 。但是,在 Tailwind 中,并没有 btn 等用于创建按钮的class,你可以通过编写如下所示的Utilize Class来创建按钮。你可能会觉得要设置的类太多了,但是学习成本很低,因为你一用就习惯了。如果不知道类名,可以通过搜索 Tailwind CSS 文档轻松找到它
<button class="bg-indigo-700 font-semibold text-white py-2 px-4 rounded">Utilize Class</button>
<!--
bg-indigo-700 设置颜色,
font-semibold 设置字体粗细,
text-white 设置文本颜色,
py-2 设置左右填充,
px 设置上下填充,
rounded 设置圆角。
-->
demo说明:tailwindcss/test
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="/dist/output.css">
</head>
<body>
<div>
<h1 class="flex text-3xl font-bold underline text-blue-600">
Hello world!
</h1>
</div>
</body>
</html>
在demo中,我只是用了flex text-3xl font-bold underline text-blue-600,这几个类名,打包之后发现,css文件当中除了基础样式,就只有这几个类对应样式:其实我们在搭建tailwind的项目过程中就可以发现,tailwind存在于JIT引擎(Just-In-Time),就是在编译过程才去扫描我们的html文件,在这个过程中去识别使用了哪些类名,然后才生成对应的样式。
相比于预先直接全局写好大量的类名,JIT机制的优点在于精简紧凑,样式所占用的空间较小,因为用到了才会生成。
// 启用JIT模式
/** @type {import('tailwindcss').Config} */
module.exports = {
mode: 'JIT',
/**
* 由于 JIT 模式通过扫描模板文件按需生成 CSS,因此在 tailwind.config.js
* 文件中使用所有模板路径配置 purge 选项至关重要
* 启动开发服务器或构建运行器时,Tailwind 将按需生成您的样式,而不是预先生成所有内容。
*/
purge: [
"public/**/*.html",
"src/pages/**/*.{js,jsx,ts,tsx,vue}"
],
theme: {
extend: {},
},
plugins: [],
}
// 注释掉 @tailwind base 样式
// tailwind.css
/* @tailwind base;
@tailwind components;
@tailwind utilities; */
// 关闭默认样式
// tailwind.config.js
...
export const corePlugins = {
preflight: false
}
...
下载preflight.css,手动导入,解决冲突。
为啥这个 css 框架叫 tailwind 呢?
因为作者 Adam Wathan喜欢叫做 kiteboarding 风筝冲浪的运动。
就是这样的,一个风筝,一个冲浪板:这种运动在顺风 tailwind 和逆风 headwind 下有不同的技巧。而 tailwind 的时候明显更加省力。
所以就给这个 css 框架起名叫 tailwind 了,借用其省力的意思。
贺燕珍: