ToolJet 自定义样式(Custom Styles)实战指南:用工作区级 CSS 统一所有应用的组件外观
2026/9/12 16:28:53 网站建设 项目流程

ToolJet 自定义样式(Custom Styles)实战指南:用工作区级 CSS 统一所有应用的组件外观

【免费下载链接】ToolJetOpen-source foundation of ToolJet AI - the enterprise app generation platform for internal tools, dashboards, business applications, workflows and AI agents. Build visually, from a prompt, or from Claude Code, Codex and Cursor over MCP 🚀项目地址: https://gitcode.com/GitHub_Trending/to/ToolJet

ToolJet 的自定义样式(Custom Styles)功能允许你在工作区(Workspace)级别注入自己的 CSS,覆盖组件的默认样式,从而让团队创建的所有应用共享一套统一、可品牌的视觉主题。本文将先带你从 Workspace Settings 中的 Custom Styles 页面完成全局与单组件两级样式定制,再结合 ToolJet 前端渲染器与后端存储的源码实现,解释_tooljet-<component>类名的生成机制、样式的作用域与持久化方式,帮助你从"会配"进阶到"懂原理"。

功能定位:一个付费特性,解决跨应用主题一致性问题

在 ToolJet 中,每次新建应用时手动逐个调整组件颜色与字体既重复又容易产生视觉偏差。Custom Styles 的设计目标正是解决这一痛点:

  • 一次编写,处处生效:在 Workspace Settings 中写入的 CSS 会作用于该工作区下所有应用的组件默认样式;
  • 保持主题一致性:通过标准化样式避免不同应用之间出现观感割裂,提升视觉连贯性与用户体验;
  • 减少重复劳动:开发者无需为每个新应用重复配置组件样式,从而提高开发效率。

从官方文档标注的 "Paid feature"(付费特性)徽标可以看出,该功能属于 ToolJet 的商业化能力,仅对付费用户开放。

工作原理:类名注入 + 样式持久化

在动手写 CSS 之前,先理解两个关键机制,这会让你后面的每个选择器都写得更自信。

1. 画布组件自动携带两个类名

在 ToolJet 前端渲染器中,每个组件渲染时都会被自动挂载两个类名。源码位于 frontend/src/AppBuilder/AppCanvas/RenderWidget.jsx:

const innerWidgetClassName = [ 'canvas-component', inCanvas && `_tooljet-${component?.component} _tooljet-${component?.name}`, isDisabledOrLoading && 'disabled', userCssClass, ] .filter(Boolean) .join(' ');

从中可以读出两个重要事实:

  • _tooljet-${component?.component}component字段是组件类型,因此会生成类似_tooljet-Button_tooljet-Table_tooljet-TextInput的类名——这就是文档中"全局组件类名"的来源;
  • _tooljet-${component?.name}name是你在画布上给具体组件起的名称,生成类似_tooljet-addIncomeButton的类名——这就是文档中"单个组件类名"的来源。

也就是说,同一个组件实例会同时拥有类型类名与实例类名,你可以据此选择是"改一批"还是"改一个"。

2. 样式以工作区为单位持久化在服务端

自定义样式并非存储在浏览器本地,而是通过 REST API 保存到服务端数据库。服务端实体定义在 server/src/entities/custom_styles.entity.ts,对应custom_styles表,关键字段包括:

字段说明
idUUID 主键
styles用户写入的 CSS 文本
organization_id工作区 ID,带唯一约束(一个工作区一份样式)
scope作用域枚举:instance(实例级)或workspace(工作区级),默认workspace
created_at/updated_at创建与更新时间

前端请求层封装在 frontend/src/_services/custom_styles.service.js,对外暴露四个方法:

  • save(body)POST /custom-styles,保存工作区样式;
  • get()GET /custom-styles,获取工作区样式;
  • getForAppViewerEditor()GET /custom-styles/app,供应用编辑器/查看器读取样式;
  • getForPublicApp(slug)GET /custom-styles/:slug,供公开分享的应用读取样式。

对应的路由定义在 server/src/modules/custom-styles/controller.ts。应用在加载时(见 frontend/src/AppBuilder/_hooks/useAppData.js)会调用这些接口拉取样式并注入页面,因此编辑器、查看器与公开分享页面都能保持一致外观。

另外值得一提的是,Renderer 中还有一处hasCustomStyling的许可证门控(frontend/src/AppBuilder/AppCanvas/RenderWidget.jsx),它与cssClass属性相关——即组件级自定义 CSS 类同样受付费能力控制,从侧面印证了 Custom Styles 整体是许可证(License)控制的功能。

第一步:进入 Custom Styles 页面

