Next.js 支持哪些样式方案?

本文为稀土掘金技术社区首发签约文章,30天内禁止转载,30天后未获授权禁止转载,侵权必究!

群友问:Next.js 怎么支持 less?

答案很简单:Next.js 就是不支持 less。

不过,Next.js 支持了除 less 以外的其他多种样式方案,如:CSS-in-JS、全局CSS、CSS模块、Sass 和 Tailwind CSS,本文就来介绍一下这些方案。

CSS-in-JS

CSS-in-JS 是将 CSS 与 JavaScript 代码结合在一起的方式,能够充分利用 JavaScript 的模块化和封装特性来管理样式,规避样式冲突的问题。Next.js 支持多种 CSS-in-JS 库,如 styled-componentsstyled-jsx

不过,由于 Next.js 作为一个以服务端渲染为主的框架,某些 CSS-in-JS 库在 React 的服务器组件(Server Components)中使用可能会遇到兼容性问题;此外,CSS-in-JS 的另一个潜在问题是增加了 JavaScript 的体积,这可能对渲染性能产生影响。

鉴于这些因素,我个人不建议在 Next.js 项目中使用 CSS-in-JS 方案。

全局CSS

在 Next.js 项目中,使用全局 CSS 可以定义应用于整个项目的样式。例如,可以在 styles/globals.css 中定义全局样式,然后在 app 文件夹下的布局文件(layout.tsx)或页面文件(page.tsx)中导入它。

以下是一个示例:

css 复制代码
/* styles/globals.css */

body {
  color: black;
}

app/layout.tsx 中导入 globals.css,则全局的 body 样式将应用黑色:

jsx 复制代码
/* app/layout.tsx */

import '@/styles/globals.css'

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  )
}

但如果新增加一个名为 login.css 的样式文件,在该文件中将 bodycolor 设置为蓝色:

css 复制代码
/* styles/login.css */

body {
  color: blue;
}

并在 app/login 文件夹内新增 layout.tsx,并导入 login.css

jsx 复制代码
/* app/login/layout.tsx */
import '@/styles/login.css' // 注释掉会应用globals.css的样式

export default function LoginLayout({ children }) {
  return (
    <html lang="en">
      <body>{children}</body>
    </html>
  )
}

在这种情况下,登录页面的 body 文本颜色将变为蓝色。如果我们注释掉 import '@/styles/login.css' 这一行,文本颜色将恢复为黑色,因为上层 layout.tsx 中导入的 globals.css 将会生效。这就是所谓的"就近原则",即页面将根据与当前组件最接近的全局样式文件来应用样式。

因此,我建议尽可能只维护一个全局样式文件,其中包含可以全局应用的样式和CSS变量定义。

除此之外,Next.js 还支持从 node_modules 依赖包中导入样式文件,例如:

jsx 复制代码
import 'bootstrap/dist/css/bootstrap.css'

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body className="container">{children}</body>
    </html>
  )
}

但这种做法可能会导致样式冲突和不可预测的结果,因此也不建议使用。

CSS模块

Next.js 内置对 CSS 模块的支持,这是一种使用 .module.css 扩展名的局部作用域 CSS 方法。在不同的 CSS 模块文件中,即便样式类名相同,Next.js 也会自动生成唯一的类名,以避免样式冲突。这种方法尤其适用于组件级别的样式管理。

例如以下场景,我们有两个组件,每个组件都有自己的 CSS 模块文件:

组件 A 的 CSS 模块 (ComponentA.module.css):

css 复制代码
.button {
  background-color: blue;
  color: white;
}

组件 B 的 CSS 模块 (ComponentB.module.css):

css 复制代码
.button {
  background-color: green;
  color: black;
}

在这两个 CSS 模块中,都定义了 .button 类。

在组件中使用这些 CSS 模块时,应通过 import ... from ... 方式导入,Next.js 会自动处理它们,生成唯一的类名。

在组件 A 中使用 (ComponentA.jsx):

