sprite-factory
sprite-factory copied to clipboard
Add support for Retina sprites
It would be amazing if we could add @2x to icons which are the Retina counterparts of their non-Retina versions. Doing would create a new rule in the same stylesheet but only for @2x versions. Some JavaScript would be needed to handle when the @2x version is used.
I agree. This would be great. Glue does something similar to what you're describing. http://glue.readthedocs.org/en/latest/ratios.html
I'm close to coming up with a solution by using sprite-factory's "Customizing the entire CSS output" method. I'm passing variables into a SASS mixin that then writes most of the necessary css/media query. I'm also using this as a general mixin for use in my stylesheets, so all the variables that'd come from sprite factory are optional and come after the $sprite: false declaration.
The only real issue I'm running into is trying to figure out a way to access the width and height of the final output image (necessary to set the correct background size on retina). I feel like I'm probably overlooking something simple... have tried using :cssw, :cssh. Any suggestions?
The code assumes you're starting with your highest resolution assets; I may try to integrate some sort of image processor after the sprite-factory call to create the second image scaled at 50%.
Again any suggestions on accessing the final output size, or code improvements would be greatly appreciated! And if you're curious I'm using retina.js for images outside the stylesheet.
@mixin retina_url($path, $filetype, $repeat: no-repeat, $rwidth: auto, $rheight: auto, $sprite: false, $sprite-posx: 0, $sprite-posy: 0, $sprite-width: 0, $sprite-height: 0) display: inline-block background-image: image-url('#{$path}.#{$filetype}') background-repeat: $repeat width: $rwidth height: $rheight @if $sprite background-position-x: -($sprite-posx / 2) background-position-y: -($sprite-posy / 2) // RETINA MEDIA QUERY, MAY ALSO NEED -MOZ PREFIX @media all and (-webkit-min-device-pixel-ratio : 1.5) background-image: image-url('#{$path}@2x.#{$filetype}') background-repeat: $repeat @if $sprite background-position-x: -($sprite-posx) background-position-y: -($sprite-posy) background-size: ($sprite-width / 2) ($sprite-width / 2) @else background-size: $rwidth $rheight
Here's my custom css output:
SpriteFactory.run!('app/assets/images/us_sprite', :nocomments => 'true', :output_style => 'app/assets/stylesheets/sprites/us_sprite.css.sass', :output_image => "app/assets/images/compiled/[email protected]") do |images| #Writing SASS, mostly done with mixin retina_url() images.map do |image_name, image_data| ".#{image_name}\n\t@include retina_url(compiled/us_sprite, png, no-repeat, #{image_data[:width] / 2}px, #{image_data[:height] / 2}px, true, #{images[:cssx]}px, #{images[:cssy]}px)" end.join("\n") end
Awesome! It's great!!!!!!
Any thoughts on this? I'm surprised this thread has been stale for so long. I would have it would be taken care of, or a reason to not do it would have been discovered
@matsuodesign I'm using https://github.com/ai/rails-sass-images to grab the image width of the 2x sprite.
After that, it's just background-size: (image-width("compiled/[email protected]") / 2) auto
.
FYI, @matsuodesign's workaround is working for me.
Here's my configuration if it helps. I'm using https://github.com/ai/rails-sass-images to grab the width of the output 2x sprite. Also, the +respond-to($hidpi)
is just a helper for targeting @media screen and (-webkit-max-device-pixel-ratio: 1.5), screen and (max-resolution: 1.5dppx)
.
Ruby:
SpriteFactory.run!('app/assets/images/sprites/2x',
:output_style => 'app/assets/stylesheets/_sprites-2x.sass.erb',
:output_image => 'app/assets/images/sprites/[email protected]',
:selector => '.icon-2x-') do |images|
images.map do |image_name, image_data|
".icon-2x-#{image_name}\n\t@include hidpi-sprite(" +
"'sprites/[email protected]', " +
"#{image_data[:cssw]}px, " +
"#{image_data[:cssh]}px, " +
"#{image_data[:cssx]}px, " +
"#{image_data[:cssy]}px)"
end.join("\n")
end
Sass:
// _icons.sass
=icon($sprite-name: null, $image-name: null)
+respond-to($hidpi)
@extend .icon-2x-#{$sprite-name}_#{$image-name}
=hidpi-sprite($path, $width: 0, $height: 0, $x: auto, $y: auto)
background-image: image-url('#{$path}')
background-repeat: no-repeat
background-position: ($x / -2) ($y / -2)
background-size: (image-width("sprites/[email protected]") / 2) auto
height: $height / 2
width: $width / 2
// usage:
.icon-facebook
&:hover
+icon("social", "facebook-hover")
Hi guys, I understand this thread is 2 years old but it's still open so in case others are searching like me, here is the method I am using that doesn't rely on rails-sass-images
. It makes an assumption (seems to be correct) that the generated sprite file won't have extra padding around the sprites.
SpriteFactory.run!('app/assets/images/sprites/2x') do |images|
# Find the max right-most point of any sprite in the list.
# This must therefore be the image width.
image_width = images.values.map{|data| data[:x] + data[:width]}.max
# The rest is standard issue, now that we know the background size.
images.map do |name, data|
<<-SCSS
.icon-2x-#{name} {
width: #{data[:width] / 2}px #{data[:height] / 2}px;
background: image-url(sprites/[email protected]) #{data[:x] / -2}px #{data[:y] / -2}px no-repeat;
background-size: #{image_width / 2}px auto;
}
SCSS
end.join("\n")
end
Updated 18th April 2017
hello, in the proposed solution I find that data[:w] is nil
, both with chunkypng and rmagick. any solution to that?
@masterkain looks like the data is now data[:width]
and data[:height]
@sethjeffery any chance you could update your example block of code with the updated keys from the images hash?