Sass sprite generation with compass for retina and non-retina images (example code for a Rails 3 application).
The below Sass+Compass/Ruby can be used to:
Example markup for a retina supported menu button:
%a.icon-hamburger
To do this, we need:
Place sprite images in .../icon
and .../icon2x
directories.
// Using Compass spriting, see http://compass-style.org/help/tutorials/spriting/
// Compass is generating the sprite map and styles from images in /app/assets/images/web/mobile/icon[2x]/*.png.
//
// NOTE: 2x icons must be an even number of pixels wide to avoid clipping/bleed.
// NOTE: Adding an icon will cause the sprites to be regenerated.
// Reduce sprite-map waste for variable-width icons
$icon-layout: horizontal
$icon2x-layout: horizontal
// Include dimensions for span background-image support
$icon-sprite-dimensions: true
// Ensure no overlap between sprites in the map
$icon-spacing: 6px
$icon2x-spacing: 12px
// Create 1x and 2x sprite map images
@import "web/mobile/icon/*.png"
@import "web/mobile/icon2x/*.png"
// Use 1x sprite for non-high-dpi screens
@include all-icon-sprites
// Override the sprite image for high-dpi screens
// and adjust background-size so 1x positions will work correctly
// for all 1x sprite style classes
@media (min--moz-device-pixel-ratio: 1.3),(-o-min-device-pixel-ratio: 2.6/2),(-webkit-min-device-pixel-ratio: 1.3),(min-device-pixel-ratio: 1.3),(min-resolution: 1.3dppx)
#{$icon-sprite-base-class}
background-image: $icon2x-sprites
background-size: image-width(asset_path((sprite-url($icon-sprites)))) image-height(asset_path((sprite-url($icon-sprites))))
# /lib/assets/sass_functions.rb
module Sass::Script::Functions
# return asset path given a url
def asset_path(url)
assert_type url, :String
begin
relative_path = url.value.match(/url\(.*\/assets\/(.*)\)/)[1]
rescue StandardError
raise "Didn't know how to find relative asset match for #{url.value}"
end
file = "#{Compass.configuration.images_path}/#{relative_path}"
unless File.exist?(file)
# for asset precompilation
file = "#{Rails.root}/public/assets/#{relative_path}"
end
Sass::Script::String.new(file)
end
declare :asset_path, :args => [:url]
end
We must require the library file explicitly
# /config/initializers/assets/sass_functions.rb
if defined?(Sass)
require File.expand_path("./lib/assets/sass_functions.rb")
end
We also must require initializers explicitly during asset initialization (e.g. precompilation)
# config/applciation.rb
module AssetsInitializers
class Railtie < Rails::Railtie
initializer "assets_initializers.initialize_rails", group: :assets do |app|
Dir["#{Rails.root}/config/initializers/assets/*.rb"].each{ |file| require file }
end
end
end