样式和布局
本章节侧重于通过样式表实现的样式。 对于更加高级的个性化需求(比如 DOM 结构、React 代码),请参阅 swizzle 教程。
Docusaurus 网站是一个 React 单页应用。 你可以像一般的 React 应用一样给你的网站提供样式。
有几种可行的添加样式的手段/框架,取决于你的偏好和你正在搭建的网站的类型。 有些网站是高度可交互的,和 web 应用程序差不多,此时用更现代的样式手法,比如把样式和组件放在一起,会更加有益。 如果你想要定制某个组件或者 swizzle 它,基于组件的样式也会很有用。
全局样式
这是最传统的添加样式的方法,绝大多数开发者(包括非前端开发者)都应该比较熟悉。 对于没有多少个性化的小网站来说,它的效果不错了。
如果你用的是 @docusaurus/preset-classic
,你可以新建一个 CSS 文件(比如 /src/css/custom.css
),然后通过把它作为经典主题的选项来全局导入它。
module.exports = {
// ...
presets: [
[
'@docusaurus/preset-classic',
{
theme: {
customCss: [require.resolve('./src/css/custom.css')],
},
},
],
],
};
你在这个文件里编写的所有 CSS 都会全局可用,类名可以直接以字符串形式引用。
.purple-text {
color: rebeccapurple;
}
function MyComponent() {
return (
<main>
<h1 className="purple-text">紫色标题!</h1>
</main>
);
}
如果你想要给某个元素添加 CSS,你可以打开浏览器的开发者工具,然后用审查元素审查它的类名。 有几种类名:
- 主题类名。 在下一节中,我们完整列出了所有的主题类名。 它们没有默认样式。 你永远应该优先选择在 CSS 中引用这些稳定的类名。
- Infima 类名。 这些类名在经典主题中使用,通常符合 BEM 规范,即
block__element--modifier
。 它们通常是稳定的,但仍然被看作实现细节,所以你一般应该避免引用它们。 然而,你可以修改 Infima CSS 变量。 - CSS 模块类名。 这些类名在生产模式中有一个散列值 (
codeBlockContainer_RIuc
),在开发模式中以一个长长的文件路径结尾。 它们完全是实现细节,你几乎永远不应该在 CSS 里引用它们。 如果你没有别的选择了,你可以用属性选择器 ([class*='codeBlockContainer']
) 来忽略末尾的随机散列值。
主题类名
为了让全局样式变得健壮而可维护,我们提供了一些稳定的 CSS 类名。 这些类名与主题无关,目的就是由自定义 CSS 来引用。
如果你找不到一种安全地用 CSS 选择某个元素的方法,请汇报你的个性化用例,然后我们会考虑增加新的类名。
稳定类名的完整列表
export const ThemeClassNames = {
page: {
blogListPage: 'blog-list-page',
blogPostPage: 'blog-post-page',
blogTagsListPage: 'blog-tags-list-page',
blogTagPostListPage: 'blog-tags-post-list-page',
docsDocPage: 'docs-doc-page',
docsTagsListPage: 'docs-tags-list-page',
docsTagDocListPage: 'docs-tags-doc-list-page',
mdxPage: 'mdx-page',
},
wrapper: {
main: 'main-wrapper',
blogPages: 'blog-wrapper',
docsPages: 'docs-wrapper',
mdxPages: 'mdx-wrapper',
},
common: {
editThisPage: 'theme-edit-this-page',
lastUpdated: 'theme-last-updated',
backToTopButton: 'theme-back-to-top-button',
codeBlock: 'theme-code-block',
admonition: 'theme-admonition',
unlistedBanner: 'theme-unlisted-banner',
admonitionType: (type: string) => `theme-admonition-${type}`,
},
layout: {
},
docs: {
docVersionBanner: 'theme-doc-version-banner',
docVersionBadge: 'theme-doc-version-badge',
docBreadcrumbs: 'theme-doc-breadcrumbs',
docMarkdown: 'theme-doc-markdown',
docTocMobile: 'theme-doc-toc-mobile',
docTocDesktop: 'theme-doc-toc-desktop',
docFooter: 'theme-doc-footer',
docFooterTagsRow: 'theme-doc-footer-tags-row',
docFooterEditMetaRow: 'theme-doc-footer-edit-meta-row',
docSidebarContainer: 'theme-doc-sidebar-container',
docSidebarMenu: 'theme-doc-sidebar-menu',
docSidebarItemCategory: 'theme-doc-sidebar-item-category',
docSidebarItemLink: 'theme-doc-sidebar-item-link',
docSidebarItemCategoryLevel: (level: number) =>
`theme-doc-sidebar-item-category-level-${level}` as const,
docSidebarItemLinkLevel: (level: number) =>
`theme-doc-sidebar-item-link-level-${level}` as const,
},
blog: {
},
} as const;
用 Infima 给你的站点添加样式
@docusaurus/preset-classic
用 Infima 作为底层样式框架。 Infima 提供了灵活的布局,以及常见的 UI 组件样式,适用于以内容为中心的网站(博客、文档、首页)。 想要了解更多详情,请查看 Infima 网站。
当你用 create-docusaurus
新建 Docusaurus 项目时,网站会生成基本的 Infima 样式表和默认样式。 你可以全局覆盖 Infima CSS 变量。
:root {
--ifm-color-primary: #25c2a0;
--ifm-code-font-size: 95%;
}
Infima 每种颜色都使用 7 种色度。 我们建议用 ColorBox 为你选择的主色调生成不同的色度。
或者,可以用下面的工具来生成不同的色度,然后把变量复制进 /src/css/custom.css
。
主色调最好至少有 WCAG-AA 对比度,以保证可读性。你可以用 Docusaurus 自己的网站来预览你的配色的效果。深色模式下,你可以换一套配色,因为同一种颜色一般不能在浅色和深色模式下都保持足够的可读性。
CSS 变量名称 | 十六进制值 | 颜色调整值 | 对比度评分 |
---|---|---|---|
--ifm-color-primary-lightest | #3cad6e | Fail 🔴 | |
--ifm-color-primary-lighter | #359962 | Fail 🔴 | |
--ifm-color-primary-light | #33925d | Fail 🔴 | |
--ifm-color-primary | #2e8555 | 0 | AA 👍 |
--ifm-color-primary-dark | #29784c | AA 👍 | |
--ifm-color-primary-darker | #277148 | AA 👍 | |
--ifm-color-primary-darkest | #205d3b | AAA 🏅 |
把 src/css/custom.css
中的变量替换成这些新变量。
:root {
--ifm-color-primary: #2e8555;
--ifm-color-primary-dark: #29784c;
--ifm-color-primary-darker: #277148;
--ifm-color-primary-darkest: #205d3b;
--ifm-color-primary-light: #33925d;
--ifm-color-primary-lighter: #359962;
--ifm-color-primary-lightest: #3cad6e;
}
暗黑模式
浅色模式下,<html>
元素会有 data-theme="light"
属性;在暗黑模式下,属性会变成 data-theme="dark"
。 因此,你可以通过选择包含某个特定属性的 html
元素,来将你的 CSS 限定到仅暗黑模式有效。
/* 覆盖 Infima 根变量 */
[data-theme='dark'] {
--ifm-color-primary: #4e89e8;
}
/* 给某个类名添加深色模式的专有样式 */
[data-theme='dark'] .purple-text {
color: plum;
}
移动设备视图
Docusaurus 使用 996px
作为移动屏幕和桌面设备之间的宽度分割线。 如果你希望你的布局在移动设备上有所不同,你可以用 CSS 媒体查询。
.banner {
padding: 4rem;
}
/** 在移动设备上,缩小 padding */
@media screen and (max-width: 996px) {
.heroBanner {
padding: 2rem;
}
}
CSS 模块
如果想用 CSS 模块来为组件添加样式,只需在样式表文件名后添加 .module.css
后缀(比如 welcome.module.css
)。 Webpack 会把这样的 CSS 文件作为 CSS 模块加载,你必须在引用类名时,使用导入的 CSS 模块的属性(而不是使用普通字符串)。 这类似 Create React App 中的传统。
.main {
padding: 12px;
}
.heading {
font-weight: bold;
}
.contents {
color: #ccc;
}
import styles from './styles.module.css';
function MyComponent() {
return (
<main className={styles.main}>
<h1 className={styles.heading}>你好!</h1>
<article className={styles.contents}>Lorem Ipsum</article>
</main>
);
}
构建过程中,类名会被 webpack 处理成全局唯一的。
CSS-in-JS
CSS-in-JS 的支持尚未完工,所以 MUI 一类的库可能会有显示问题。 欢迎贡献代码。
Sass/SCSS
要用 Sass/SCSS 作为 CSS 预处理器,请安装非官方的 Docusaurus 2 插件 docusaurus-plugin-sass
。 这个插件对于全局样式和 CSS 模块方案都适用。
- npm
- Yarn
- pnpm
npm install --save docusaurus-plugin-sass sass
yarn add docusaurus-plugin-sass sass
pnpm add docusaurus-plugin-sass sass
- 在
docusaurus.config.js
文件中包含这个插件:
module.exports = {
// ...
plugins: ['docusaurus-plugin-sass'],
// ...
};
- 像平常一样,用 Sass/SCSS 编写样式表并导入。
使用 Sass/SCSS 的全局样式
你现在可以把 @docusaurus/preset-classic
的 customCss
属性设置成你的 Sass/SCSS 文件:
module.exports = {
presets: [
[
'@docusaurus/preset-classic',
{
// ...
theme: {
customCss: [require.resolve('./src/css/custom.scss')],
},
// ...
},
],
],
};
使用 Sass/SCSS 模块
在你的样式表文件名后添加 .module.scss
后缀(比如 welcome.module.scss
),而不是 .css
。 Webpack 会用 sass-loader
预处理样式表,然后把它加载为 CSS 模块。
.main {
padding: 12px;
article {
color: #ccc;
}
}
import styles from './styles.module.scss';
function MyComponent() {
return (
<main className={styles.main}>
<article>Lorem Ipsum</article>
</main>
);
}