跳到主要内容
版本:2.2.0

样式和布局

提示

本章节侧重于通过样式表实现的样式。 对于更加高级的个性化需求(比如 DOM 结构、React 代码),请参阅 swizzle 教程

Docusaurus 网站是一个 React 单页应用。 你可以像一般的 React 应用一样给你的网站提供样式。

有几种可行的添加样式的手段/框架,取决于你的偏好和你正在搭建的网站的类型。 有些网站是高度可交互的,和 web 应用程序差不多,此时用更现代的样式手法,比如把样式和组件放在一起,会更加有益。 如果你想要定制某个组件或者 swizzle 它,基于组件的样式也会很有用。

全局样式

这是最传统的添加样式的方法,绝大多数开发者(包括非前端开发者)都应该比较熟悉。 对于没有多少个性化的小网站来说,它的效果不错了。

如果你用的是 @docusaurus/preset-classic,你可以新建一个 CSS 文件(比如 /src/css/custom.css),然后通过把它作为经典主题的选项来全局导入它。

docusaurus.config.js
module.exports = {
// ...
presets: [
[
'@docusaurus/preset-classic',
{
theme: {
customCss: [require.resolve('./src/css/custom.css')],
},
},
],
],
};

你在这个文件里编写的所有 CSS 都会全局可用,类名可以直接以字符串形式引用。

/src/css/custom.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-classicInfima 作为底层样式框架。 Infima 提供了灵活的布局,以及常见的 UI 组件样式,适用于以内容为中心的网站(博客、文档、首页)。 想要了解更多详情,请查看 Infima 网站

当你用 create-docusaurus 新建 Docusaurus 项目时,网站会生成基本的 Infima 样式表和默认样式。 你可以全局覆盖 Infima CSS 变量。

/src/css/custom.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#3cad6eFail 🔴
--ifm-color-primary-lighter#359962Fail 🔴
--ifm-color-primary-light#33925dFail 🔴
--ifm-color-primary#2e85550AA 👍
--ifm-color-primary-dark#29784cAA 👍
--ifm-color-primary-darker#277148AA 👍
--ifm-color-primary-darkest#205d3bAAA 🏅

src/css/custom.css 中的变量替换成这些新变量。

/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 中的传统。

styles.module.css
.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 模块方案都适用。

  1. 安装 docusaurus-plugin-sass
npm install --save docusaurus-plugin-sass sass
  1. docusaurus.config.js 文件中包含这个插件:
docusaurus.config.js
module.exports = {
// ...
plugins: ['docusaurus-plugin-sass'],
// ...
};
  1. 像平常一样,用 Sass/SCSS 编写样式表并导入。

使用 Sass/SCSS 的全局样式

你现在可以把 @docusaurus/preset-classiccustomCss 属性设置成你的 Sass/SCSS 文件:

docusaurus.config.js
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 模块。

styles.module.scss
.main {
padding: 12px;

article {
color: #ccc;
}
}
import styles from './styles.module.scss';

function MyComponent() {
return (
<main className={styles.main}>
<article>Lorem Ipsum</article>
</main>
);
}