NextJS学习笔记 - 样式篇
内联 CSS
最基础的添加样式的方式便是使用内联 CSS
CSS 模块
Next.js 内置了对 CSS 模块的支持。使用 CSS 模块,你只需要使用 .module.css
作为文件后缀名,然后在你需要的文件中导入,Next.js 就会自动进行处理。
全局样式
全局样式,顾名思义,应用到所有路由的样式,像我们传统写页面 CSS 的时候,都会引入 normalize.css
或者 reset.css
等,这种场景就适合使用全局样式。
全局样式可以被导入 app
目录下的任意 layout、page 或者组件中。
外部样式表
你也可以通过导入外部包的方式添加样式,举个例子:
import 'bootstrap/dist/css/bootstrap.css'
不过要注意,该外部包必须是从 npm 包直接导入或者下载完和你的代码放在一起。
如果我想引用外部 CDN CSS 文件呢?就比如https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css 这种文件?
那你可以使用 <link>
标签添加在 Root Layout 中,就像这样:
// app/layout.js
import "./globals.css";
export default function RootLayout({ children }) {
return (
<html lang="en">
<head>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" />
</head>
<body>{ children }</body>
</html>
);
}
Tailwind CSS
Tailwind CSS 是一个非常知名的 CSS 框架,本质是一个工具集,包含了大量比如 flex
、pt-4
、text-center
、rotate-90
等工具类,可以组合使用并直接在 HTML 代码上实现任何 UI 设计。与 Next.js 搭配使用非常顺手。Next.js 官方便是用的 Tailwind CSS。
在使用 create-next-app
创建项目的时候,如果你在命令行中选择了使用 Tailwind CSS,则相关配置都会自动生成,可以直接使用。如果没有选择,希望引入 Tailwind CSS,可以参考此步骤。其实 Tailwind CSS 官方也提供了针对各个框架的使用指南
安装
在项目根目录执行以下命令:
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
会同时生成 tailwind.config.js
和 postcss.config.js
文件。
配置 Tailwind
postcss.config.js
不需要修改。在 tailwind.config.js
中添加使用 Tailwind CSS 类名的文件路径:
// 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}',
// 嫌麻烦,你也可以直接使用 `src` 目录
'./src/**/*.{js,ts,jsx,tsx,mdx}',
],
theme: {
extend: {},
},
plugins: [],
}
content
Tailwind CSS
是按需生成类名的,它需要扫描你项目中用到的类名,然后才会生成对应的 CSS。
比如你写了:<div className="bg-red-500 text-white px-4 py-2">按钮</div>
Tailwind 就会在打包时生成 .bg-red-500
、.text-white
等对应的 CSS。
但它要知道你在哪些文件中用了这些类名,这就需要你告诉它扫描哪些路径。
导入样式
添加 Tailwind CSS 指令,将 Tailwind 的样式注入到全局样式中。使用方式如下:
// app/globals.css
@tailwind base;
@tailwind components;
@tailwind utilities;
在根布局(app/layout.tsx
),导入 globals.css
:
// app/layout.js
import './globals.css'
export const metadata = {
title: 'Create Next App',
description: 'Generated by create next app',
}
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>{children}</body>
</html>
)
}
使用类名
然后你就可以在应用里使用 Tailwind 的工具类名:
// app/page.js
export default function Page() {
return <h1 className="text-3xl font-bold underline">Hello, Next.js!</h1>
}
辅助使用
在 VSCode 中使用的时候,可以安装 Tailwind CSS IntelliSense 这个插件,提供自动功能、语法校验、悬停预览等功能。
Tailwind CSS 中的工具类众多,记不清的时候也可以查询这个速查表。
CSS-in-JS
介绍
配置方式
在 Next.js 中配置 CSS-in-JS 的基本原理分为三步:
- 在渲染的时候有一个包含所有 CSS 规则的样式注册表
- 使用
useServerInsertedHTML
hook 在内容被使用前注入样式规则 - 使用包含样式注册表的客户端组件包裹应用
Styled Components
注意使用 styled-components@6
或者更高版本。
首先,创建一个全局注册表:
'use client'
// lib/registry.js
import React, { useState } from 'react'
import { useServerInsertedHTML } from 'next/navigation'
import { ServerStyleSheet, StyleSheetManager } from 'styled-components'
export default function StyledComponentsRegistry({ children }) {
const [styledComponentsStyleSheet] = useState(() => new ServerStyleSheet())
useServerInsertedHTML(() => {
const styles = styledComponentsStyleSheet.getStyleElement()
styledComponentsStyleSheet.instance.clearTag()
return <>{styles}</>
})
if (typeof window !== 'undefined') return <>{children}</>
return (
<StyleSheetManager sheet={styledComponentsStyleSheet.instance}>
{children}
</StyleSheetManager>
)
}
然后用此包含注册表的组件包裹根组件的 children
:
// app/layout.js
import StyledComponentsRegistry from './lib/registry'
export default function RootLayout({ children }) {
return (
<html>
<body>
<StyledComponentsRegistry>{children}</StyledComponentsRegistry>
</body>
</html>
)
}
然后你就可以在 page.js 中使用:
'use client';
import styled from 'styled-components';
const Container = styled.div`
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 1.5rem /* 24px */;
`;
const SkeletonInner = styled.div`
padding: 1rem /* 16px */;
background-color: rgb(24 24 27 / 0.8);
border-radius: 1rem /* 16px */;
`;
const SkeletonImg = styled.div`
height: 3.5rem /* 56px */;
border-radius: 0.5rem /* 8px */;
background-color: rgb(63 63 70 / 1);
`;
const SkeletonBtn = styled.div`
margin-top: 0.75rem /* 12px */;
width: 25%;
height: 0.75rem /* 12px */;
border-radius: 0.5rem /* 8px */;
background-color: rgb(255 0 128 / 1);
`;
const Skeleton = () => (
<SkeletonInner>
<SkeletonImg />
<SkeletonBtn />
</SkeletonInner>
);
export default function Page() {
return (
<div className="space-y-4">
<h1 className="text-xl font-medium text-gray-400/80">
Styled with Styled Components
</h1>
<Container>
<Skeleton />
<Skeleton />
<Skeleton />
</Container>
</div>
);
}
Sass
使用
Sass 作为知名的 CSS 预处理器已无须过多介绍。Next.js 内置了对 Sass 文件的支持,你需要使用 .scss
和 .sass
作为文件后缀。
你也可以结合 CSS 模块使用组件级别的 Sass, 你需要使用.module.scss
或者 .module.sass
作为文件后缀。
使用 sass,你需要首先安装 sass:npm install --save-dev sass
自定义配置
如果你希望配置 Sass 编译器,使用 next.config.js
的 sassOptions
选项:
// next.config.js
const path = require('path')
module.exports = {
sassOptions: {
includePaths: [path.join(__dirname, 'styles')],
},
}
Sass 变量
Next.js 支持从 CSS 模块文件导出 Sass 变量。这是一个示例代码:
// app/variables.module.scss
$primary-color: #64ff00;
:export {
primaryColor: $primary-color;
}
// app/page.js
// maps to root `/` URL
import variables from './variables.module.scss'
export default function Page() {
return <h1 style={{ color: variables.primaryColor }}>Hello, Next.js!</h1>
}