cover_image

带你探索Tailwind Css

58本地服务终端 58本地服务终端技术
2023年07月18日 01:00

1.介绍

tailwind 是一个流行的原子化 css 框架。本质上是一个工具集,包含了大量类似 flex、 pt-4、 text-center 以及 rotate-90 等工具类,可以组合使用并直接在 HTML 代码上实现任何 UI 设计。

2、安装

下方法是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的基本指令

/* tailwind.css */
/* tailwind base 相当于一份重置样式表,包含了最基础的样式。 */
@tailwind base;
/* tailwind components 包含了一些组件类, 组件相当于复合样式 */
@tailwind components;
/* tailwind utilities 包含了工具类,也就是 flex mx-auto 这些内置样式 */
@tailwind utilities;


/*
这么划分的原因是因为 css 的优先级规则,tailwindcss 全部都是一级样式,在类名权重相等的情况,
下面的样式可以覆盖上面的样式,所以工具类优先,组件类次之,基础样式兜底,生成的样式顺序尤为重要,
所以 上面三句指令的顺序非必须建议不要修改。
*/



3、应用

传统上,当我们需要在网络上设计某些内容时,都会编写 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>

在上面的例子中,使用了

  • Tailwind 的Flexbox和填充实用程序(flex、shrink-0和p-6)控制整体卡片布局
  • 最大宽度和边距实用程序 (max-w-sm和mx-auto) 限制卡片宽度并将其水平居中
  • 设置卡片外观样式的背景颜色、边框半径和框阴影实用程序用(bg-white、rounded-xl和shadow-lg)
  • 图像宽度和高度实用程序用 (w-12和h-12)
  • space-Between实用程序 (space-x-4) 处理图像和文本之间的间距
  • 设置卡片文本样式的字体大小、文本颜色和字体粗细实用程序(text-xl、text-black、font-medium)

能够实现完全自定义的组件设计,而无需编写一行自定义 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>
图片
image.png

悬停、焦点还有其他状态

<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。

