Rails 和 SASS:使用相同变量的多种颜色主题 - 允许用户为帐户选择首选主题

lit*_*hxe 1 themes ruby-on-rails sass

我想为浅色主题使用一组 SASS 变量,并为我的深色主题更改相同的 SASS 变量。我真的不希望我的 CSS 充满每个主题的 mixins 和 if 语句,这似乎是我迄今为止找到的大部分答案。我的 CSS 几乎已经完全写好了,所以如果可能的话,我也不想回去进行大量更改。

我还想让我的用户能够选择他们想要的主题并保存他们的偏好。

lit*_*hxe 5

我找到了一个似乎运行良好的解决方案。我可以看到,如果您有一堆非常大的主题,则此方法可能不实用,因为它会预编译每个主题。然而,我发现这对于我的项目来说是一个很好的解决方案。如果有人发现任何潜在的问题,我很乐意听到他们的声音,因为我对其中的一些还是有点陌生​​,并且不想违反 Rails 规则......

我的样式表文件夹看起来像这样:
app/assets/stylesheets/

_forms.scss
_layout.scss
_manifest.scss
_mixins.scss
_tables.scss
_utilities.scss
light_theme.scss
dark_theme.scss

我将所有组件分成部分以便组织。“_manifest.scss”文件导入我的主题的所有组件。

应用程序/资产/样式表/_manifest.scss

// ---------------- Import all CSS components ----------------
@import 'bootstrap';
@import 'utilities';
@import 'layout';
@import 'tables';
@import 'forms';
Run Code Online (Sandbox Code Playgroud)

我为每个主题创建一个 .scss 文件,其颜色变量位于顶部,然后导入清单。请注意,使用相同的变量名称,以便轻松替换。

应用程序/资产/样式表/light_theme.scss

// ---------------- LIGHT THEME ----------------
// Theme Colors
$light: #f4f3ef;
$medium: #9a9a9a;
$dark: #252422;
$ocean: #36414f;
$accent: cadetblue;
$red: #ed4033;
$orange: #ff8c65;
$yellow: #f4ba58;
$green: #76c29d;
$blue: #65b4c6;

// Import all components
@import 'manifest';
Run Code Online (Sandbox Code Playgroud)

应用程序/资产/样式表/dark_theme.scss

// ---------------- DARK THEME ----------------
// Theme Colors
$light: #d5d6fa;
$medium: #9e9ed6;
$dark: #0d1118;
$ocean: #1f2c44;
$accent: #806df3;
$red: #f24e77;
$orange: #f2a23b;
$yellow: #f2c54a;
$green: #34d07e;
$blue: #2c8fef;

// Import all components
@import 'manifest';
Run Code Online (Sandbox Code Playgroud)

我在 CSS 框架中使用 bootstrap,因此大部分颜色特定的 css 是通过“btn-blue”“text-orange”等类设置的。这样,当我想切换主题时,需要筛选和更改的代码就更少了。文本橙色仍然是橙色,只是深色主题上的橙色更亮,而浅色主题上的橙色更柔和,这就是为什么简单的变量交换如此必要。

有些元素需要特别指出,所以我也为每个主题使用一个主体类。这使您可以进行特定于主题的更改。
应用程序/资产/样式表/_layout.scss

body.light_theme {
    background-color: $light;
    color: $dark;
}

body.dark_theme {
    background-color: $lake;
    color: $white;
}
Run Code Online (Sandbox Code Playgroud)

接下来我希望我的用户能够设置自己的主题。我创建了一个迁移,将一列添加到我的用户表中:

class AddThemeToUsers < ActiveRecord::Migration[5.1]
  def change
    add_column :users, :user_theme, :string
  end
end
Run Code Online (Sandbox Code Playgroud)

在我的用户表单上,他们可以通过下拉菜单选择他们的主题。您的选择选项在这里很重要,因为名称会变成变量,因此请保持命名一致。
应用程序/视图/用户/_form.html.erb

<div class="form-group">
  <%= form.label :user_theme, 'Theme' %>
  <%= form.select :user_theme, ['Light Theme', 'Dark Theme'], class: 'form-control' %>
</div>
Run Code Online (Sandbox Code Playgroud)

现在我在应用程序控制器中设置我的主题。如果用户登录,它将采用他们的主题设置,否则默认为浅色主题。如果您要将 user_theme 行添加到现有用户表中,请确保在添加以下内容之前运行迁移来为每个用户设置默认主题,否则您将收到错误,因为该单元格为空。或者添加一些代码来检查 current_user.user_theme 是否为空,然后默认为另一个主题。(可能更好...)
application_controller.rb

class ApplicationController < ActionController::Base

before_action :set_theme

private
def set_theme
  if current_user
    @user_theme = current_user.user_theme.parameterize.underscore
  else
    @user_theme = 'light_theme'
  end
end

end
Run Code Online (Sandbox Code Playgroud)

在布局文件中,我将主题作为类添加到主体中:
app/views/layouts/application.html.erb(布局文件)

<body class="<%= @user_theme %>">
    ...
</body>
Run Code Online (Sandbox Code Playgroud)

您可能会遇到另一个问题,如果您遇到资产编译错误,请将其添加到每个主题文件的config/initializers/assets.rb中。

Rails.application.config.assets.precompile += %w( dark_theme.css )
Rails.application.config.assets.precompile += %w( light_theme.css )
Run Code Online (Sandbox Code Playgroud)