Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using SASS with user-specified colors

I'm building a website with Rails 3 that'll let users have profiles with different layouts and color schemes. I'm already using SASS, and the variables would be invaluable if I could do something like this…

<link src="base_styles.css" rel="stylesheet">
<link src="color_schemes/users_choice.css" rel="stylesheet">
<link src="layouts/users_choice.css" rel="stylesheet">

…where the color scheme definition would be primarily (entirely?) SASS variables specifying the colors to use in the layout. Obviously I can't just link the SASS or CSS files like this, I'll need to import them into SASS.

How can I import SASS files into the parser dynamically at request-time, then cache the resulting CSS files for use later?

I've considered going the ugly route of building every possible combination on deploy, but that still leaves me hanging if I want to let users set their own colors in the future. It seems like such low-hanging fruit with SASS that it might as well be implemented.

like image 879
coreyward Avatar asked Jan 07 '11 02:01

coreyward


People also ask

What is the correct way to define a color variable in Sass?

Declaration of a variable in SASS: In SASS, you can define a variable by using $ symbol at the starting of the name of the variable and followed by its value.

Can I use CSS variables in Sass?

Sass variables are all compiled away by Sass. CSS variables are included in the CSS output. CSS variables can have different values for different elements, but Sass variables only have one value at a time.

What is the difference between SCSS and Sass?

SASS (Syntactically Awesome Style Sheets) is a pre-processor scripting language that will be compiled or interpreted into CSS. SassScript is itself a scripting language whereas SCSS is the main syntax for the SASS which builds on top of the existing CSS syntax.


1 Answers

Alright I dug into the Sass docs and it looks like it would be possible to do using their functions, but it seems like it'd be overly complicated and introduce problems later anyways.

The best way I have found to do this is to generate the user-specific template when they update their settings. This works better anyways, as a request is never delayed while waiting on the parser.

# unless cached_copy_exists
template = %Q{
  @import '/path/to/color_scheme';
  @import '/path/to/layout';
}

output = Sass::Engine.new(template, :syntax => :scss).render

# output rendered CSS to file for inclusion in HTML template

In order to allow custom colors, user-input could be assembled into SASS css variables in a string and prepended to the template file being passed to the Sass parsing/rendering engine.

Update:

Per request, here's a more fleshed-out example of how this works, focusing just on using Sass variables and a pre-coded Sass stylesheet (simplified to isolate this specific problem):

# config/routes.rb
resources :stylesheets, only: [:show]

# app/controllers/stylesheets_controller.rb
class StylesheetsController < ApplicationController
  layout nil

  def show
    styles = Stylesheet.find(params[:id])
    base_stylesheet_path = Rails.root.join('app', 'assets', 'profile.scss')

    # Build the string of SCSS we'll pass to the Sass rendering engine
    @sass = <<-SASS
      #{styles.to_sass}
      @import "#{base_stylesheet_path}";
    SASS

    # Cache for long time
    response.headers['Cache-Control'] = "public, max-age=#{1.year}"

    respond_to do |format|
      format.css
    end
  end
end

# app/views/stylesheets/show.css.erb
<%= raw Sass::Engine.new(@sass :syntax => :scss).render -%>

# app/models/stylesheet.rb
class Stylesheet < ActiveRecord::Base
  serialize :variables, JSON

  def to_sass
    # Convert a hash of variables into SCSS
    variables.each_pair.map do |name, value|
      "$#{name}: #{value};"
    end.join("\n")
  end
end

# example for the stylesheet model 
stylesheet = Stylesheet.new
stylesheet.variables[:primary_color] = "#0000ff"
stylesheet.save   
like image 69
coreyward Avatar answered Nov 15 '22 18:11

coreyward