所以,你对为 Discourse 设计自己的主题感兴趣?那你来对地方了:smile:
本指南将更侧重于在 Discourse 中处理主题的 SCSS/CSS 方面。如果你也熟悉 JS/EmberJs/Handlebars,你可以通过查看这份指南深入探索。
我将向你介绍我在 Discourse 中设计和主题化的个人方法。就像大多数事情一样,实现自己的设计有很多方式。我非常喜欢在使用 Inspector 工具时进行主题创作,并会在本文中向你展示几次我是如何做的。
主题设置准备
在继续之前,请先阅读 Discourse 主题使用入门指南 以及 主题结构…。此时不需要深入的知识,但这些文章会让你在开始之前对相关内容有更熟悉的感觉。
为了在 Discourse 中更好地进行主题设计,我建议进行以下设置,以提供最快、最流畅的设计流程。这些步骤将使你能够在进行修改时实时查看变化,而无需从 Discourse 站点管理面板“保存”并刷新。
完全可以通过管理控制台来完成本指南(前提是你拥有 Discourse 论坛的管理员权限。)
- 安装 Discourse Theme CLI 并阅读该主题以了解其功能。
- 从 https://discourse.theme-creator.io/ 获取 API 密钥
- 使用你的 Meta 账户登录
- 点击 我的主题
- 点击 API 密钥
- 在弹出的模态框中,点击 生成 API 密钥 并复制为你生成的密钥(稍后我们会用到)
运行 Discourse Theme CLI
安装好 Discourse Theme CLI 并准备好 API 密钥后,打开你喜欢的文本编辑器或终端窗口,将工作目录更改为你希望设置主题文件夹的位置。
到达后,运行以下命令 discourse_theme new your_theme_name,并按如下方式填写提示:
-
你想给主题起什么名字? 选择你的主题名称
-
你想开始监控这个主题吗? 是
-
你的 Discourse 站点的根 URL 是什么?
https://discourse.theme-creator.io/ -
你想将此站点名称存储…? 是
-
你的 API 密钥是什么? 输入你从主题生成器获取的 API 密钥
-
你想将此 API 密钥存储…? 是
-
当提示时,选择 创建并与新主题同步
-
当提示关于子主题组件时,选择 不操作
如果一切正常,你现在应该能够导航到 https://discourse.theme-creator.io/ 上的“我的主题”,并在左侧的主题列表中看到你的新主题。
要实时查看这些更改,点击你的主题名称,然后在信息区域底部点击 预览
Theme CLI 现在也在监控新创建目录中的任何更改,并会在每次更改时保存以及更新 theme-creator 上的主题。
第一步
Discourse Theme CLI 已在我们之前命令中指定的文件夹名称内为我们创建了主题脚手架。生成了很多我们不会使用的文件,因此我们将删除除以下内容之外的所有内容:
common/common.scss
desktop/desktop.scss
mobile/mobile.scss
about.json
在目录内,同时也运行 rm -rf .git 以移除 git 版本跟踪,本指南不需要它。
你的主题目录现在应该看起来像这样:
值得注意的是,添加到这些文件中的样式将在其各自的用例中呈现。common.scss 中的样式将应用于桌面端和移动端,而 desktop.scss 中的样式仅应用于桌面浏览,mobile.scss 中的样式仅应用于移动端视图。
Hello World(彩色版)
Discourse 使用 SCSS 进行样式设计,因此为了最好地利用样式,你可能想熟悉一下 SASS,但如果不熟悉,你仍然可以跟随本指南进行。
好的,现在让我们进入大家期待已久的内容……主题化!
目前,我们的 about.json 尚未定义任何 color_schemes,因此请将以下代码粘贴到该部分中然后保存。
{
"name": "my theme",
"about_url": null,
"license_url": null,
"assets": {},
"color_schemes": {
"Default": {
"primary": "222222",
"secondary": "ffffff",
"tertiary": "0088cc",
"quaternary": "e45735",
"header_background": "ffffff",
"header_primary": "333333",
"highlight": "ffff4d",
"danger": "e45735",
"success": "009900",
"love": "fa6c8d"
}
}
}
如果你打开了浏览器,你可能不会看到任何变化生效,因为这是在没有方案时使用的默认配色方案。
主题概览
为了在本指南中实际实现一些内容,我将带你基于这个配色方案创建一个简单的主题。

