# Tailwind CSS 小贴士

随笔 8 / 8
阅读约需 2 分钟
目录

@import 的位置

Tailwind 第一步——在全局的 CSS 中引入。不过当你有很多引入的时候可能会有这样的问题出现:

global.css
@import 'tailwindcss';
/* MiSans - 使用 jsdelivr CDN */
@import url('https://cdn.jsdelivr.net/npm/misans@4.1.0/lib/Normal/MiSans-Regular.min.css');
@import url('https://cdn.jsdelivr.net/npm/misans@4.1.0/lib/Normal/MiSans-Medium.min.css');
@import url('https://cdn.jsdelivr.net/npm/misans@4.1.0/lib/Normal/MiSans-Bold.min.css');
/* JetBrains Mono - 使用 jsdelivr CDN */
@import url('https://cdn.jsdelivr.net/npm/@fontsource-variable/jetbrains-mono@5.1.0/index.min.css');
12:46:01 [WARN] [vite] [vite:css][postcss] @import must precede all other statements (besides @charset or empty @layer)
1772| @import url('https://cdn.jsdelivr.net/npm/misans@4.1.0/lib/Normal/MiSans-Medium.min.css');
1773| @import url('https://cdn.jsdelivr.net/npm/misans@4.1.0/lib/Normal/MiSans-Bold.min.css');
1774| @import url('https://cdn.jsdelivr.net/npm/@fontsource-variable/jetbrains-mono@5.1.0/index.min.css');
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1775| header {
1776| view-transition-name: none;

解决办法和原因:@import 'tailwindcss'; 这一句会在编译时被 Tailwind 替换为大量的 CSS 代码,而 CSS 规范要求 @import 前不能有其他规则(除了 @charset 或空 @layer)。PostCSS 阶段位于 Tailwind 之后,因此最好把 Tailwind 引入放在所有 @import 语句的最后面。

动态拼接实用类

偶尔做组件的时候可能会希望有动态决定的样式,比如一个 Button,我希望它接受 type prop 来决定颜色,tip 是绿色,warning 是黄色,error 是红色。

Button.vue
<template>
<button :class="buttonClass">
<slot />
</button>
</template>
<script setup lang="ts">
import { computed, defineProps } from 'vue'
const props = defineProps<{
type: 'tip' | 'warning' | 'error'
}>()
const buttonClass = computed(() => {
switch (props.type) {
case 'tip':
return 'bg-green-500 border-green-500 shadow-green-500/20 text-white'
case 'warning':
return 'bg-yellow-500 border-yellow-500 shadow-yellow-500/20 text-white'
case 'error':
return 'bg-red-500 border-red-500 shadow-red-500/20 text-white'
}
})
</script>

这样的代码效果是没问题的。接着,我觉得,三种预设颜色好像有点太单调了,我想要自定义配色,于是写出了这样的代码:

Button.vue
<script setup lang="ts">
import { computed, defineProps } from 'vue'
const props = defineProps<{
type?: 'tip' | 'warning' | 'error'
customColor?: string
}>()
const buttonClass = computed(() => {
switch (props.type) {
case 'tip':
return 'bg-green-500 border-green-500 shadow-green-500/20 text-white'
case 'warning':
return 'bg-yellow-500 border-yellow-500 shadow-yellow-500/20 text-white'
case 'error':
return 'bg-red-500 border-red-500 shadow-red-500/20 text-white'
case undefined:
if (props.customColor) {
return `bg-[${props.customColor}] border-[${props.customColor}] shadow-[${props.customColor}/20] text-white`
} else {
return 'bg-gray-500 border-gray-500 shadow-gray-500/20 text-white'
}
}
})
</script>

看上去也没什么问题,但是当我在页面中使用这个组件时,发现无论传入什么颜色,按钮的颜色都没有变化,始终是灰色的。这是因为 Tailwind 在编译时并不知道 props.customColor 会是什么值,因此无法生成对应的 CSS 类。

要想解决这个问题,你必须确保对应的类至少完整的出现过一次,例如:

  • 在别处用过。
  • 使用了 safelist 包含过。
tailwind.config.js
module.exports = {
safelist: [
'bg-green-500',
'border-green-500',
'shadow-green-500/20',
'bg-yellow-500',
'border-yellow-500',
'shadow-yellow-500/20',
'bg-red-500',
'border-red-500',
'shadow-red-500/20',
],
}
写下此篇时暂时不是懒狗的星语

这是开发的责任感和前瞻性的问题。不兼容的改变不应该轻易被加入到有许多依赖代码的软件中。升级所付出的代价可能是巨大的。
—— 《语义化版本》


随笔 系列