Next.js 14中next/font与Tailwind配合时按钮显示不一致问题
问题描述
升级至Next.js 14时使用next/font遇到样式异常:两个Tailwind类完全一致的按钮,仅其中一个末尾添加了next/font生成的className,结果只有未添加该className的按钮显示粗体,且两者font-family完全相同。
代码示例:
import type { Metadata } from "next"; import { Lato } from "next/font/google"; import "./globals.css"; const LatoFont = Lato({ subsets: ["latin"], weight: "400", }); export const metadata: Metadata = { title: "Create Next App", description: "Generated by create next app", }; export default function RootLayout({ children, }: { children: React.ReactNode; }) { return ( <html lang="en"> <body style={{ backgroundColor: "rgba (244, 241, 255, 1)" }} className={` ${LatoFont.className}`} > {/* {children} */} <button className={`bg-red-600 hover:bg-red-700 text-white font-semibold py-2 px-4 rounded-lg w-1/2 mr-2 ${LatoFont.className}`} > Google </button> <button className={`bg-red-600 hover:bg-red-700 text-white font-semibold py-2 px-4 rounded-lg w-1/2 mr-2`} > Google </button> </body> </html> ); }
原因分析
next/font生成的className包含固定字重:定义LatoFont时指定了weight: "400",next/font会为生成的className自动添加font-weight: 400的样式,而不只是设置字体家族。- CSS样式覆盖:第一个按钮的className中,
font-semibold(对应Tailwind的font-weight: 600)写在${LatoFont.className}之前,CSS中后声明的样式优先级更高,因此font-weight: 400会覆盖font-semibold的600权重,导致按钮显示常规字重。 - 第二个按钮的粗体来源:第二个按钮未添加
LatoFont.className,但继承了body上的字体家族设置;同时font-semibold的600权重没有被覆盖,由于仅加载了Lato的400权重,浏览器会自动合成粗体效果,所以呈现为粗体。
解决方案
- 加载对应权重的字体:如果需要使用
font-semibold(600权重),在定义Lato时同时加载该权重:const LatoFont = Lato({ subsets: ["latin"], weight: ["400", "600"], // 同时加载400和600两种权重 }); - 移除重复的字体className:既然
body已经全局应用了LatoFont.className,按钮上无需重复添加,这样font-semibold的权重就能正常生效。 - 调整className顺序(不推荐):若一定要在按钮上添加字体className,将
font-semibold放在${LatoFont.className}之后,让它覆盖字体类的权重设置,但这种做法会破坏样式一致性,不建议采用。
内容的提问来源于stack exchange,提问作者sonphung.xf
相关产品推荐
相关产品推荐

