前面的章节我们主要关注功能和逻辑,本节来聊聊样式。Next.js 支持多种样式方案,你可以根据自己的习惯和项目需求选择合适的方案。
样式方法概述
Next.js 支持多种样式方案:
- Tailwind CSS - 推荐方式(默认包含)
- CSS Modules - 组件级作用域 CSS
- CSS-in-JS - styled-components、emotion 等
- Sass - CSS 预处理器
- 全局 CSS - 传统的全局样式文件
其中 Tailwind CSS 是 Next.js 推荐的方式,也是目前最流行的选择。
Tailwind CSS
Tailwind CSS 是一个功能类优先的 CSS 框架,能让你快速构建自定义设计。
安装 Tailwind
使用 create-next-app 时可以自动安装:
npx create-next-app@latest my-app --tailwind
或者手动安装:
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
配置 Tailwind
// tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./app/**/*.{js,ts,jsx,tsx,mdx}',
'./pages/**/*.{js,ts,jsx,tsx,mdx}',
'./components/**/*.{js,ts,jsx,tsx,mdx}',
],
theme: {
extend: {
colors: {
primary: {
50: '#f0f9ff',
100: '#e0f2fe',
500: '#0ea5e9',
900: '#0c4a6e',
},
},
},
},
plugins: [],
}
全局样式
/* app/globals.css */
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer base {
body {
@apply bg-gray-50 text-gray-900;
}
}
@layer components {
.btn-primary {
@apply px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600;
}
.card {
@apply bg-white rounded-lg shadow-md p-6;
}
}
使用 Tailwind 类
export default function Page() {
return (
<div className="min-h-screen bg-gray-50">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<h1 className="text-3xl font-bold text-gray-900">
标题
</h1>
<button className="btn-primary">
按钮
</button>
</div>
</div>
)
}
CSS Modules
如果你更喜欢传统的 CSS 写法,CSS Modules 是个不错的选择。
基本 CSS Module
/* components/Button.module.css */
.button {
padding: 0.5rem 1rem;
background-color: blue;
color: white;
border: none;
border-radius: 0.25rem;
}
.button:hover {
background-color: darkblue;
}
// components/Button.tsx
import styles from './Button.module.css'
export default function Button() {
return <button className={styles.button}>点击</button>
}
CSS Modules 与 Tailwind 混用
import styles from './Card.module.css'
export default function Card() {
return (
<div className={`bg-white rounded-lg ${styles.card}`}>
<h2>标题</h2>
</div>
)
}
CSS-in-JS
CSS-in-JS 库让你可以在 JavaScript 中写样式,但需要注意,大多数 CSS-in-JS 库只支持客户端组件。
styled-components
// components/Button.tsx
'use client'
import styled from 'styled-components'
const StyledButton = styled.button`
padding: 0.5rem 1rem;
background-color: blue;
color: white;
border: none;
border-radius: 0.25rem;
&:hover {
background-color: darkblue;
}
`
export default function Button() {
return <StyledButton>点击</StyledButton>
}
Sass
Sass 是一个 CSS 预处理器,提供了变量、嵌套、混合等功能。
安装 Sass
npm install -D sass
使用 Sass
/* styles/styles.scss */
$primary-color: blue;
.button {
padding: 0.5rem 1rem;
background-color: $primary-color;
color: white;
&:hover {
background-color: darkblue;
}
}
import './styles.scss'
export default function Button() {
return <button className="button">点击</button>
}
全局 CSS
对于简单的项目,使用全局 CSS 也是完全可以的。
/* app/globals.css */
body {
margin: 0;
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 1rem;
}
响应式设计
Next.js 和 Tailwind CSS 让响应式设计变得很简单:
export default function ResponsiveGrid() {
return (
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
<div>项目 1</div>
<div>项目 2</div>
<div>项目 3</div>
</div>
)
}
暗色模式
实现暗色模式:
// components/ThemeProvider.tsx
'use client'
import { createContext, useContext, useEffect, useState } from 'react'
type Theme = 'light' | 'dark'
const ThemeContext = createContext<{
theme: Theme
toggleTheme: () => void
}>({
theme: 'light',
toggleTheme: () => {},
})
export function ThemeProvider({ children }: { children: React.ReactNode }) {
const [theme, setTheme] = useState<Theme>('light')
useEffect(() => {
const savedTheme = localStorage.getItem('theme') as Theme
if (savedTheme) setTheme(savedTheme)
}, [])
useEffect(() => {
document.documentElement.classList.toggle('dark', theme === 'dark')
localStorage.setItem('theme', theme)
}, [theme])
function toggleTheme() {
setTheme((prev) => (prev === 'light' ? 'dark' : 'light'))
}
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
)
}
实用建议
这里分享几个在处理样式时特别有用的技巧。
优先使用 Tailwind
实际开发中,我发现 Tailwind CSS 能显著提高开发效率:
// 推荐这样做 - 使用 Tailwind 类
<div className="flex items-center gap-4">
// 内联样式虽然也可以,但维护起来不太方便
<div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>
使用组件类
这个技巧特别实用——把常用的样式组合成组件类,可以大大减少重复代码:
@layer components {
.card {
@apply bg-white rounded-lg shadow-md p-6;
}
}
避免内联样式
这里有个小建议:除非是动态值,否则尽量避免内联样式:
// 推荐这样做
<div className="text-blue-500">
// 动态值才用内联样式
<div style={{ color: userColor }}>
总结
本节我们学习了 Next.js 中的样式方案,包括 Tailwind CSS、CSS Modules、CSS-in-JS 等。Tailwind CSS 是最推荐的方案,能显著提高开发效率。选择合适的样式方案能让你的开发更高效。
如果你对本节内容有任何疑问,欢迎在评论区提出来,我们一起学习讨论。