第18章 样式与资源处理
CSS Modules、Tailwind CSS、图片和字体优化
作者:zyyc-0336 | 日期:2026-06-12
📍 学习路径建议
本文是前端学习路径第18章(Next.js · 样式与资源处理)
- 先学 18.1(全局样式),理解
globals.css的作用 - 再学 18.2(CSS Modules),掌握组件级样式的写法
- 然后学 18.3(next/image),学会用 Image 组件加载图片
- 最后学 18.4(next/font),掌握字体优化
⚠️ 常见错误提示
全局样式只能在
layout.js 中导入,不能在 page.js 里导入CSS Modules 的文件名必须是
xxx.module.css,否则不生效<img> 标签在 Next.js 中会报警告,必须用 <Image /> 组件next/font 是内置的,不需要额外安装任何包18.1 全局样式
全局样式就是所有页面共享的样式,比如重置浏览器默认样式、设置全局字体和颜色。
Next.js 项目里有一个 app/globals.css 文件,这就是全局样式文件:
CSS
/* app/globals.css */
/* 重置浏览器默认样式 */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* 全局字体和背景 */
body {
font-family: sans-serif;
background-color: #f9fafb;
color: #333;
}
/* 全局链接样式 */
a {
color: #2563eb;
text-decoration: none;
}
💡 全局样式只在
app/layout.js 中导入一次,整个网站就都生效了。
JSX
// app/layout.js
import './globals.css'; // ← 只在这里导入
export default function RootLayout({ children }) {
return (
<html lang="zh-CN">
<body>{children}</body>
</html>
);
}
⚠️ 不要在
page.js 或其他组件里 import './globals.css',会导致样式重复加载甚至冲突。18.2 CSS Modules
CSS Modules 让每个组件拥有自己独立的样式,类名自动加哈希,绝对不会跟别的组件冲突。
创建 CSS Module 文件
文件名必须是 xxx.module.css
CSS
/* app/components/Card.module.css */
.card {
background: white;
border-radius: 12px;
padding: 24px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
transition: transform 0.2s;
}
.card:hover {
transform: translateY(-4px);
}
.title {
font-size: 1.25rem;
font-weight: bold;
margin-bottom: 8px;
color: #1f2937;
}
.description {
font-size: 0.9rem;
color: #6b7280;
line-height: 1.6;
}
在组件中使用
JSX
// app/components/Card.js
import styles from './Card.module.css';
export default function Card({ title, description }) {
return (
<div className={styles.card}>
<h3 className={styles.title}>{title}</h3>
<p className={styles.description}>{description}</p>
</div>
);
}
在页面中使用
JSX
// app/page.js
import Card from './components/Card';
export default function Home() {
return (
<div style={{ display: 'flex', gap: '20px', padding: '40px' }}>
<Card title="学习 Next.js" description="从零开始搭建现代网站" />
<Card title="学习 CSS" description="让页面变得好看起来" />
<Card title="学习 React" description="掌握组件化开发思维" />
</div>
);
}
💡 编译后,
.card 类名会变成类似 .Card_card__a1b2c 的形式,全局唯一,永远不会冲突。对比两种方式
| 特性 | 全局样式 globals.css | CSS Modules xxx.module.css |
|---|---|---|
| 作用范围 | 整个网站 | 只有导入它的那个组件 |
| 类名冲突 | 可能冲突 | 绝对不会冲突 |
| 适合场景 | 重置样式、全局主题 | 组件专属样式 |
| 导入方式 | import './globals.css' | import styles from './xxx.module.css' |
18.3 next/image 图片组件
Next.js 提供了
<Image /> 组件,自动帮你优化图片大小、懒加载、防止布局抖动。
JSX
// 直接用 HTML 的 <img> 标签 → 不推荐(会报警告)
<img src="/photo.jpg" alt="照片" />
// ✅ 用 Next.js 的 Image 组件
import Image from 'next/image';
export default function Avatar() {
return (
<Image
src="/avatar.png"
alt="头像"
width={120}
height={120}
priority // ← 首屏大图加上这个,优先加载
/>
);
}
常用属性一览
| 属性 | 说明 | 示例 |
|---|---|---|
src | 图片路径或远程 URL | "/photo.jpg" 或 "https://..." |
alt | 图片描述(无障碍) | "一只猫" |
width / height | 图片尺寸(像素) | width={400} height={300} |
priority | 优先加载(首屏图用) | priority |
fill | 自动填满父容器(不用写宽高) | fill |
style | 自定义样式 | style={{ borderRadius: '50%' }} |
使用 fill 模式(图片自适应容器大小)
JSX
// 需要父容器设置 position: relative + 固定宽高
<div style={{ position: 'relative', width: '300px', height: '200px' }}>
<Image
src="/cover.jpg"
alt="封面"
fill
style={{ objectFit: 'cover' }} // 裁剪适配
/>
</div>
加载远程图片(需要配置域名白名单)
需要在 next.config.js 中配置域名白名单:
JS
// next.config.js
module.exports = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'example.com',
},
],
},
};
JSX
<Image
src="https://example.com/photo.jpg"
alt="远程图片"
width={400}
height={300}
/>
18.4 next/font 字体优化
next/font 内置了字体加载功能,自动下载、自托管字体,避免从 Google Fonts 发请求,提升加载速度。加载 Google 字体
JSX
// app/layout.js
import { Inter, Noto_Sans_SC } from 'next/font/google';
const inter = Inter({ subsets: ['latin'] });
const notoSansSC = Noto_Sans_SC({
subsets: ['latin'],
weight: ['400', '700'],
display: 'swap',
});
export default function RootLayout({ children }) {
return (
<html lang="zh-CN">
<body className={notoSansSC.className}>
{children}
</body>
</html>
);
}
💡
display: 'swap' 的意思是:字体没加载完时先用系统默认字体,加载完后自动替换,用户不会看到空白。加载本地字体文件
JSX
// app/layout.js
import localFont from 'next/font/local';
const myFont = localFont({
src: './fonts/MyFont.woff2',
display: 'swap',
});
export default function RootLayout({ children }) {
return (
<html lang="zh-CN">
<body className={myFont.className}>
{children}
</body>
</html>
);
}
⚠️ 本地字体文件放在
app/fonts/ 目录下,支持 .woff2、.woff、.ttf、.otf 格式。给特定元素设置不同字重
JSX
const inter = Inter({
subsets: ['latin'],
weight: ['400', '700'],
});
// 在 JSX 中使用 CSS 变量
<html className={inter.variable}>
<body style={{ fontFamily: 'var(--font-inter), sans-serif' }}>
{children}
</body>
</html>
本章复盘——样式与资源处理核心要点
| 要点 | 说明 |
|---|---|
| CSS Modules | 组件级样式隔离,避免全局冲突 |
| 全局样式 | 在 _app.js 中引入全局 CSS |
| 静态资源 | public 目录存放图片、字体等 |
| next/image | 内置图片组件,自动优化加载性能 |
下一章预告(第19章):我们将学习部署与环境变量——生产环境部署流程和配置管理。
本文档由 zyyc-0336 编写,最后更新:2026-06-14