-
-
Save thulstrup/2140082 to your computer and use it in GitHub Desktop.
$sprites: sprite-map("sprites/*.png"); | |
$sprites-retina: sprite-map("sprites-retina/*.png"); | |
@mixin sprite-background($name) { | |
background-image: sprite-url($sprites); | |
background-position: sprite-position($sprites, $name); | |
background-repeat: no-repeat; | |
display: block; | |
height: image-height(sprite-file($sprites, $name)); | |
width: image-width(sprite-file($sprites, $name)); | |
@media (-webkit-min-device-pixel-ratio: 2), (-o-min-device-pixel-ratio: 3/2), (min-device-pixel-ratio: 2) { | |
// Workaround for https://gist.github.com/2140082 | |
@if (sprite-position($sprites, $name) != sprite-position($sprites-retina, $name)) { | |
$ypos: round(nth(sprite-position($sprites-retina, $name), 2) / 2); | |
background-position: 0 $ypos; | |
} | |
// Hard coded width of the normal sprite image. There must be a smarter way to do this. | |
@include background-size(444px auto); | |
background-image: sprite-url($sprites-retina); | |
} | |
} | |
// Usage. | |
.mail-icon { | |
@include sprite-background(mail); | |
} |
One of the above solution works really well. I have slightly modified it to have a placeholder selector :
%sprites {
display: inline-block;
background-repeat: no-repeat;
background-image: sprite-url($sprites);
}
@mixin sprite($name, $dimensions: true, $pad: 0) {
@if ($dimensions == true) {
@include sprite-dimensions($sprites, $name);
}
@extend %sprites;
background-position: sprite-position($sprites, $name, -$pad, -$pad);
@if $pad > 0 {
padding: $pad;
}
@media (-webkit-min-device-pixel-ratio: 1.5), (min--moz-device-pixel-ratio: 1.5),
(-o-min-device-pixel-ratio: 3/2), (min-device-pixel-ratio: 1.5) {
& {
$pos: sprite-position($sprites2x, $name, -$pad * 2, -$pad * 2);
background-image: sprite-url($sprites2x);
background-position: nth($pos, 1) nth($pos, 2) / 2;
@include background-size(ceil(image-width(sprite-path($sprites2x)) / 2), auto);
}
}
}
The problem is that it the background-image: sprite-url($sprites2x); makes compile time a lot longer as soon as you have a few images (as it does this for every images in retina, while it just extend for the "basic" version). Is there a solution to that ?
Just an FYI for anyone else looking to use this with a hover state, I've forked a version of this from @rstacruz and added hover and active states.
The the mixin with a demo and docs is available here: https://github.com/AdamBrodzinski/Retina-Sprites-for-Compass , as well as the mixin below.
@import "compass/utilities/sprites"; // Include compass sprite helpers
@import "compass/css3/background-size"; // Include helper to calc background size
@mixin sprite($name, $hover: false, $active: false) {
@include retina-sprite($name, $sprites, $sprites2x, $hover, $active);
}
// The general purpose retina sprite mixin.
//
// @include retina-sprite(name, $spritemap1, $spritemap2)
// @include retina-sprite(name, $spritemap1, $spritemap2[, $dimensions: true, $pad: 0])
//
// If `dimensions` is true, then width/height will also be set.
//
// if `pad` is non-zero, then that's how much padding the element will have (requires
// $spacing on the sprite maps). Great for iPhone interfaces to make hit areas bigger.
//
@mixin retina-sprite($name, $sprites, $sprites2x, $hover, $active, $dimensions: true, $pad: 0) {
@if $dimensions == true {
@include sprite-dimensions($sprites, $name);
}
background-image: sprite-url($sprites);
background-position: sprite-position($sprites, $name, -$pad, -$pad);
background-repeat: no-repeat;
@if $hover == true {
$name_hover: $name + _hover;
&:hover {
background-position: sprite-position($sprites, $name_hover, -$pad, -$pad);
}
}
@if $active == true {
$name_active: $name + _active;
&:active {
background-position: sprite-position($sprites, $name_active, -$pad, -$pad);
}
}
@if $pad > 0 {
padding: $pad;
}
@media (-webkit-min-device-pixel-ratio: 1.5), (min--moz-device-pixel-ratio: 1.5), (-o-min-device-pixel-ratio: 3/2), (min-device-pixel-ratio: 1.5) {
& {
$pos: sprite-position($sprites2x, $name, -$pad * 2, -$pad * 2);
background-image: sprite-url($sprites2x);
background-position: nth($pos, 1) nth($pos, 2) / 2;
@include background-size(ceil(image-width(sprite-path($sprites2x)) / 2), auto);
// sprite-path() returns the path of the generated sprite sheet, which
// image-width() calculates the width of. the ceil() is in place in case
// you have sprites that have an odd-number of pixels in width
@if $hover == true {
$name_hover: $name + _hover; // create myButton_hover and assign it
&:hover{
$pos: sprite-position($sprites2x, $name_hover, -$pad * 2, -$pad * 2);
background-position: nth($pos, 1) nth($pos, 2) / 2;
}
}
@if $active == true {
$name_active: $name + _active; // create myButton_active and assign it
&:active{
$pos: sprite-position($sprites2x, $name_active, -$pad * 2, -$pad * 2);
background-position: nth($pos, 1) nth($pos, 2) / 2;
}
}
}
}
}
Is there any way we can not add media queries on each individual icon class on compiling? Not sure if there's a different way to go about this fix.
I wondered the same thing. This is what i came up with: https://gist.github.com/3837343
Do somebody have a fix for the long compile time mentioned by @bakura10? I'm using compass on a Sencha project with about 30 sprites, and while the "compass compile" takes from 15 to 20 seconds to finish – and I can see it trying to generate sprites multiple times – Sencha's build command takes forever.
@tegola , not sure it this is related but you may want to checkout this issue.
I've had issues with the retina sprite when using smart layout. I tried to use smart layouts as follows:
$sprites-retina: sprite-map("double/*.png", $layout: smart);
This resulted in two identical sprite images as expected, but SASS wasn't calculating the distances properly at all.
I am having issues with $layout: smart
as well. Anyone have a fix?
Anyone get '$layout: smart' working? Also, is anyone using this with images of varying sizes/dimensions? I want to create a sprite that contains all of my site's ui elements, but they aren't all square shaped.
We prefer using the compass helpers for sprite map and style class generation. This is a bit more future proof than manually setting background-size
as well as less labor intensive than generating the style classes manually:
@thulstrup Can you include an open source license in this gist?
here is my take on retina sprites. i wanted a way to use it within the @media directive as well...
https://gist.github.com/brewster1134/13162e2cb0220e87b017
I would love some feedback...
Here is my try to make it little short and for best practice. I wanted to use background-image property for once instead of using it in every class to minimise my code. I make this
https://github.com/mbilalsiddique1/Sass-Mixins
@import "compass/utilities/sprites"; // Include compass sprite helpers
@import "compass/css3/background-size"; // Include helper to calc background size
// General Sprite Defaults
// You can override them before you import this file.
$icon-sprite-base-class: ".icon-sprite" !default;
$icon-sprite-dimensions: false !default;
$icon-spacing: 10px !default;
$icon-position: 0% !default;
$icon-repeat: no-repeat !default;
$icon-sprites: sprite-map("sprites/*.png", $spacing: $icon-spacing, $repeat: $icon-repeat, $position: $icon-position);
$icon-sprites-retina: sprite-map("sprites-retina/*.png", $spacing: $icon-spacing * 2, $repeat: $icon-repeat, $position: $icon-position);
// All sprites should extend this class
// The icon-sprite mixin will do so for you.
#{$icon-sprite-base-class} {
background: $icon-sprites $icon-repeat;
}
@media (-webkit-min-device-pixel-ratio: 1.5), (min--moz-device-pixel-ratio: 1.5), (-o-min-device-pixel-ratio: 3 / 2), (min-device-pixel-ratio: 1.5), (min-resolution: 1.5dppx) {
#{$icon-sprite-base-class} {
background: $icon-sprites-retina $icon-repeat;
@include background-size(ceil(image-width(sprite-path($icon-sprites-retina)) / 2) auto);
}
}
// Extends the sprite base class and set the background position for the desired sprite.
// It will also apply the image dimensions if $dimensions is true.
@mixin icon-sprite($name, $dimensions: $icon-sprite-dimensions, $offset-x: 0, $offset-y: 0) {
@extend #{$icon-sprite-base-class};
@include sprite($icon-sprites, $name, $dimensions, $offset-x, $offset-y)
}
// Example Usage.
.icon-analytics {
@include icon-sprite(main-sprite);
}
My smaller contribution: https://gist.github.com/tomasdev/56bc62e86ab0700f8298 works right out of the box if you're planning to save only the biggest assets and not the pixelated (non-retina) ones.
@mbilalsiddique1 - thanks for this bit above. Working well for my usage thus far. Maybe i missed it, but any way to have the css for all icons in the folder automatically render with their unique file names as classes, instead of defining each one again ( as you show in your example ) ?
// Example Usage. .icon-analytics { @include icon-sprite(main-sprite); }
I believe i figured it out how to declare all the sprites in the map. Works well on top of whats above.
$sprite-names: sprite_names($icon-sprites);
@each $sprite in $sprite-names {
.icon-#{$sprite} {
@include icon-sprite($sprite, true);
}
}
How to combine this mixin to get the image height of the sprite?
@Aetherpoint see my solution:
Can I create a class for sprite or improve this:
It would be interesting to create a selector [class^="sprite-"] for all classes begin with .sprite-
Abs,