样式和布局
本节重点介绍通过样式表进行样式设置。有关更高级的自定义(DOM 结构、React 代码等),请参阅 swizzling 指南。
Docusaurus 站点是单页面 React 应用程序。你可以按照 React 应用程序的样式设置方式来为其设置样式。
有几种方法/框架可用,具体取决于你的偏好以及你正在尝试构建的网站类型。高度交互且行为更像 Web 应用的网站将受益于更现代的样式方法,这些方法将样式与组件共同放置。当你想自定义或 swizzle 组件时,组件样式也特别有用。
全局样式
这是大多数开发人员(包括非前端开发人员)都熟悉的传统样式设置方式。它适用于不需要太多自定义的小型网站。
如果你正在使用 @docusaurus/preset-classic
,你可以创建自己的 CSS 文件(例如 /src/css/custom.css
),并通过将其作为经典主题的一个选项来全局导入。
export default {
// ...
presets: [
[
'@docusaurus/preset-classic',
{
theme: {
customCss: ['./src/css/custom.css'],
},
},
],
],
};
你在此文件中编写的任何 CSS 都将全局可用,并且可以使用字符串字面量直接引用。
.purple-text {
color: rebeccapurple;
}
function MyComponent() {
return (
<main>
<h1 className="purple-text">Purple Heading!</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',
blogAuthorsListPage: 'blog-authors-list-page',
blogAuthorsPostsPage: 'blog-authors-posts-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',
draftBanner: 'theme-draft-banner',
admonitionType: (type: string) => `theme-admonition-${type}`,
},
announcementBar: {
container: 'theme-announcement-bar',
},
layout: {
navbar: {
container: 'theme-layout-navbar',
containerLeft: 'theme-layout-navbar-left',
containerRight: 'theme-layout-navbar-right',
mobileSidebar: {
container: 'theme-layout-navbar-sidebar',
panel: 'theme-layout-navbar-sidebar-panel',
},
},
main: {
container: 'theme-layout-main',
},
footer: {
container: 'theme-layout-footer',
column: 'theme-layout-footer-column',
},
},
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: {
blogFooterTagsRow: 'theme-blog-footer-tags-row',
blogFooterEditMetaRow: 'theme-blog-footer-edit-meta-row',
},
pages: {
pageFooterEditMetaRow: 'theme-pages-footer-edit-meta-row',
},
} 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 | 失败 🔴 | |
--ifm-color-primary-lighter | #359962 | 失败 🔴 | |
--ifm-color-primary-light | #33925d | 失败 🔴 | |
--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 仅限于深色模式。
/* Overriding root Infima variables */
[data-theme='dark'] {
--ifm-color-primary: #4e89e8;
}
/* Styling one class specially in dark mode */
[data-theme='dark'] .purple-text {
color: plum;
}
可以通过 docusaurus-theme
查询字符串参数直接初始化 Docusaurus 主题。
示例
数据属性
可以通过遵循 docusaurus-data-<key>
模式的查询字符串参数来注入 <html>
数据属性。这使你可以根据查询字符串灵活地以不同方式设置页面样式。
例如,让我们渲染一个带有红色边框且没有导航栏的页面:
html[data-navbar='false'] .navbar {
display: none;
}
html[data-red-border] div#__docusaurus {
border: red solid thick;
}
如果你打算通过 iframe 在另一个网站上嵌入 Docusaurus 页面,那么创建替代显示模式并使用 iframe URL(例如 https://mysite.com/docs/myDoc?docusaurus-data-mode=iframe
)可能会很有用。提供额外的样式并决定要保留或隐藏哪些 UI 元素是你的责任。
移动视图
Docusaurus 使用 996px
作为移动屏幕宽度和桌面之间的分界线。如果你希望布局在移动视图中有所不同,可以使用媒体查询。
.banner {
padding: 4rem;
}
/** In mobile view, reduce the padding */
@media screen and (max-width: 996px) {
.heroBanner {
padding: 2rem;
}
}
一些 React 组件,如页眉和侧边栏,在移动视图中实现不同的 JavaScript 逻辑。如果你在自定义 CSS 中更改了断点值,你可能还需要通过 swizzling 它所使用的组件并传递一个显式选项参数来更新 useWindowSize
钩子调用。
CSS 模块
要使用 CSS Modules 为组件设置样式,请将样式表文件命名为带有 .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}>Hello!</h1>
<article className={styles.contents}>Lorem Ipsum</article>
</main>
);
}
类名将在构建过程中由 webpack 处理为全局唯一的类名。
CSS-in-JS
CSS-in-JS 支持仍在开发中,因此像 MUI 这样的库可能存在显示问题。欢迎 PR。
Sass/SCSS
要使用 Sass/SCSS 作为你的 CSS 预处理器,请安装非官方的 Docusaurus 插件 docusaurus-plugin-sass
。该插件适用于全局样式和 CSS 模块方法。
- npm
- Yarn
- pnpm
- Bun
npm install --save docusaurus-plugin-sass sass
yarn add docusaurus-plugin-sass sass
pnpm add docusaurus-plugin-sass sass
bun add docusaurus-plugin-sass sass
- 在你的
docusaurus.config.js
文件中包含该插件
export default {
// ...
plugins: ['docusaurus-plugin-sass'],
// ...
};
- 像往常一样用 Sass/SCSS 编写和导入你的样式表。
使用 Sass/SCSS 的全局样式
你现在可以将 @docusaurus/preset-classic
的 customCss
属性设置为指向你的 Sass/SCSS 文件。
export default {
presets: [
[
'@docusaurus/preset-classic',
{
// ...
theme: {
customCss: ['./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>
);
}
TypeScript 支持
要为 Sass/SCSS 模块启用 TypeScript 支持,应更新 TypeScript 配置以添加 docusaurus-plugin-sass
类型定义。这可以在 tsconfig.json
文件中完成。
{
"extends": "@docusaurus/tsconfig",
"compilerOptions": {
...
+ "types": ["docusaurus-plugin-sass"]
}
}