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

时间:2018-04-08 14:44:49

标签: ruby-on-rails sass themes

我想为Light Theme使用一组SASS变量,并为我的Dark Theme更改相同的SASS变量。我真的不希望我的CSS充满了mixins和if每个主题的语句,这似乎是我到目前为止找到的大部分答案。我的css几乎已经完全写好了所以我也不想回过头来改变一下。如果可能的话。

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

2 个答案:

答案 0 :(得分:2)

我找到了一个似乎运作良好的解决方案。如果你有一堆非常大的主题,我可以看到这个方法可能不实用,因为它预先编译了每个主题。但是,我发现这对我的项目来说是一个很好的解决方案。如果有人发现任何潜在的问题,我很乐意听到他们,因为我对其中的一些人还有点新意,并且不想违反铁路规则......

我的stylesheets文件夹看起来像这样:
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';

我为每个主题创建一个.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';

应用/资产/样式表/ 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';

我正在为我的CSS框架使用bootstrap,所以我的大部分颜色特定的css都是通过" btn-blue"等类来设置的。 "文本橙色&#34 ;.这样,当我想切换主题时,我需要更少的代码来筛选和更改。文本橙色仍然是橙色,黑色主题上只有一个更亮的橙色,而浅色主题上则是淡橙色,这就是为什么简单的变量交换是如此必要。

有些元素需要专门调用,所以我也为每个主题使用了一个body类。这使您可以进行特定于主题的更改 应用/资产/样式表/ _layout.scss

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

body.dark_theme {
    background-color: $lake;
    color: $white;
}

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

class AddThemeToUsers < ActiveRecord::Migration[5.1]
  def change
    add_column :users, :user_theme, :string
  end
end

在我的用户表单上,他们可以通过下拉列表选择主题。您的选择选项在此非常重要,因为名称会变为变量,因此请保持命名一致 app / views / users / _form.html.erb

<div class="form-group">
  <%= form.label :user_theme, 'Theme' %>
  <%= form.select :user_theme, ['Light Theme', 'Dark Theme'], class: 'form-control' %>
</div>

现在我在应用程序控制器中设置我的主题。如果用户已登录,则采用其主题设置,否则默认为Light Theme。如果要将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

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

<body class="<%= @user_theme %>">
    ...
</body>

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

Rails.application.config.assets.precompile += %w( dark_theme.css )
Rails.application.config.assets.precompile += %w( light_theme.css )

答案 1 :(得分:0)

所以现在似乎有一种更简单的方法:

Stylesheets 文件夹看起来像这样:
app/javascript/stylesheets/

<块引用>

应用程序.scss
light_theme.scss
dark_theme.scss

接下来,将prefers-color-scheme添加到application.scss中,根据用户的系统偏好(Windows、MacOS、iOS、Linux、Andriod中的设置)为您完成所有工作

app/javascript/stylesheets/application.scss

@media (prefers-color-scheme: light) {
    @import 'light_theme';
}
@media (prefers-color-scheme: dark) {
    @import 'dark_theme';
}

现在在单独的主题文件中添加主题首选项:

app/javascript/stylesheets/light_theme.scss

background-color: white;
color: black;

app/javascript/stylesheets/dark_theme.scss

background-color: black;
color: white;

所以,就是这样,prefers-color-scheme 完成了所有繁重的工作,无需在数据库中保存任何内容作为首选项,因为多个用户可能使用同一个帐户并需要不同的设置。