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

相关推荐
HEX9CF13 分钟前
【CTF Web】Pikachu xss之href输出 Writeup(GET请求+反射型XSS+javascript:伪协议绕过)
开发语言·前端·javascript·安全·网络安全·ecmascript·xss
凌云行者25 分钟前
使用rust写一个Web服务器——单线程版本
服务器·前端·rust
华农第一蒟蒻41 分钟前
Java中JWT(JSON Web Token)的运用
java·前端·spring boot·json·token
积水成江43 分钟前
关于Generator,async 和 await的介绍
前端·javascript·vue.js
___Dream44 分钟前
【黑马软件测试三】web功能测试、抓包
前端·功能测试
金灰44 分钟前
CSS3练习--电商web
前端·css·css3
人生の三重奏1 小时前
前端——js补充
开发语言·前端·javascript
Tandy12356_1 小时前
js逆向——webpack实战案例(一)
前端·javascript·安全·webpack
TonyH20021 小时前
webpack 4 的 30 个步骤构建 react 开发环境
前端·css·react.js·webpack·postcss·打包
你会发光哎u1 小时前
Webpack模式-Resolve-本地服务器
服务器·前端·webpack