操作路径非常直接:

  1. 登录 ToolJet 并进入仪表盘;
  2. 点击侧边栏或右上角的Workspace Settings
  3. 在设置页中找到并进入Custom Styles页面。

在该页面中你会看到一个 CSS 编辑区域,后续所有全局与单组件样式都写在这里并保存生效。

全局定制:让一类组件统一换肤

规则一:使用组件类型类名_tooljet-<component>

要修改某类组件的默认颜色,直接使用它的类型类名即可,格式为_tooljet-<component>。例如 Button 组件的类型类名就是_tooljet-Button

规则二:用浏览器检查器定位子类与 HTML 标签

类型类名通常挂在组件最外层容器上,而具体要修改的属性(如按钮文字颜色、输入框标签字号)往往藏在组件的子类或内部 HTML 标签里。此时需要借助浏览器开发者工具(Inspector):

  • 右键目标元素 → 检查;
  • 在 DOM 树中逐层展开,找到目标属性的对应子类或 HTML 标签。

实战示例一:修改 Button 背景色

找到 Button 组件内部的<button>标签后,在 Custom Styles 区域写入:

._tooljet-Button button { background-color: #152A65 !important; }

保存后画布上所有 Button 组件的背景色都会变为深蓝色#152A65

实战示例二:修改 Table 组件 Filter 按钮背景色

Table 组件的 Filter 按钮位于表头区域,对应子类为.table-card-header,其内部同样是<button>标签:

._tooljet-Table .table-card-header button { background-color: #152A65 !important; }

这条规则只作用于 Table 表头中的 Filter 按钮,不会影响页面上的其他普通按钮。

实战示例三:修改 Text Input 与 Number Input 的标签样式

输入类组件的标签渲染为<p>标签,因此通过._tooljet-TextInput p._tooljet-NumberInput p即可同时调整标签的颜色、字号与字重:

._tooljet-TextInput p { color: #152A65 !important; font-size: 16px !important; font-weight: bold !important; } ._tooljet-NumberInput p { color: #152A65 !important; font-size: 16px !important; font-weight: bold !important; }

这样所有文本输入框与数字输入框的标签都会呈现统一的加粗深蓝样式。

单组件定制:只改某一个组件

当你不希望影响整类组件、只想单独美化画布上的某一个组件时,使用该组件的实例类名,格式为_tooljet-<component_name>,其中component_name是在应用中为组件设置的名称。

例如在画布上把一个 Button 命名为addIncomeButton,它的实例类名就是_tooljet-addIncomeButton

对应的样式如下,背景色会变为蓝色:

._tooljet-addIncomeButton button { background-color: blue !important; }

可以看到与全局示例的结构完全一致,只是把类型类名换成了实例类名。

进阶建议与注意事项

  1. !important的使用:组件默认样式通常来自组件自身的 SCSS,优先级不低;官方示例中统一使用!important确保覆盖生效。建议在自定义样式中保持同样的写法,并在全局维护一份统一的品牌色/字体变量,避免散落硬编码。
  2. 选择器粒度选择:全局样式写在_tooljet-<component>下会作用于工作区所有应用中的所有同类组件,适合品牌主题;单组件样式写在_tooljet-<component_name>下,适合报表、看板等特殊页面的局部强调。二者可同时使用,实例类名写法更具体,可以覆盖更粗粒度的全局规则。
  3. 作用域与团队协作:样式保存在custom_styles表中并与工作区一一对应(organization_id唯一),意味着同一个团队的所有成员打开应用时都会看到相同的自定义外观;scope字段还支持instance级作用域,可在需要时覆盖整个实例的默认外观。
  4. 排查技巧:如果某条规则没有生效,先用浏览器检查器确认目标组件的最外层类名是否确实以_tooljet-开头、子元素选择器是否命中,并检查 Custom Styles 页面是否已保存成功(保存对应POST /custom-styles请求)。

总结

Custom Styles 让 ToolJet 用户摆脱逐组件手改样式的重复劳动:全局定制解决"品牌一致性",单组件定制解决"局部差异化"。其底层机制清晰可见——前端渲染器在 RenderWidget.jsx 中为每个组件自动注入_tooljet-<类型>_tooljet-<名称>两类选择器,后端通过 custom_styles.entity.ts 与 custom_styles.service.js 完成样式的工作区级持久化与按需分发。掌握这套类名体系,你就能用标准 CSS 高效地打造出观感统一、品牌鲜明、可规模复用的 ToolJet 应用集群。

【免费下载链接】ToolJetOpen-source foundation of ToolJet AI - the enterprise app generation platform for internal tools, dashboards, business applications, workflows and AI agents. Build visually, from a prompt, or from Claude Code, Codex and Cursor over MCP 🚀项目地址: https://gitcode.com/GitHub_Trending/to/ToolJet

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询