Next.js14中Shadcn Sheet组件内Tailwind样式不生效求助
基于Next.js 14、Tailwind和shadcn组件开发项目时,遇到shadcn的Sheet组件内部组件无法应用Tailwind样式的问题:Sheet内所有Tailwind样式均被忽略,比如给按钮设置bg-yellow-300类,按钮会失去颜色变得“不可见”,但在Sheet外使用该类则正常生效,仿佛Sheet内的Tailwind属性未被编译。
表单代码(entry-form.tsx)
import {useFieldArray, useForm} from "react-hook-form"; import {zodResolver} from "@hookform/resolvers/zod"; import {z} from "zod"; import {Form, FormControl, FormField, FormItem, FormLabel} from "@/components/ui/form"; import {Input} from "@/components/ui/input"; import {Button} from "@/components/ui/button"; import {Select} from "@/components/select"; import {Plus} from "lucide-react"; const dynamicFieldSchema = z.object({ name: z.string(), type: z.string(), }) const propertiesSchema = z.array(dynamicFieldSchema) const formSchema = z.object({ name: z.string(), url: z.string(), properties: propertiesSchema }) type FormValues = z.input<typeof formSchema> type Props = { id?: string; defaultValues?: FormValues; onSubmit: (values: FormValues) => void; onDelete?: () => void; disabled?: boolean; } export const EntryForm = ( { id, defaultValues, onSubmit, onDelete, disabled }: Props ) => { const form = useForm<FormValues>({ resolver: zodResolver(formSchema), defaultValues: { name: "", url: "", properties: [] } }) const {control, handleSubmit} = form const {fields, append, remove} = useFieldArray({ control, name: "properties" }) const typeOptions = [ {label: "STRING", value: "string"}, {label: "NUMBER", value: "number"}, {label: "BOOLEAN", value: "boolean"}, {label: "DOUBLE", value: "double"}, ] const submit = (values: FormValues) => { console.log({values}) onSubmit(values) } const handleDelete = () => { onDelete?.() } return ( <Form {...form}> <form onSubmit={form.handleSubmit(submit)} className="space-y-4"> <FormField name={"name"} control={form.control} render={({field}) => ( <FormItem> <FormLabel> Name of set </FormLabel> <FormControl> <Input disabled={disabled} placeholder="Posts..." {...field} /> </FormControl> </FormItem> )} /> <FormField name={"url"} control={form.control} render={({field}) => ( <FormItem> <FormLabel> URL of set </FormLabel> <FormControl> <Input disabled={disabled} placeholder="https://myweb.com/user?=1/posts..." {...field} /> </FormControl> </FormItem> )} /> {fields.map((item, index) => ( <div key={item.id} className="flex flex-col space-y-4"> <div className="flex flex-row gap-x-2"> <FormField name={`properties.${index}.name`} control={form.control} render={({field}) => ( <FormItem> <FormLabel> Name </FormLabel> <FormControl> <Input disabled={disabled} placeholder="name" {...field} /> </FormControl> </FormItem> )} /> <FormField name={`properties.${index}.type`} control={form.control} render={({field}) => ( <FormItem> <FormLabel> Type </FormLabel> <FormControl> <Select placeholder="STRING" options={typeOptions} disabled={disabled} onCreate={(name) => { console.log("Creating", name) }} value={field.value} onChange={field.onChange} /> </FormControl> </FormItem> )} /> </div> <Button type={"button"} onClick={() => remove(index)} > Remove property </Button> </div> ))} {/* 该className未生效 */} <div className="flex flex-col space-y-4 border-2 border-sky-700 rounded-md"> <p className="text-sm font-medium"> Define your object response type </p> {/* 该className未生效,无法给按钮设置任何样式 */} <Button type={"button"} onClick={() => append({name: "", type: ""})} className="w-fit bg-zinc-600" > <Plus className="size-4 mr-2"/> Add property </Button> </div> <Button className="w-full" disabled={disabled}> {id ? "Save changes" : "Create set"} </Button> </form> </Form> ) }
Sheet组件代码(new-entry-sheet.tsx)
import {insertEntrySchema} from "@/db/schema"; import {z} from "zod"; import {useNewEntry} from "@/features/entry/hooks/use-new-entry"; import {useCreateEntry} from "@/features/entry/api/use-create-entry"; import {Sheet, SheetContent, SheetDescription, SheetHeader, SheetTitle} from "@/components/ui/sheet"; import {EntryForm} from "@/features/entry/components/entry-form"; const formSchema = insertEntrySchema.omit({ userId: true }) type FormValues = z.input<typeof formSchema> export const NewEntrySheet = () => { const { isOpen, onClose } = useNewEntry() const mutation = useCreateEntry() const onSubmit = (values: FormValues) => { mutation.mutate(values, { onSuccess: () => { onClose(); } }) } return ( <Sheet open={isOpen} onOpenChange={onClose}> <SheetContent className="space-y-4"> <SheetHeader> <SheetTitle> New Data Set </SheetTitle> <SheetDescription className={"text-yellow-600"}> Create a new data set to track your data and manage your data. </SheetDescription> </SheetHeader> <EntryForm onSubmit={onSubmit} disabled={mutation.isPending} /> </SheetContent> </Sheet> ) }
项目其余部分的Tailwind样式正常工作,其他shadcn组件内的按钮也能正常应用样式,已排查tailwind.config.ts、components.json、globals.css的正确性,但问题仍未解决。
调整SheetContent的样式设置方式
shadcn的SheetContent内置样式可能干扰内部组件,建议移除SheetContent上的space-y-4,改用内部容器包裹内容来设置间距:<SheetContent> <div className="space-y-4 w-full"> <SheetHeader> {/* 原内容 */} </SheetHeader> <EntryForm onSubmit={onSubmit} disabled={mutation.isPending} /> </div> </SheetContent>确认Tailwind配置的内容覆盖路径
检查tailwind.config.ts中的content数组,确保包含EntryForm所在的目录(比如features),避免Tailwind未编译该组件的样式:/** @type {import('tailwindcss').Config} */ module.exports = { content: [ "./app/**/*.{js,ts,jsx,tsx,mdx}", "./components/**/*.{js,ts,jsx,tsx,mdx}", "./features/**/*.{js,ts,jsx,tsx,mdx}", // 必须包含此路径 ], theme: { extend: {}, }, plugins: [], }排查样式优先级问题
shadcn的Button组件默认样式优先级可能高于自定义Tailwind类,可临时用!important测试是否生效(仅用于排查,不推荐长期使用):<Button className="w-fit !bg-zinc-600"> <Plus className="size-4 mr-2"/> Add property </Button>若生效,可修改
components/ui/button.tsx中的默认样式,或通过Tailwind自定义变体来覆盖默认样式。清除缓存并重启开发服务
缓存可能导致样式未更新,执行以下操作:- 删除
.next目录 - 重启开发服务器:
npm run dev(或yarn dev) - 若仍无效,尝试执行
npm run build后再启动开发服务
- 删除
检查globals.css中的样式重置
确保globals.css中没有对Sheet内部元素的全局样式重置,比如是否存在* { background: transparent !important; }这类极端样式规则。
内容的提问来源于stack exchange,提问作者MACROSystems

