Laravel9 Inertia React中Tailwind @import外部CSS样式失效问题
问题根因
- 原生CSS语法要求
@import必须写在文件所有其他样式规则的最顶部,你最初将@import "input.css"放在三条@tailwind指令之后本身不符合规范,Vite会抛出警告;如果手动将@import挪到@tailwind之前,Tailwind编译时会先处理input.css的内容,此时Tailwind的三层样式(base/components/utilities)还未完成初始化,input.css里@apply调用的Tailwind工具类(包括:focus状态相关的伪类工具类)根本不存在,直接触发构建错误。 - Vite处理CSS时存在默认的
@import提升逻辑:即使你把@import写在@tailwind指令之后,构建时Vite也会自动把所有@import语句提到整个CSS文件的最顶部执行,最终效果和手动把@import挪到最前面完全一致,这就导致input.css的内容永远在Tailwind核心样式注入之前被处理,里面的伪类样式、自定义工具类无法被正确编译,自然不会生效。 - Tailwind的样式优先级按层级严格划分:
base < components < utilities,只有被纳入@layer规则的自定义样式才会被Tailwind正确排序、参与优先级计算。你之前写在@layer外的:focus相关样式,要么编译失败丢失,要么优先级低于你在components层写的全局input重置样式,被覆盖后无法生效。
正确拆分方案
方案1:在@layer内导入CSS文件(推荐)
不要用原生CSS的顶层@import,直接在Tailwind的@layer components块内导入拆分的input.css,Tailwind会自动处理导入顺序、样式优先级,支持Tree-shake,和你把样式全写在app.css里的效果完全一致。
修改resources/css/app.css:
@tailwind base; @tailwind components; @tailwind utilities; .flex::before, .flex::after { display: none !important; } @layer components { /* 注意写对相对路径,加./前缀 */ @import "./input.css"; [type="text"], [type="email"], [type="url"], [type="password"], [type="number"], [type="date"], [type="datetime-local"], [type="month"], [type="search"], [type="tel"], [type="time"], [type="week"], [multiple], textarea, select { border-color: transparent; } [type="text"]:focus, [type="email"]:focus, [type="url"]:focus, [type="password"]:focus, [type="number"]:focus, [type="date"]:focus, [type="datetime-local"]:focus, [type="month"]:focus, [type="search"]:focus, [type="tel"]:focus, [type="time"]:focus, [type="week"]:focus, [multiple]:focus, textarea:focus, select:focus { border-color: transparent; --tw-ring-color: transparent; } }
resources/css/input.css无需额外套@layer,保留原有写法即可:
.input-primary { @apply focus:bg-form-bg bg-form-bg focus:outline-alerange focus:outline-none; } .input-error { @apply ring ring-red-600; } .input-primary-outline { @apply bg-[#fff] focus:bg-[#fff] border-alerange focus:border-alerange; @apply file:bg-alerange file:text-white file:rounded-md file:pd-2; }
方案2:在JS入口文件导入拆分的CSS
Vite原生支持在JS/JSX文件中按顺序导入CSS,不会出现CSS原生@import的顺序提升问题。
首先打开Inertia项目的JS入口文件(通常是resources/js/app.jsx),在导入app.css的语句之后追加input.css的导入:
import '../css/app.css'; import '../css/input.css'; // 其余入口逻辑,比如createInertiaApp相关代码
为了保证样式优先级正确,给input.css里的自定义样式套上@layer components即可:
/* resources/css/input.css */ @layer components { .input-primary { @apply focus:bg-form-bg bg-form-bg focus:outline-alerange focus:outline-none; } .input-error { @apply ring ring-red-600; } .input-primary-outline { @apply bg-[#fff] focus:bg-[#fff] border-alerange focus:border-alerange; @apply file:bg-alerange file:text-white file:rounded-md file:pd-2; } }
注意事项
- 不要在Tailwind项目中使用顶层原生
@import导入包含@apply指令的CSS文件,很容易因为Vite的导入提升逻辑打乱Tailwind的编译顺序,导致样式丢失。 - 所有用到Tailwind工具类、伪类选择器的自定义组件样式,尽量放在
@layer components块内,既可以保证优先级正确,也能在生产构建时被Tree-shake,减小CSS包体积。
内容的提问来源于stack exchange,提问作者Naufal Aldy Pradana
相关产品推荐
相关产品推荐