jsx 复制代码
import styles from './ComponentA.module.css';

function ComponentA() {
  return <button className={styles.button}>Button A</button>;
}

在组件 B 中使用 (ComponentB.jsx):

jsx 复制代码
import styles from './ComponentB.module.css';

function ComponentB() {
  return <button className={styles.button}>Button B</button>;
}

在构建过程中,Next.js 会为每个组件的 .button 类生成独特的标识符,如 .ComponentA_button__FR_sA.ComponentB_button__2C5X

在生产环境中,Next.js 会自动对所有 CSS 模块文件进行处理。这包括将这些文件合并成多个压缩的 .css 文件,并实施代码分割。这种处理方式是根据应用中的热执行路径(hot execution paths)来优化的,意味着只会加载渲染应用所必需的最少量 CSS。这不仅优化了加载速度,还减少了不必要的资源消耗,从而提高了应用的整体性能和用户体验。

Sass

Sass 是一种广受欢迎的 CSS 预处理器,它通过引入变量、嵌套规则、混合体等功能来扩展 CSS 的能力。Sass 提供了两种语法:.sass.scss

.sass 文件使用一种基于缩进的语法,不需要大括号和分号:

sass 复制代码
#sidebar
  width: 30%
  background-color: #fafafa

.scss 文件则使用类似于传统 CSS 的语法:

scss 复制代码
#sidebar {
  width: 30%;
  background-color: #fafafa;
}

我推荐使用 .scss 文件格式,因为它更符合大多数开发者编写 CSS 的习惯。

在 Next.js 中使用 Sass 非常简单。首先,需要安装 Sass 作为依赖:

bash 复制代码
npm install --save-dev sass
# 或
yarn add sass

Next.js 使用 Sass 的方式与 CSS 模块类似。你可以将前一节提到的 .module.css 文件后缀更改为 .module.scss 来尝试。

此外,Next.js 还内置了对 Sass 模块的解析,简化了使用 @import 导入路径的过程。例如,假设有以下 Sass 文件结构:

markdown 复制代码
/styles
|-- globals.scss
|-- _variables.scss

可以在 globals.scss 中这样使用 @import 导入:

scss 复制代码
// styles/globals.scss

@import 'variables';

Next.js 的内置模块解析能力会在编译 Sass 文件时,在同一目录下查找并导入对应的 Sass 文件。

但是,如果需要从非同级目录导入 Sass 文件,就需要在 next.config.js 中添加自定义的 Sass 解析器配置:

jsx 复制代码
const path = require('path')
 
module.exports = {
  sassOptions: {
    includePaths: [path.join(__dirname, 'styles')], // 配置 Sass 编译器
  },
}

通过这样的配置,例如当有以下文件结构时:

jsx 复制代码
/components
|-- componentA.scss
/styles
|-- _variables.scss

就可以在 componentA.scss 中正确地导入 _variables.scss

jsx 复制代码
// components/componentA.scss

@import 'variables';

没有这种自定义的 Sass 编译配置时,从非同级目录导入 Sass 文件会导致编译错误。

Tailwind CSS

Tailwind CSS 是一个功能性的 CSS 框架,与传统的 CSS 框架(如 Bootstrap)有所不同。它不提供预设的组件样式,而是提供了一系列可组合的原子化样式类,让开发者能够灵活地创造所需的样式。

原子化的概念

平时我们会这样写样式:

html 复制代码
<div class="content"></div>

<style>
.content {
  font-size: 14px;
  padding: 2px;
  border: 1px solid #000;
}
</style>

而在 Tailwind CSS 中,原子化的写法更为简洁:

html 复制代码
<div class="text-sm p-0.5 border"></div>

原子化 CSS 带来了诸多优势:

  • 一致性和重用性:通过统一的样式类,整个项目中的样式更加一致。这种方法鼓励重用而非重复创建样式规则,减少了代码的冗余。
  • 减少上下文切换:开发者可以直接在 HTML 中定义样式,避免在 HTML 和 CSS 文件之间频繁切换。
  • 更小的样式文件体积:虽然 HTML 文件中的类名增多,但大量重用导致整体上 CSS 文件体积更小,尤其在大型项目中效果显著。

