第18章 样式与资源处理

CSS Modules、Tailwind CSS、图片和字体优化

作者:zyyc-0336  |  日期:2026-06-12

📍 学习路径建议

本文是前端学习路径第18章(Next.js · 样式与资源处理)
  1. 先学 18.1(全局样式),理解 globals.css 的作用
  2. 再学 18.2(CSS Modules),掌握组件级样式的写法
  3. 然后学 18.3(next/image),学会用 Image 组件加载图片
  4. 最后学 18.4(next/font),掌握字体优化

⚠️ 常见错误提示

全局样式只能layout.js 中导入,不能在 page.js 里导入
CSS Modules 的文件名必须是 xxx.module.css,否则不生效
<img> 标签在 Next.js 中会报警告,必须<Image /> 组件
next/font内置的,不需要额外安装任何包

📑 目录

  1. 18.1 全局样式
  2. 18.2 CSS Modules
  3. 18.3 next/image 图片组件
  4. 18.4 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.cssCSS 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