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.jsmodule.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>
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>
比如要实现一个媒体查询,根据不同的屏幕宽度实现不同的图片宽度。
按照之前的写法,可能得这么干@mediaonly screen and (max-width:1280px) { .img { width:196px; } }@mediaonly 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.jsmodule.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 配置中的第一个插件:exportdefault { plugins: { tailwindcss: {}, autoprefixer: {}, },}
通俗的讲法:postCss 就是一个开发工具,是一个用 JavaScript 工具和插件转换 CSS 代码的工具。支持变量,混入,未来 CSS 语法,内联图像等等。
PostCSS 包括 CSS 解析器,CSS 节点树 API,一个源映射生成器和一个节点树 stringifier。
PostCSS 主要的原理核心工作流:
image.png
在PostCSS中有几个关键的处理机制:(详细看postcss文档)
Source string → Tokenizer(分词器) → Parser(解析器) → AST → Processor (处理器)→ Stringifier(弦化器)->new css
image.png
基本的步骤:
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
许多人会想到 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...exportconstcorePlugins = { preflight: false}...
下载preflight.css,手动导入,解决冲突。
为啥这个 css 框架叫 tailwind 呢? 因为作者 Adam Wathan喜欢叫做 kiteboarding 风筝冲浪的运动。 就是这样的,一个风筝,一个冲浪板:
这种运动在顺风 tailwind 和逆风 headwind 下有不同的技巧。而 tailwind 的时候明显更加省力。 所以就给这个 css 框架起名叫 tailwind 了,借用其省力的意思。
贺燕珍:
来源:微信公众号:58本地服务终端技术
出处
:https://mp.weixin.qq.com/s/y9ZIJX_FxgeTRUi695-eDw