受常见设备分辨率的启发,默认有五个断点:
![image.png](https://wos.58cdn.com.cn/IjGfEdCbIlr/ishare/712be3f2-ba8e-4030-88b4-8d2d6ec4496cimage.png)

```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

使用@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

使用 @apply 将任何现存的功能类内联到自定义 CSS 中。如上面重复样式的例子所用的方式。

@layer

使用 @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

@screen 指令允许创建通过名称引用断点的媒体查询,而不是在 CSS 中复制他们的值。

/* 假设有一个名为 sm 的 640px 的断点,只需要写一些自定义的指向这个断点的 CSS。 */
/* 而不是编写一个复制那些值的原始的媒体查询,如下所示: */
@media (min-width: 640px) {
/* ... */
}

@screen sm {
/* ... */
}


screen()

screen 函数接受像 md 这样的屏幕名称并生成相应的媒体特征表达式:

/* Input */
@media screen(sm) {
/* ... */
}

/* Output */
@media (min-width: 640px) {
/* ... */
}

theme()

使用 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'),
],
}

4、原理

从TaiWindCss实践的使用场景上来看,我们以 PostCSS 插件的形式安装TaiWindCss,本质上讲TaiWindCss是一个postCss的插件。 对于PostCSS的插件使用,我们在使用的过程中一般都需要如下步骤:

  • PostCSS 配置文件 postcss.config.js,新增 tailwindcss 插件。
  • TaiWindCss插件需要一份配置文件,比如:tailwind.config.js。
  • 项目 引入的 less,sass,css 文件中注入 @tailwind 标识,并引入 base,components,utilities,是否全部引入取决你自己。

使用postcss做处理器

// `postcss-import`:用于处理 PostCSS 的规范插件
npm install postcss-import


// postcss.config.js
// 然后把它作为 PostCSS 配置中的第一个插件:
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

了解什么是postcss

通俗的讲法:postCss 就是一个开发工具,是一个用 JavaScript 工具和插件转换 CSS 代码的工具。支持变量,混入,未来 CSS 语法,内联图像等等。

特性与常见的功能:
  • 增强代码的可读性:
  • 将未来的 CSS 特性带到今天
  • 避免 CSS 代码中的错误
  • 可以作为预处理器使用
postCss的核心原理/工作流

PostCSS 包括 CSS 解析器,CSS 节点树 API,一个源映射生成器和一个节点树 stringifier。

PostCSS 主要的原理核心工作流:

  • 通过 fs 读取CSS文件
  • 通过 parser 将CSS解析成抽象语法树(AST树)
  • 将AST树”传递”给任意数量的插件处理
  • 诸多插件进行数据处理。插件间传递的数据就是AST树
  • 通过 stringifier 将处理完毕的AST树重新转换成字符串
图片
image.png
  • 将CSS解析成抽象语法树(AST树)
  • 将AST树”传递”给任意数量的插件处理
  • 将处理完毕的AST树重新转换成字符串

在PostCSS中有几个关键的处理机制:(详细看postcss文档)

Source string → Tokenizer(分词器) → Parser(解析器) → AST → Processor (处理器)→ Stringifier(弦化器)->new css

tailwindcss工作流
图片
image.png

基本的步骤:

  • 将CSS解析成抽象语法树(AST树)
  • 读取插件配置,根据配置文件,生成新的抽象语法树
  • 将AST树”传递”给一系列数据转换操作处理(变量数据循环生成,切套类名循环等)
  • 清除一系列操作留下的数据痕迹
  • 将处理完毕的AST树重新转换成字符串

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
}
}
}

图片
image.png

5、问题

问题1、为什么不直接使用内联样式呢?

  • 有约束的设计。使用内联样式,每个值都是一个神奇的数字。使用实用程序,可以从预定义的设计系统中选择样式,这使得构建视觉上一致的 UI 变得更加容易。
  • 响应式设计。不能在内联样式中使用媒体查询,但可以使用 Tailwind 的响应式实用程序轻松构建完全响应式界面。
  • 悬停、焦点等状态。内联样式无法针对悬停或焦点等状态,但 Tailwind 的状态变体可以轻松地使用实用程序类来设置这些状态的样式

问题2、与bootstrap的区别

许多人会想到 CSS 框架,有很多,例如 Bootstrap、Bulma 和 Material UI。Bootstrap 和 Bulma 等框架利用预先准备好的组件(例如按钮、菜单和面包屑)进行设计。在 Tailwind CSS 中,没有准备任何组件,而是使用Utilize Class来创建设计自己的组件。 原来Bootstrap等框架可以通过提前准备组件集合来高效地设计网站,但是有一个缺点,就是因为使用了相同的设计,所以没有原创性。相比之下,Tailwind CSS 没有组件集合,所以即使你创建一个名为相同按钮的组件,每个人都会应用不同的Utilize Class创建它,可以创建出一个高度原创的网站。

两者都有优点和缺点,所以使用哪一个取决于个人,但使用 Tailwind CSS 的人数正在稳步增加

什么是Utilize Class?

例如,如果要使用 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 设置圆角。
-->

问题3、这跟在项目中直接写好全局的类名然后直接使用,有什么区别呢?

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: [],
}

问题4、与其他UI组件同时引用时,可能会出现样式冲突

// 注释掉 @tailwind base 样式
// tailwind.css
/* @tailwind base;
@tailwind components;
@tailwind utilities; */


// 关闭默认样式
// tailwind.config.js
...
export const corePlugins = {
  preflight: false
}
...

下载preflight.css,手动导入,解决冲突。图片

6、总结

优点

  • 默认样式好看
  • 响应式系统更灵活
  • 主题可配置
  • 工具链完善
  • 开发效率高(配合VSCode插件)

应用场景

  • 偏展示型的网站(企业官网,产品官网,币圈各种官网等等)

适用人群

  • 对UI有决定权的人
    • 会前端的设计师
    • 独立开发者
    • ...

最后

为啥这个 css 框架叫 tailwind 呢? 因为作者 Adam Wathan喜欢叫做 kiteboarding 风筝冲浪的运动。 就是这样的,一个风筝,一个冲浪板:图片这种运动在顺风 tailwind 和逆风 headwind 下有不同的技巧。而 tailwind 的时候明显更加省力。 所以就给这个 css 框架起名叫 tailwind 了,借用其省力的意思。

作者介绍

贺燕珍:

  • 一个有两个孩子的妈妈。
  • 喜欢跑步、爬山和听音乐,这些活动可以帮助我释放压力。
  • 对自由的渴望驱使着我不断追求个人发展和成长。
  • 享受探索新技术和构建用户友好的界面的过程。
  • 希望我能努力保持积极的心态,以充满热情和创造力的方式工作。

58同城北京总部

CSS · 目录
上一篇前端换肤方案介绍和使用
继续滑动看下一个
58本地服务终端技术
向上滑动看下一个