Next.js第十一课 - 样式与 CSS

0 阅读3分钟

前面的章节我们主要关注功能和逻辑,本节来聊聊样式。Next.js 支持多种样式方案,你可以根据自己的习惯和项目需求选择合适的方案。

样式方法概述

Next.js 支持多种样式方案:

  1. Tailwind CSS - 推荐方式(默认包含)
  2. CSS Modules - 组件级作用域 CSS
  3. CSS-in-JS - styled-components、emotion 等
  4. Sass - CSS 预处理器
  5. 全局 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 是最推荐的方案,能显著提高开发效率。选择合适的样式方案能让你的开发更高效。

如果你对本节内容有任何疑问,欢迎在评论区提出来,我们一起学习讨论。

原文地址:blog.uuhb.cn/archives/ne…