更改背景色 + 主文本颜色
让我们做一些非常简单的事情。我们将更改当前配色方案的 "Secondary" 值。将其更改为 "secondary": "EEF4F7"(这将更改背景颜色)。我们还将 "primary" 值更改为 "203243"。
仅凭这一行,我们就已经改变了论坛的外观和感觉。仅通过编辑配色方案中的颜色就可以完成大量自定义。
配色方案的使用
以下所有键都在 about.json 文件中根据相应的配色方案名称定义。这些描述是很好的参考,可以帮助你理解每个变量名称的主要用途:
| 颜色 | 描述 |
|---|---|
| primary | 大多数文本、图标和边框 |
| secondary | 主背景色以及某些按钮的文本颜色 |
| tertiary | 链接、某些按钮、通知和强调色 |
| quaternary | 导航链接 |
| header_background | 站点标题的背景色 |
| header_primary | 站点标题中的文本和图标 |
| highlight | 页面上高亮元素的背景色,例如帖子和主题 |
| danger | 删除帖子和主题等操作的强调色 |
| success | 用于指示操作成功 |
| love | 点赞按钮的颜色 |
这些变量中的每一个都可以像这样在我们的 SCSS 文件中使用。
body {
background-color: var(--primary);
}
每种颜色的其他版本也已创建供我们使用。诸如 var(--primary-medium) 或 var(--primary-very-low) 之类的东西可用于获取同一颜色的不同色调。
让我们将“Default”配色方案中的其他颜色更改为与此匹配:
"Default": {
"primary": "203243",
"secondary": "EEF4F7",
"tertiary": "416376",
"quaternary": "5E99B9",
"header_background": "FaFaFa",
"header_primary": "EEF4F7",
"highlight": "86BDDB",
"danger": "8F393E",
"success": "70DB82",
"love": "FC94CB"
}
如果你在 theme creator 上预览主题时点击 样式指南 链接,然后在左侧菜单中点击“颜色”,你可以看到所有可用于 SCSS 文件的变量。
样式指南是创建自定义主题时查看的非常有用的部分。每个 Atom 都会向你展示应用你的样式后 Discourse 的某些元素将如何显示。
深入探索
有了上一部分的内容,我认为现在是时候更深入地了解仅使用 SCSS 在 Discourse 中可以做什么了。(提示:很多!)
样式化标题
你会注意到,我们对配色方案的先前更改使我们的标题有些不尽如人意。图标几乎看不见!
![]()
Discourse 标题包含一个容器(带有背景色),用于容纳站点徽标以及右侧的导航图标。所有这些都可以自定义。
自定义标题的目标类是 .d-header。
在我们的 common/common.scss 文件中,添加以下内容:
.d-header {
box-shadow: none;
border-bottom: 1px solid var(--primary-low-mid);
height: 5em;
}
这将移除标题的默认 box-shadow,增加一点高度,并设置 border-bottom 以提供一些分隔。
对于图标——在 .d-header SCSS 括号内,让我们添加以下嵌套代码。
.d-header {
// ...之前的代码
.d-icon {
color: var(--primary-low-mid);
}
}
看起来不错,但敏锐的眼睛会注意到增加的标题高度使它与其余 Discourse 论坛元素之间的空间变少了!
主区域和标题之间的间距由 #main-outlet 目标控制。让我们通过在 common/common.scss 文件底部添加以下内容来稍微增加这个间距。
#main-outlet {
padding-top: 6.5em;
}
导航容器
导航容器包含以下部分。
![]()
最左侧区域是分类/标签筛选下拉菜单,接着是导航链接,最后是“新主题”按钮。
分类 / 标签下拉菜单
让我们对这个区域做一些更改。为此,将以下内容添加到你的 common.scss 文件中。
.navigation-container {
.select-kit.combo-box {
.select-kit-header {
border-radius: 0.9em;
background-color: var(--header_background);
}
}
}
在这里,我们针对 .select-kit-header 以给它们相同的 border-radius,以及更浅的背景色。
点击其中任何一个,都会打开一个下拉菜单。
目前,它也有硬角,所以让我们添加一些样式来将它们圆角化,并将背景色更改为与标题相同。
.navigation-container {
.select-kit.combo-box {
// ...之前的代码
&.category-drop,
&.tag-drop {
.select-kit-body {
border-radius: 0.9em;
background-color: var(--header_background);
.select-kit-collection {
background-color: var(--header_background);
border-top-left-radius: 0px;
border-top-right-radius: 0px;
}
}
}
}
}
结果如下所示…
如果你仔细观察,你会发现我们的更改在搜索区域的右上角留下了一条可见的小边框。
让我们通过在浏览器 Inspector 中查看来修复这个问题。这始终是一个超级有用的工具,用于学习我们需要针对哪些类/ID 以正确应用样式。
当下拉菜单可见时,右键点击搜索区域并在浏览器中“检查”该元素。
我们可以看到该输入位于一个具有 select-kit-filter 类的 div 内。
如果我们查看应用于此选择器的规则,我们可以看到它目前具有 border-top 和 border-bottom,以及一些应用的 padding。我们只想更改 border-top 样式。
将以下代码嵌套到之前的 .select-kit-body scss 中。
.select-kit.combo-box.category-drop,
.select-kit.combo-box.tag-drop {
.select-kit-body {
// ...之前的代码
.select-kit-filter {
border-top: 0px;
}
}
}
这样,我们用于样式化导航容器的代码应该如下所示。
.navigation-container {
// 分类 + 标签下拉菜单
.select-kit.combo-box {
.select-kit-header {
border-radius: 0.9em;
background-color: var(--header_background);
}
&.category-drop,
&.tag-drop {
.select-kit-body {
border-radius: 0.9em;
background-color: var(--header_background);
.select-kit-collection {
background-color: var(--header_background);
border-top-left-radius: 0px;
border-top-right-radius: 0px;
}
.select-kit-filter {
border-top: 0px;
}
}
}
}
}
导航链接
让我们添加一些样式,使这些导航链接看起来类似于此:
![]()
让我们再次使用 Inspector 来发现我们应该针对什么。
我们可以看到我们的导航元素位于一个具有 "nav nav-pills ..." 类的 UL 内。
回到我们的 common.scss 文件,在上一部分之下,但仍嵌套在 navigation-container 内,让我们添加以下内容:
.nav-pills {
& > li a {
&.active {
color: var(--tertiary);
background-color: var(--secondary);
border-bottom: 4px solid var(--tertiary);
}
}
}
此更改将仅针对具有 active 类且是 nav-pills 子项的链接。此更改应使我们的活动链接看起来像这样:
![]()
这还可以,但我希望底部边框仅延伸到文本长度。为此,在 &.active { 行之上,让我们添加以下内容,这将影响导航 <li> 标签内的所有 A 链接。
// ...其他代码
.nav-pills {
& > li a {
padding: 0;
margin-right: 20px;
color: var(--tertiary-high);
border-bottom: 4px solid transparent;
&.active {
// ...更多代码
}
}
}
现在,我们需要将“悬停”效果样式化为与“活动”效果相同。
在我们之前的 &.active 下添加
:hover {
color: var(--tertiary);
background-color: var(--secondary);
border-bottom: 4px solid var(--primary);
}
因此,我们所有的导航代码现在应该如下所示:
// Nav Pills
.nav-pills {
& > li a {
padding: 0;
margin-right: 20px;
color: var(--tertiary-high);
border-bottom: 4px solid transparent;
&.active {
color: var(--tertiary);
background-color: var(--secondary);
border-bottom: 4px solid var(--tertiary);
}
&:hover {
color: var(--tertiary);
background-color: var(--secondary);
border-bottom: 4px solid var(--primary);
}
}
}
按钮
Discourse 中的按钮有多种形状和大小。你可以在样式指南的“按钮”部分查看它们的 assortment。
我想将此主题上的大多数按钮更改为圆角并带有自定义样式。这将更改 + 新主题 按钮以及站点中的其他按钮。
在我们的 common.scss 文件底部,让我们添加以下内容:
.btn {
background-color: var(--header_background);
color: var(--primary);
border-radius: 1.2em;
border: 1px solid var(--primary-low-mid);
.d-icon {
color: var(--primary);
}
&:hover {
background-color: var(--quaternary-low);
color: var(--primary);
.d-icon {
color: var(--primary);
}
}
&.btn-default,
&.btn-primary {
padding: 10px 12px;
}
}
这将使我们的按钮看起来像这样:

现在我们的按钮已经样式化,我想指出关于按钮样式化的一点,以及为什么测试所有设计很重要。
前往你的站点预览中的某个主题,然后点击主题回复上的 回复 按钮,或者主题流底部的回复按钮。你会看到我们的按钮样式化影响了一些我们可能没想到的东西。
我不希望这些文本编辑按钮受到我先前样式化的影响。这需要更复杂的 SASS/CSS,但我们可以让代码 :not() 影响这些按钮。![]()
让我们在当前的 .btn 目标之前添加这一行代码。这将告诉我们的样式仅应用于不是 .d-editor-button-bar 子项的按钮。
:not(.d-editor-button-bar) > .btn
好的,这工作得很好……但是等等!现在有一个奇怪的叛逆者在做自己的事情。
![]()
在浏览器中检查它,我可以看到这个按钮有一个 .select-kit-header 类,因为点击这个齿轮后,会显示更多选项。
我无法强调在创建 Discourse 主题时使用浏览器 Inspector 工具的重要性。它们是你旅途中最好的朋友。
既然我们知道我们_不_想针对这个按钮,让我们为我们的代码添加更多 :not() 功能。
:not(.d-editor-button-bar) >
.btn:not(.single-select-header)
这将选择所有不是 .d-editor-button-bar 子项且没有 .single-select-header 类的按钮。我知道这有点令人困惑,但在 Discourse 内部,有很多移动部件,所以有时样式需要非常具体才能正确影响元素。
我还注意到,我们当前的样式化以尴尬的方式影响了模态关闭按钮。点击任何弹出模态框的内容,你就可以看到这一点,或者更简单地说,我们可以导航到样式指南的模态框部分。
为了解决这个问题,我将为我们的代码添加另一个目标。
:not(.d-editor-button-bar) >
.btn:not(.single-select-header):not(.modal-close)
继续…
我看到还有一个按钮似乎没有受到我们代码的影响。它是位于主题帖子流最底部的 Tracking 按钮。

我将在当前 .btn 代码的逗号后添加以下行。
:not(.d-editor-button-bar) >
.btn:not(.single-select-header):not(.modal-close),
.topic-notifications-button > .select-kit > .btn
这将正确针对出现在此部分的按钮,现在,我们完成了论坛顶部区域的样式化。
请随意调整你自己的 css 中的任何参数。你越尝试这些样式并观察它们如何影响 html,你就会学到越多!
接下来去哪里
本指南旨在让你初步了解如何为 Discourse 自定义自己的主题。我希望你现在对如何针对应用程序的区域进行自定义有了更多了解。
记住 许多事情仅使用 SCSS 就可以自定义。如果你想更深入地进行开发,我推荐阅读本文顶部链接的文章。
随时提出任何问题,我很乐意尝试帮助你,或为你指明正确的方向。
本文档受版本控制 - 建议更改 在 github 上。