当然,Tailwind CSS 并不是完美的。一些开发者在刚接触Tailwind CSS时,可能因为需要记忆大量的样式类而犹豫。但请尝试一下,经过短暂的适应期后,你就会发现 Tailwind CSS 显著提高了样式编写的效率。这是"磨刀"与"砍柴"的关系,Tailwind CSS绝对值得学习。

在 Next.js 中使用 Tailwind CSS

如果通过 create-next-app 构建 Next.js 应用,可以选择自动集成 Tailwind CSS。例如,前文提到的项目结构中包含了 tailwind.config.ts,这正是集成 Tailwind CSS 后的配置文件。

如果未在项目构建时选择 Tailwind CSS,也可以手动初始化配置:

bash 复制代码
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

这将生成 tailwind.config.jspostcss.config.js ****两个文件。

下面是 Next.js 所需的基本 Tailwind 配置:

bash 复制代码
import type { Config } from 'tailwindcss'

const config: Config = {
  content: [
    './pages/**/*.{js,ts,jsx,tsx,mdx}',
    './components/**/*.{js,ts,jsx,tsx,mdx}',
    './app/**/*.{js,ts,jsx,tsx,mdx}',
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}
export default config

在实际项目中,可根据设计需求自定义主题(theme)或添加插件(plugins)。
💡 Tailwind主题定义包括定制响应式屏幕边界、颜色色值和字体名称等等可能大量使用的样式信息,插件则是一些能增强Tailwind样式的外部库。这些知识如果展开介绍篇幅会太长,如果你对Tailwind不熟悉,请到官方中文网站学习:https://www.tailwindcss.cn/。

要使 Tailwind 的样式生效,需要在全局 CSS 文件中导入相关指令:

css 复制代码
/* styles/globals.css */

@tailwind base;
@tailwind components;
@tailwind utilities;

现在,可以在组件中直接使用 Tailwind CSS 的样式类:

jsx 复制代码
export default function Page() {
  return <h1 className="text-3xl font-bold underline">Hello, Next.js!</h1>
}

Tailwind CSS 的生态系统发展迅速,已被众多开源和商业项目采用。在 Next.js 的生态系统中,Tailwind CSS 占据着重要的位置,许多优秀的 UI 库也采用 Tailwind CSS 编写样式。因此,在 Next.js 项目中大胆使用 Tailwind CSS 吧!

结语

以上就是 Next.js 目前支持的所有样式方案了,你可以从中选择一个自己喜欢的或者擅长的方案来使用。

关于我

我是一名前端工程师,Next.js 手艺人,AI降临派。

今年致力于 Next.js 和 Node.js 领域的开源项目开发和知识分享。

欢迎关注我的 掘金Github

相关推荐
慧一居士22 分钟前
flex 布局完整功能介绍和示例演示
前端
DoraBigHead24 分钟前
小哆啦解题记——两数失踪事件
前端·算法·面试
一斤代码6 小时前
vue3 下载图片(标签内容可转图)
前端·javascript·vue
中微子6 小时前
React Router 源码深度剖析解决面试中的深层次问题
前端·react.js
光影少年6 小时前
从前端转go开发的学习路线
前端·学习·golang
中微子6 小时前
React Router 面试指南:从基础到实战
前端·react.js·前端框架
3Katrina6 小时前
深入理解 useLayoutEffect:解决 UI "闪烁"问题的利器
前端·javascript·面试
前端_学习之路7 小时前
React--Fiber 架构
前端·react.js·架构
伍哥的传说8 小时前
React 实现五子棋人机对战小游戏
前端·javascript·react.js·前端框架·node.js·ecmascript·js
qq_424409198 小时前
uniapp的app项目,某个页面长时间无操作,返回首页
前端·vue.js·uni-app