28
votes

Does anyone have a workflow for developing Shopify themes with Compass and Sass? I am really close, I just need to figure out how to not make Sass barf on the CSS liquid tags.

Here's what I've got:

  • A sass/compass project in directory (ex:, "/newwebsite/)
  • A subdirectory containing my Shopify theme ("/newwebsite/newwebsite-theme/")
  • A Compass config.rb that points the css,_dir images_dir and javascripts_dir all to the them's assets folder ("/newwebsite/newwebsite-theme/assets/")
  • Compass watch on
  • shopify_theme gem also watch on, uploading theme files to shopify (https://github.com/Shopify/shopify_theme)
  • EDIT Sass interpolations (see anser below)
  • EDIT Compass callback to rename to .css.liquid

The problem: Compass barf's when you need to use Shopify's liquid templating tags, for example, a background image - example, background: url( "{{ "splash-1.jpg" | asset_url }}")

Does anyone know how to instruct Compass / Sass to spit out the liquid template tags as they are into the CSS? If I have that, then I have a solid workflow of editing Sass locally, and realizing the changes momentarily after on the shopify shop.

Thanks

EDIT: By using Hopper's answer below for the liquid tags in Sass, and renaming the Compass output .css file to .css.liquid, I now have an instantaneous workflow for designing a Shopify theme with Compass and Sass! Here is the code for the Compass callback that goes in the config.rb:

on_stylesheet_saved do |filename|
  s = filename + ".liquid"
  puts "copying to: " + s
  FileUtils.cp(filename, s)
  puts "removing: " + filename
end
9
I was trying to do this at one point and got nowhere. It might be possible with a custom SASS extension, or if there is a directive that tells the sass compiler to ignore and output as is, but I didn't find anything that would work.John Duff

9 Answers

23
votes

I'm not familiar with Shopify or liquid tags, but I do know that in SASS you can use interpolations to output plain CSS as-is. For example, the SASS here:

.test {
    background: url( #{'{{ "splash-1.jpg" | asset_url }}'} )
}

Would be compiled to:

.test {
    background: url({{ "splash-1.jpg" | asset_url }}); }

Does that get you close to what you're looking for?

10
votes

How do you keep Compass from barfing on liquid logic between properties? E.g. any time there's a liquid if statement I get errors, and using #{'...'} doesn't seem to help.

This is a test I can't get to work:

#container {
  width:884px;
  margin:0px auto;
  min-height:500px;
  position:relative;
  padding:0 40px;
  {% if settings.page_bg_transparent %}
    background:transparent;
  {% else %}
    background:{{ settings.page_bg_color }};
  {% endif %}
}

UPDATE weirdly, commenting liquid logic works:

#container {
  width:884px;
  margin:0px auto;
  min-height:500px;
  position:relative;
  padding:0 40px; 
  /* {% if settings.page_bg_transparent %} */
    background:transparent;
  /* {% else %} */
    background:#{'{{ settings.page_bg_color }}'}; 
  /* {% endif %} */
}
2
votes

For asset url you can also use SCSS custom functions. Put this in your config.rb file

module Sass::Script::Functions
  def shopify_image_url(string)
    assert_type string, :String
    Sass::Script::String.new("url({{'#{string.value}' | asset_url}})")
  end
end

And then use it in your styles.scss like this

background: shopify_image_url('image.png');
1
votes

I found it useful to remove the original output file after save so you don't have that extra, non liquid file floating in the assets dir.

on_stylesheet_saved do |filename|
  s = filename + ".liquid"
  puts "copying to: " + s
  FileUtils.cp(filename, s)
  puts "removing: " + filename
  FileUtils.remove_file(filename)
end
1
votes

Building on hopper's answer, for anyone using autoprefixer to process sass output, you would need to add an additional pair of quotes because url( {{ ... }} ) causes autoprefixer's parser to choke.

Do this:

background: url( "#{'{{ "splash-1.jpg" | asset_url }}'}" )

Which becomes this in the *.css.liquid file :

background: url( '{{ "splash-1.jpg" | asset_url }}' )
1
votes

If you wish to preserve the ".scss.liquid" extension for the new responsive checkout use:

on_stylesheet_saved do |filename|
  FileUtils.mv filename, "#{File.dirname(filename)}/#{File.basename(filename,'.*')}.scss.liquid"
end

It renames the files instead of copying and then removing.

1
votes

I wrote an article describing the methods I used to get Compass and Sass working well with Shopify. This is the same approach of DOMUSNETWORK's answer. I go into a little more detail on file structure.

http://www.mealeydev.com/blog/shopify-and-sass/

0
votes

This worked for me, partially - however I found that the Shopify Theme app a lot of times didn't want to upload my edited .css.liquid file, because apparently it didn't recognize that the file had been edited.

What solved it for me was to use the following code in my config.rb, instead of the code in the question above:

on_stylesheet_saved do |filename|
  move_to = filename + ".liquid"
  puts "Moving from #{filename} to #{move_to}"
  FileUtils.mv(filename, move_to)
end
0
votes

Shameless plug...

I think @nick is on the right track.

scss is better when it's compiled before sending to Shopify.

For others who find this answer, I think Quickshot is the tool you are looking for.

You will still need to interpolate for asset urls, but quickshot will automatically recompile your scss and upload the result to shopify in one step. Which also gives you the ability to use @include in your scss files.

http://quickshot.io/

https://github.com/internalfx/quickshot