css - 如何根据rails中的用户设置动态更改tailwind-config.js
问题描述
我有一个 Rails 6 应用程序设置为使用带有 Webpacker 的Tailwind CSS,类似于它在这个 GoRails 教程中的完成方式。
我希望能够根据控制器和操作动态更改 Tailwind 默认值,以便用户通过选择一些选项来“皮肤”网站的各个部分,然后动态调整一些 Tailwind 配置选项。(如何使用此功能的一个示例是用户登录到网站的管理区域,更改他们的字体系列和背景颜色以匹配他们的品牌。)
我不能只根据条件将样式表添加到布局中,因为我必须覆盖我想要更改的 Tailwind css 变量的所有实例(例如“sans-serif”)。随着 Tailwind 的发展,这将是大量的工作和脆弱的维护。
如果有一种方法可以将用户选择的选项动态插入到 Tailwind 配置文件 ( /javascript/stylesheets/tailwindcss-config.js ) 中,那将是理想的,但我不确定如何执行此操作。
在使用 Tailwind 时,还有更好的方法在 Rails 中执行此操作吗?似乎应该有某种方法可以使用控制器中的 Javascript 来动态更改我的 tailwindcss-config.js 中的设置(此处解释了Tailwind 配置文件)。因此,该文件中的内容如下:
theme: {
fontFamily: {
display: ['Gilroy', 'sans-serif'],
body: ['Graphik', 'sans-serif'],
},
在 Tailwind 中硬编码为配置的字体堆栈将变为:
theme: {
fontFamily: {
display: DYNAMICALLY INSERTED FONT STACK,
body: ANOTHER DYNAMICALLY INSERTED FONT STACK,
},
你会如何在 Rails 中做到这一点?我有位于 /javascript/stylesheets/tailwindcss-config.js 的 Tailwind 配置文件。这可能与 Rails 中的 Webpack 有关吗?这甚至是使用 Webpacker + Tailwind 使用 Rails 6 的正确方法吗?
解决方案
我感觉我们会尝试使用“构建时间”工具进行“运行时”操作
将变量直接注入到 tailwindcss 配置文件中意味着重建提供给用户的实际 css,将 tailwind 配置文件中的说明应用到 app/javascript/css 中的实际内容(假设上述视频教程中使用的设置)。
该操作由 webpack 进行,通过 webpacker gem 集成。
恕我直言,webpack 和 tailwind 都不是为了在运行时重建资产而设计的,而且,即使我很清楚通用机器可以做任何事情;)我想知道走这条路会走哪条路,主要是在以下方面可维护性。
从这个链接看来,在配置更改时触发 webpack 的重建并不简单。
这是一条稍微不同的尝试路径:
在应用程序的 <head> 部分中,为您希望用户访问的设置定义 css 变量(更准确地说是“css 自定义属性”),可以动态设置和更改(也可以从 js 中)
<style>
:root{
--display-font: "<%= display_font_families %>";
--body-font: "<%= body_font_families %>";
--link-color: "<%= link_color %>";
}
</style>
或者,您可以创建 app/assets/stylesheets/root.css.erb (扩展名很重要)并在顺风之前将其包含在您的模板中
然后您应该能够将您的 tailwindcss 配置更改为以下内容:
theme: {
fontFamily: {
display: "var(--display-font)",
body: "var(--body-font)",
},
extend: {
colors: {
link: "var(--link-color)",
},
}
通过这种方式,我们定义了一个响应css variables值的动态 css 布局。它们作用的变量和结构位于相同的逻辑级别,这对应于提供给用户的实际网页。
可以从 js 轻松访问css 变量,这也是从 rails 进行干净访问的一种方法
现在让我们假设用户想要更改链接颜色(应用于所有链接)。
在我们想象的设置表单中,她选择了任意颜色(以任何 css 有效格式 - 这里唯一的限制是它必须是有效的 css 值,您需要通过某种形式的输入验证来解决这个问题)。
我们可能想要
- 预览功能(客户端/js):无需重新加载页面,用户应该能够暂时将新设置应用于页面。这可以通过 js 调用来完成,该调用为变量--link-color设置新值
// userSelectedColor is the result of a user's choice,
// say it's "#00FF00"
document.documentElement.style
.setProperty('--link-color', userSelectedColor);
一旦更改此值,tailwind 之前创建的所有类以及使用该变量的任何规则都将反映更改,根本不需要重建 css。
请注意,我们的用户不受可能值的任意子集的限制,任何可以被 css 接受的东西都是公平的游戏。通过为 config 参数分配一个 css 变量,我们实际上已经指示 tailwindcss 在它的所有类中将它指定为一个变量值,现在我们可以通过 css/js 控制它......我们绝对不需要(也不想要) webpack 重建样式
为了更清楚地说明,通过我们的颜色示例,在生成的 css中将有这样的类 - 请查看此链接以了解自定义顺风主题的工作原理
/* GENERATED BY TAILWIND - well, this or something very similar :) */
.text-link {
color: var(--link-color);
}
.bg-link{
background-color: var(--link-color);
}
/* .border-link { ... */
很明显,浏览器需要知道--link-color的值(我们在:root部分中定义了它)并且值本身可以是任何有效的 css,但我们感兴趣的是它可以随时更改,自动传播更改使用它的每个规则,它是一个CSS 变量...
- 我们需要一个保存功能(服务器端/rails):当用户点击“保存”时,应该使新设置持久化(保存在数据库中)
这显然是完成的(例如)处理表单提交,保存新值,然后从数据库中提取新值以在页面的下一个渲染中评估css 变量
只是我的 2 美分 :) 玩得开心!
推荐阅读
- python - 通过 Vagrant 访问项目时,PyCharm 是否使用安装在虚拟环境中的依赖项?
- raspberry-pi - 为什么手动启动 c-lightning 可以工作,但无法通过 systemd 启动?
- php - 加入 2 个表时出现“唯一表/别名”错误
- arduino - 如何使这些 LED 一次淡入淡出?
- c# - 为什么我们在 i*j 之后加上“To.String”?
- eclipse - JavaFx 不允许我 setText() 或 add(),(仅添加节点)
- javascript - 每次 props 更新时,如何从 props 中的对象中获取项目并将它们放入 state?
- python - 平均提取的数字块
- reactjs - 如何为 React 的“withProps”函数正确定义类型?
- regex - 如何简化正则表达式模式?