0%

Tailwind CSS 的工程化实践与总结

实际项目开发中,Tailwind CSS 是一个非常好用的工具。它的原子化设计让我们可以快速上手,方便实现响应式布局和定制化设计。然而,随着项目复杂度的增加,Tailwind 的灵活性也带来了新的挑战,比如如何保持代码的可维护性、性能优化、适配复杂设计规范等。

今天,我结合我在项目中的实践经验,分享一些我个人使用 Tailwind CSS 时的注意事项和应对策略。

1. 样式冗长与可维护性问题

问题:

Tailwind 的原子化类名非常灵活,但当页面组件增多、样式变复杂时,HTML 中会出现大量的类名,代码变得冗长、重复,难以维护。例如,当你为多个组件写了相同的样式时,代码冗余就会越来越严重。

示例:

1
2
3
<div class="text-center bg-blue-500 px-6 py-4 rounded-lg shadow-md">
<p class="text-white font-bold text-xl">Welcome to the App</p>
</div>

这段代码在一个简单的场景下没什么问题,但当项目规模扩大,多个组件有类似的样式时,HTML 里堆砌的类名不仅冗长,还难以统一管理。

解决方案:

Tailwind 的 @apply 规则 可以很好地解决这个问题。通过将常用的样式抽象为自定义的类,我们可以减少重复代码,并且方便未来的维护。

1
2
3
4
5
6
7
/* 自定义复用样式 */
.btn-primary {
@apply text-center bg-blue-500 px-6 py-4 rounded-lg shadow-md;
}
.text-title {
@apply text-white font-bold text-xl;
}
1
2
3
4
<!-- 简化后的代码 -->
<div class="btn-primary">
<p class="text-title">Welcome to the App</p>
</div>

通过这种方式,我们大幅减少了冗余代码,尤其是在样式较为复杂或复用度高的场景下,非常有效。

2. 适配设计规范与业务需求

问题:

在实际业务中,还要根据 UI 设计规范严格实现样式,且目前大部分设计团队工具设计稿已自带tailwind插件,如图:

image.png

Tailwind 默认提供了一套不错的颜色、字体和间距,但很多时候,这些默认值并不能完全满足业务需求。例如,你可能需要特定的颜色或自定义的字体来满足品牌要求。

示例:

1
2
3
<div class="text-center bg-gray-500 text-gray-700">
<p>默认样式可能不符合设计规范</p>
</div>

解决方案:

扩展 Tailwind 的配置文件 是解决这个问题的关键。通过自定义 tailwind.config.js,我们可以为项目定制符合业务需求的主题,确保样式与设计规范一致。

1
2
3
4
5
6
7
8
9
10
11
12
13
module.exports = {
theme: {
extend: {
colors: {
primary: '#1E3A8A', // 定义业务主色调
secondary: '#9333EA',
},
fontFamily: {
sans: ['Helvetica', 'Arial', 'sans-serif'], // 自定义字体
},
},
},
};

通过这种方式,不仅可以保证与设计的统一,还能在项目中方便地复用自定义的颜色和字体,从而减少重复工作,提升开发效率。

3. 性能优化与按需裁剪

问题:

Tailwind 默认会生成大量的 CSS 类,尤其是在项目规模变大时,可能会导致最终打包的 CSS 文件体积过大,影响页面加载性能。这个问题在移动端或网络环境较差的场景中表现尤为明显。

解决方案:

PurgeCSS 是 Tailwind 提供的一个非常实用的功能,能够在生产环境下移除未使用的样式类,从而大幅缩减最终生成的 CSS 文件体积。

1
2
3
4
module.exports = {
purge: ['./src/**/*.{html,js,ts,jsx,tsx}'], // 指定需要清理的文件
theme: {},
};

通过这种配置,Tailwind 会在生产环境中自动裁剪未使用的 CSS 类,确保打包输出的文件仅包含项目实际需要的样式。

4. 响应式设计与页面类型适配

在实际开发中,不同设备的用户体验是很重要的。对于同一个组件,PC 和移动端的展示通常有所不同。为了适配这些不同的场景,Tailwind 提供了方便的断点系统,可以帮助我们轻松实现响应式设计。

示例:

在一个实际项目中,我需要根据页面类型(PC、H5、Copilot)进行不同的样式适配。为了保持代码的清晰性和可维护性,我配置了一套映射,将页面类型与样式关联起来。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import CopilotHeader from '../../components/CopilotHeader';
import { useSnapshot } from 'valtio';
import { contextService } from '../../service/register';
import { PageType } from '@loong-apaas/util-message';

// 定义不同页面类型的样式
const WrapClassMap = {
[PageType.Copilot]: 'fixed top-0 w-full px-6 z-[2] pointer-events-auto h-[88px] overflow-hidden',
[PageType.PC]: 'fixed top-6 right-0 px-6 z-[2] pointer-events-auto',
[PageType.H5]: 'hidden',
};

const ContentClassMap = {
Copilot: 'h-full relative box-border',
PC: '',
H5: '',
}

// 根据页面类型动态设置样式
const withCopilotHeader = () => {
const { clientData } = useSnapshot(contextService.state, { sync: true });
const { handleAutoBroadcastChange } = contextService;

return (
<div className={WrapClassMap[clientData.pageType]}>
<CopilotHeader
title={clientData.assistantInfo.name || ''}
description={clientData.assistantInfo.description || ''}
isAutoBroadcast={clientData.isAutoBroadcast}
onAutoBroadcastChange={handleAutoBroadcastChange}
className={ContentClassMap[clientData.pageType]}
isSingleControl={clientData.pageType === PageType.PC}
/>
</div>
);
};

export default withCopilotHeader;

通过 WrapClassMapContentClassMap,我为不同的页面类型设置了不同的样式。比如在 H5 页面中我们隐藏了 CopilotHeader,而在 PC 页面中则调整了其位置和布局。这种方法使得代码结构清晰,同时也非常方便扩展。如果以后增加新的页面类型,只需修改这两个映射表即可。

5. Tailwind 配置文件的共享与扩展

在大型项目中,不同子项目之间往往需要共享同一套样式规范。为了实现这一点,Tailwind 的 presets 可以将某些通用的样式配置提取出来,供多个子项目复用。

示例:

在我最近的项目中,我们使用了一个共享的 Tailwind 配置文件,确保各个子项目之间的样式一致性,同时根据不同子项目的需求进行个性化扩展。

1
2
3
4
5
6
7
8
9
10
11
12
13
import type { Config } from 'tailwindcss';
import { config as sharedConfig } from '@traffic/tailwind-config/default';

const config: Pick<Config, 'prefix' | 'presets' | 'content'> = {
content: [
'./src/**/*.{html,js,ts,jsx,tsx}',
'../../packages/ui-chat/src/**/*.{js,ts,jsx,tsx}',
'../../packages/ui-widget/src/**/*.{js,ts,jsx,tsx}',
],
presets: [sharedConfig], // 引用共享配置
};

export default config;

通过这种方式,不仅可以确保各个项目的样式规范一致,还能根据各自的业务需求灵活扩展。

总结

在业务驱动的背景下使用 Tailwind CSS,并不只是简单地使用原子类名,它需要结合业务需求,通过配置、样式抽象、性能优化等方式,来提升代码的可维护性和扩展性。Tailwind 提供了足够的灵活性,帮助我们快速实现响应式设计,但也要注意如何在复杂的业务场景中高效地使用它,实现组件复用性并保持扩展灵活性。