ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Quartz 5 页面布局完全指南:从 Section 槽位、Page Frame 到响应式断点的深度解析

Quartz 5 页面布局完全指南:从 Section 槽位、Page Frame 到响应式断点的深度解析 Quartz 5 页面布局完全指南从 Section 槽位、Page Frame 到响应式断点的深度解析【免费下载链接】quartz a fast, batteries-included static-site generator that transforms Markdown content into fully functional websites项目地址: https://gitcode.com/GitHub_Trending/qua/quartzQuartz 是一个将 Markdown 内容转换为完整网站的静态站点生成器其 v5 版本把页面布局的完全控制权交给了配置层你可以在quartz.config.yaml中通过layout.position、layout.priority与顶层layout段自由重组页面每一个区块。本文以 docs/layout.md 为主线结合 quartz/cfg.ts、config-loader.ts 等源码系统讲解页面槽位Section、组件排序、Flex 分组、条件渲染、Page Frame 与响应式断点的完整机制帮助你像拼积木一样定制属于自己的 Quartz 站点。页面由哪些 Section 组成Quartz 中每个页面由多个不同的 Section区域构成每个 Section 内可以放置一个或多个QuartzComponent。emitter 插件会把它们渲染为 HTML 输出而布局允许你完全重新排列这些区域。完整的布局结构定义在 quartz/cfg.ts 的FullPageLayout接口中export interface FullPageLayout { head: QuartzComponent // single component header: QuartzComponent[] // laid out horizontally beforeBody: QuartzComponent[] // laid out vertically pageBody: QuartzComponent // single component afterBody: QuartzComponent[] // laid out vertically left: QuartzComponent[] // vertical on desktop and tablet, horizontal on mobile right: QuartzComponent[] // vertical on desktop, horizontal on tablet and mobile footer: QuartzComponent[] // laid out vertically /** Page frame name (e.g. default, full-width, minimal). Defaults to default. */ frame?: string }每个槽位的渲染行为各不相同槽位Section类型布局方式说明head单组件—渲染 HTML 的head标签负责页面元数据标签页标题、脚本、样式不在页面上产生可见内容header组件数组水平排列位于beforeBody之前可复刻 Quartz 3 风格的顶栏标题 搜索框 暗色模式开关beforeBody组件数组垂直排列正文之前的内容区pageBody单组件—页面正文Content本体afterBody组件数组垂直排列正文之后的内容区left组件数组桌面/平板为垂直、移动端为水平左侧栏right组件数组桌面为垂直、平板/移动端为水平右侧栏footer组件数组垂直排列页脚不同屏幕宽度下这些槽位的实际排布如下图所示三张预览图来自 docs/images布局预览桌面宽度 1200px平板800px 宽度 1200px移动端宽度 800px[!note] 上方示意图中没有展示两个额外的布局字段head是一个渲染 HTMLhead标签的单组件不产生视觉内容只负责文档元数据标签页标题、脚本与样式。header是一组水平排列的组件位于beforeBody之前。你可以在插件配置中设置layout.position: header将组件放入其中从而实现类似 Quartz 3 顶栏标题、搜索框、暗色模式切换的布局。从源码看默认的三栏布局由 DefaultFrame.tsx 实现它依次渲染.left sidebar、.center内部包含.page-header包裹的header与beforeBody、pageBody、.page-footer包裹的afterBody、.right sidebar和footer。FullPageLayout中还有一个frame字段用于指定该页使用哪个 Page Frame详见下文Page Frames章节。插件如何声明自己的布局位置布局组件在quartz.config.yaml的layout段中配置。插件通过layout.position与layout.priority两个字段声明自己的位置和优先级布局系统会自动完成排列plugins: - source: github:quartz-community/explorer enabled: true layout: position: left priority: 50 - source: github:quartz-community/graph enabled: true layout: position: right priority: 10 - source: github:quartz-community/search enabled: true layout: position: left priority: 20 - source: github:quartz-community/backlinks enabled: true layout: position: right priority: 30 - source: github:quartz-community/article-title enabled: true layout: position: beforeBody priority: 10 - source: github:quartz-community/content-meta enabled: true layout: position: beforeBody priority: 20 - source: github:quartz-community/tag-list enabled: true layout: position: beforeBody priority: 30 - source: github:quartz-community/darkmode enabled: true layout: position: header priority: 10 - source: github:quartz-community/footer enabled: true options: links: GitHub: https://github.com/jackyzha0/quartz Discord Community: https://discord.gg/cRFFHYye7t layout: position: footer priority: 50 layout: groups: toolbar: direction: row gap: 0.5rem byPageType: content: {} folder: exclude: - reader-mode positions: right: [] tag: exclude: - reader-mode positions: right: [] 404: positions: beforeBody: [] left: [] right: []position 与 priority 的底层处理从源码看布局的组装发生在 config-loader.ts 的buildLayoutForEntries函数中其核心逻辑是遍历所有启用的插件条目只处理带有layout声明的插件通过componentRegistry查找到注册的组件若组件是构造函数则实例化并通过注册表缓存避免跨页面类型重复实例化若声明了display或condition依次套上MobileOnly/DesktopOnly或ConditionalRender包装按position分桶后以priority从小到大排序——数值越小越靠前/越靠上排序完成后调用resolveGroups把同组组件合并为 Flex 容器详见下节。需要注意如果插件没有显式声明layout布局系统会回退读取插件 manifest 中的defaultPosition/defaultPriority默认值 50自动放置见 config-loader.ts。这一点在 quartz.config.default.yaml 中也能印证——例如explorer声明position: left, priority: 50而table-of-contents声明position: right, priority: 30。使用 Flex 分组把多个组件排成一行/一列顶层layout.groups定义flex 容器如toolbar把多个组件组合到同一行或同一列。这是实现搜索框 暗色模式 阅读模式这类顶栏/工具栏布局的标准手段。YAML 侧的完整用法plugins: - source: github:quartz-community/search enabled: true layout: position: left priority: 20 group: toolbar groupOptions: grow: true # Search will grow to fill available space - source: github:quartz-community/darkmode enabled: true layout: position: left priority: 30 group: toolbar # Darkmode keeps its natural size - source: github:quartz-community/reader-mode enabled: true layout: position: left priority: 35 group: toolbar layout: groups: toolbar: direction: row gap: 0.5rem每个插件条目上的groupOptions字段支持以下 flex 子项属性选项类型说明growboolean组件是否增长以填满可用空间shrinkboolean组件在需要时是否收缩basisstring组件的初始主轴尺寸如200pxordernumber在 flex 容器中的排序alignstart|end|center|stretch交叉轴对齐justifystart|end|center|between|around主轴对齐顶层layout.groups段配置 flex 容器本身选项类型说明directionrow|row-reverse|column|column-reverseflex 方向wrapnowrap|wrap|wrap-reverseflex 换行行为gapstring子项间距如0.5remlayout.groups还支持一个文档中未展开但默认配置实际用到的字段priority——例如 quartz.config.default.yaml 中toolbar组声明了priority: 35。从 config-loader.ts 的resolveGroups实现看组的有效优先级遵循显式配置的组优先级 第一个成员的优先级规则这样可以把整个组作为一个整体参与同位置组件的排序。组件的实际渲染resolveGroups会把同组的成员打包成一个Flex组件。底层实现在 Flex.tsx渲染一个带flex-component类的容器 div内联写入flex-direction、flex-wrap、gap样式每个子组件再套一层包裹 div写入flex-grow、flex-shrink、flex-basis、order、align-self、justify-self。未显式指定的属性有默认值grow默认 0不增长、shrink默认 1可收缩、basis默认auto、order默认 0、align/justify默认center。Flex还会通过concatenateResources合并所有子组件的afterDOMLoaded、beforeDOMLoaded与css资源保证功能与样式不丢失。[!note] 覆盖 Flex 默认样式Flex内组件会获得额外的 CSS 类flex-component其自带display: flex属性。如需覆盖可在自定义 CSS 中给组件类添加display属性.flex-component { display: block; // 或任意其他 display 类型 }按页面类型定制布局byPageType顶层layout.byPageType提供按页面类型content、folder、tag、404 等的布局覆盖作用于beforeBody、left、right三个槽位并可选通过template字段控制页面的 Page Frame。以 quartz.config.default.yaml 的实际配置为例layout: byPageType: 404: positions: beforeBody: [] left: [] right: [] content: {} folder: exclude: - reader-mode positions: right: [] tag: exclude: - reader-mode positions: right: [] canvas: {} bases: {}其中有两个关键语义对应 config-loader.ts 的处理逻辑exclude从该页面类型中排除指定插件按插件名匹配例如folder/tag页面排除reader-mode。positions中的空数组表示清空该槽位例如404页面把beforeBody、left、right全部置空与minimalframe 配合形成极简的 404 页面。byPageType也允许覆盖template见下文 Page Frames例如layout: byPageType: canvas: template: minimal条件渲染让组件按需出现插件可以在layout块中通过condition字段控制自己何时出现使用内置条件预设plugins: - source: github:quartz-community/breadcrumbs enabled: true layout: position: beforeBody priority: 5 condition: not-index内置条件如下条件效果not-index在根 index 页隐藏其余页面显示has-tags仅在 frontmatter 中带 tags 的页面显示has-backlinks仅在存在反链的页面显示has-toc仅在存在目录table of contents的页面显示[!note] 前两个条件出现在 docs/layout.md 中has-backlinks与has-toc两个预设可以在 conditions.ts 的builtinConditions中确认——它们分别检查fileData.backlinks与fileData.toc是否为非空数组。条件求值的底层机制applyConditionWrapper通过getCondition(conditionName)查找预设找不到时打印警告并让组件始终渲染见 config-loader.ts。ConditionalRender组件本身只是对condition(props)的布尔判断为真渲染子组件为假返回null见 ConditionalRender.tsx。内置响应式组件MobileOnly 与 DesktopOnly除了condition插件还可以通过display属性控制可见屏幕plugins: - source: github:quartz-community/table-of-contents enabled: true layout: position: right priority: 20 display: desktop-only # 仅在桌面端可见值说明all所有屏幕尺寸可见默认mobile-only仅在移动设备可见desktop-only仅在桌面设备可见其实现位于 MobileOnly.tsx 与 DesktopOnly.tsx它们把子组件包进带mobile-only/desktop-only类的 div由 CSS 媒体查询控制显隐同时透传afterDOMLoaded、beforeDOMLoaded与css资源。display属性在 config-loader.ts 中通过applyDisplayWrapper统一处理all视为无需包装。quartz.config.default.yaml 中spacer插件就是display: mobile-only的实际用例——它只在移动端插入一个空白占位。通过 TypeScript 覆盖quartz.ts实现高级布局对于需要自定义组件包装或复杂条件逻辑的高级场景可以在quartz.ts中使用 TypeScript 覆盖布局import { loadQuartzConfig, loadQuartzLayout } from ./quartz/plugins/loader/config-loader const config await loadQuartzConfig() export default config export const layout await loadQuartzLayout({ defaults: { // override default layout for all page types }, byPageType: { content: { // override layout for content pages only }, folder: { // override layout for folder pages only }, }, })defaults中定义的字段可以被byPageType中更具体的条目覆盖。从源码看loadQuartzLayout会把 YAML 解析出的默认布局与覆盖项合并mergedDefaults合并layoutOverrides?.defaultsmergedByPageType对每个页面类型逐项展开合并config-loader.ts并且所有byPageType条目都会自动继承结构槽位head、header、footer确保任意页面类型都有完整的页面外壳。在 TS 中使用 Flex / MobileOnly / DesktopOnly / ConditionalRenderFlex的 TS 写法Component.Flex({ components: [ { Component: Plugin.Search(), grow: true, // Search will grow to fill available space }, { Component: Plugin.Darkmode() }, // Darkmode keeps its natural size ], direction: row, gap: 1rem, })type FlexConfig { components: { Component: QuartzComponent grow?: boolean shrink?: boolean basis?: string order?: number align?: start | end | center | stretch justify?: start | end | center | between | around }[] direction?: row | row-reverse | column | column-reverse wrap?: nowrap | wrap | wrap-reverse gap?: string }响应式包装的 TS 写法Component.MobileOnly(Component.Spacer())Component.DesktopOnly(Plugin.TableOfContents())自定义条件逻辑的 TS 写法Component.ConditionalRender({ component: Plugin.Search(), condition: (props) props.displayClass ! fullpage, })type ConditionalRenderConfig { component: QuartzComponent condition: (props: QuartzComponentProps) boolean }[!tip] 你还可以在插件的初始化代码中调用registerCondition()注册自定义条件以便在 YAML 中直接使用见 conditions.ts 的registerCondition实现自定义条件优先于内置条件匹配。关于插件开发与自定义组件的更多细节可参考 docs/advanced/making plugins.md 与 docs/advanced/creating components.md。社区组件插件的安装命令为npx quartz plugin add github:quartz-community/name更多内置布局工具Flex、MobileOnly、DesktopOnly等可查阅 docs/layout-components.md。Page Frames控制页面的整体 HTML 骨架Page Frame控制页面的整体 HTML 结构——具体来说是布局槽位侧栏、页头、内容、页脚如何在页面外壳shell内排列。不同类型的页面可以使用不同的 frame从而产出截然不同的布局形态。内置的三种 FrameQuartz 内置三种 frame注册于 frames/index.tsFrame描述使用方default三栏布局左侧栏、居中内容header、beforeBody、content、afterBody、右侧栏与页脚即标准 Quartz 布局ContentPage、FolderPage、TagPage、BasesPagefull-width无侧栏。单居中列横跨全宽包含 header、content、afterBody 与 footer—minimal无侧栏、无 header 或 beforeBody 装饰。仅内容与 footerNotFoundPage404插件也可以提供自己的 frame。例如canvas-page插件自带canvasframe提供带可切换侧栏的全屏画布。PageFrame接口定义在 frames/types.ts每个 frame 有一个唯一name、一个接收PageFrameProps包含全部槽位组件与共享componentData的render函数以及可选的css。DefaultFrame的渲染结构左侧栏 → 中心区 → 右侧栏 → 页脚即是经典的 Quartz 三栏布局见 DefaultFrame.tsx。Frame 的解析顺序每种页面类型可以在插件源码中通过frame属性声明默认 frame。解析顺序为YAML 配置覆盖layout.byPageType.name.template在quartz.config.yaml中插件注册的 frame插件通过 Frame Registry 注册的 frame从插件的frames导出加载插件声明页面类型插件源码中设置的frame属性回退default例如将 canvas 页面覆盖为 minimal framelayout: byPageType: canvas: template: minimal从源码看该解析逻辑在resolveFrame(name)中实现frames/index.ts先检查插件注册表frameRegistry再查内置 frame若未知则打印警告并回退到DefaultFrame。最终 frame 的 name 会作为data-frame属性写入页面根元素并在运行时应用 frame 的 CSS 与渲染函数见 renderPage.tsx。自定义 Frame 的两种方式方式一插件提供 frame推荐用于可复用 frame插件可以在package.json中声明 frame并从./frames子路径导出它们。插件安装后其 frame 会自动注册进 Frame Registry并可按名字使用详见 docs/advanced/making plugins.md。注册表实现见 frames/registry.ts同名 frame 被不同来源重复注册时会打印覆盖警告。方式二核心 frame用于项目专属 frame你也可以直接在quartz/components/frames/中创建 frame——实现PageFrame接口并在quartz/components/frames/index.ts中注册。完整PageFrame接口可参考 docs/advanced/architecture.md。用 CSS 定位 FrameFrame 会作为data-frame属性应用到.page元素上可以直接在 CSS 中定位.page[data-framemy-frame] #quartz-body { /* custom grid layout */ }Frame 的 CSS 应使用[data-framename]选择器进行作用域隔离避免与其他 frame 冲突。实际上 Quartz 的网格布局正是这么工作的——renderPage.tsx会把 frame 的css注入style标签并在#quartz-root根元素上设置data-frame属性。布局断点Breakpoints与响应式Quartz 会根据屏幕宽度切换不同的布局mobile屏幕宽度低于该值使用移动端布局desktop屏幕宽度高于该值使用桌面端布局介于mobile与desktop之间使用平板布局断点可以在quartz/styles/variables.scss中配置$breakpoints: ( mobile: 800px, desktop: 1200px, );默认值定义于 variables.scss并据此推导出媒体查询$mobile为max-width: 800px$tablet为800px ~ 1200px区间$desktop为min-width: 1200px。同文件还定义了三种断点下的 CSS Grid 模板$mobileGrid、$tabletGrid、$desktopGrid可以看到侧栏宽度固定为 320px$sidePanelWidth桌面端为左栏 内容 右栏三列网格移动端则把左右侧栏、页头、内容、页脚堆叠为单列这正对应本文开头三张预览图展示的布局差异。样式定制大多数有意义的样式修改如配色方案与字体都可以直接通过通用配置完成。如果需要更深入的样式改动可以编写自定义样式。Quartz 使用 Sass 进行样式处理。基础样式表位于quartz/styles/base.scss你自己的样式写在quartz/styles/custom.scss中。[!note] 有些组件自带样式社区插件会打包它们自己的样式。如果想定制某个组件的样式请先查看组件定义确认其样式是如何定义的——例如Flex组件的.flex-component类、MobileOnly的.mobile-only类都对应各自的默认规则覆盖时需保持选择器优先级与作用域正确。小结Quartz 5 的布局系统是一套层次清晰的组合机制槽位Section定义放哪positionpriority定义组件去哪、排第几layout.groups定义怎么排成一行byPageType定义哪些页面特殊Page Frame 定义整个骨架长什么样最后通过断点与 Sass 变量控制响应式表现。无论是仅改quartz.config.yaml的纯配置玩法还是通过quartz.ts的 TypeScript 覆盖实现完全自定义这套机制都能在不修改 Quartz 核心代码的前提下满足需求。相关参考资源docs/layout.md本文依据、docs/layout-components.md布局工具组件、quartz/cfg.ts布局类型定义、quartz/plugins/loader/config-loader.ts布局组装实现、quartz.config.default.yaml默认布局示例。【免费下载链接】quartz a fast, batteries-included static-site generator that transforms Markdown content into fully functional websites项目地址: https://gitcode.com/GitHub_Trending/qua/quartz创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表