Reputation: 823
I've read every single question about responsive sprites using css, I saw jsfiddle with working examples of responsive sprites, but I still cannot understand how to get the percentage of background-position and of background-size, how to use a wrapper (some people say it is necessary) around the div that uses background-image and why to use it...
For instance, if I have a div that has width:20% (say 40px) and is a circle. The image I need to use as background-image has 80px width (a circle, and I need to resize it to fit my div) and is one of the 40 images I have in my sprite sheet. It is at the position -173px -293px.
I really have no clue how to make it work.
I tried:
div {
width:20%;
border-radius:50%;
background: url('images/sprites.png') no-repeat 72.083% 67.981%;
background-size: 50%;
}
Of course, it did not work. I don't understand how to get the background-position-x, background-position-y (the numbers I have are from the "auto" size sprite sheet) when the background-size is not auto, or how the background-size relates to the percentage of the div size.
Is there any mathematical formula that I can use? Can anyone please explain me or give me a name of some website/book where I can learn it?
Thanks,
Upvotes: 28
Views: 30293
Reputation: 115
From a large FE experience, I've developed responsive sprites framework that does not rely on background-image, but instead it uses "physical" image in a container that is scaled like original image/part of sprites. The problem with css bgd-img is calculating size and position and its often for css to "miss" pics possition for few pixels. Most of the browsers renders these values at 0.1px, but rounds it as well. So the precision is (about 1/2 of the px). This missmatch multiplies when you try to scale it (to make it responsive). - so dont be fooled by "responsive sprites" that rely on css background-image. They're just a bad and displaced display of sprites image you need. - The JavaScript (framework) is far more precisious - (1/100px), and its solid ground for responsive images - as you have 1/50 size to scale pics and not loose any pixel. I'm not advertising this, If anyone is interested - take a look at: responsive-sprites.com
Upvotes: -1
Reputation: 6247
My approach is similar to Greg's in that I wrote a tool to generate responsive css sprites. I however have taken it one step further and added a sorting algorithm so you can pack more images efficiently onto a png.
Here is the Responsive CSS Sprite Generator Tool: https://responsive-css.us/
Upvotes: 0
Reputation: 1180
An update to @vals' answer. Some of his calcs didn't quite work for me.
The background-size calcs worked, except that he was multiplying by 1000 instead of 100 to get the final percentage figures. So 12500% should be 1250% and so on. (Update: 10/2015 - it looks like @vals has corrected this in his answer.)
The background-position X value calcs were very slightly out for me. They didn't match what was generated by spritecow.com (as per Adrian Florescu's suggestion). This is, I think, because absolute coordinates are calculated from the left of the background image, whereas with percentages, you have to calculate from the right of the background image. That being the case, you have to subtract the image width from the overall background width before you divide the absolute x-pos number with it.
So instead of:
x-part 173px / 1000px = 0.173 ->> 17.3%
do this:
x-part 173px / (1000px - 80px) = 0.1880434783 ->> 18.80434783%
Where:
1000px is the width of the background image (sprite)
80px is the width of displayed image
173px is the absolute x-coordinate of the displayed image.
This is what works for me, anyway!
Upvotes: 30
Reputation: 321578
I've written a Responsive CSS Sprite Generator to take care of all the work for you. You can just upload a bunch of images and it will give you a sprite image and the CSS for it.
It uses a novel method for making the sprites responsive - a data src with a transparent PNG to make the image maintain its aspect ratio, so unlike other methods the images don't need to be square, or all the same ratio.
Upvotes: 16
Reputation: 64164
The div dimension doesn't play in the calculus, only the background sizes, and the part that you are going to use.
Lets say that your background has a width of 1000px and a height of 500px.
The image that you are going to use has 80px width and height.
background-size:
x part 1000px / 80px = 12.5 ->> 1250%
y part 500px / 80px = 6.25 ->> 625%
background-size: 1250% 625%;
background-position:
x-part 173px / 1000px = 0.173 ->> 17.3%
y part 293px / 500px = 0.586 ->> 58.6%
background-position: 17.3% 58.6%;
Upvotes: 19
Reputation: 111
I spent a lot of time looking for an answer on this matter, I came out with this solution, it works for me at least for now, is based on fixed pixel box-sizing, and horizontal sprites, will be a mess with percentage anyway because you will have to do the math for the pixel values for that percentage, and for random located sprites because you will have to find the random location of the sprite inside the image, too much math for a simple task I believe.
You need:
compass image-width($image)
)As a piece of advice, you will have to leave at least 1px of physical margin between each image because percentages produce not integer pixels, and you will end up with overlaping sprites!! ;)
Check it out and give me some feedback please:
//functions
//stretch by percentage
@function stretchImage($width, $height, $percentage) {
$s_width: round( ($width * $percentage) / 100 );
$s_height: round( ($height * $percentage) / 100 );
@return ($s_width, $s_height);
}
//strip units
//(Eric M Suzanne) http://stackoverflow.com/questions/12328259/how-do-you-strip-the-unit-from-any-number-in-sass
@function strip-units($number) {
@return $number / ($number * 0 + 1);
}
//replace in string
//(css tricks) http://css-tricks.com/snippets/sass/str-replace-function/
@function str-replace($string, $search, $replace: '') {
$index: str-index($string, $search);
@if $index {
@return str-slice($string, 1, $index - 1) + $replace + str-replace(str-slice($string, $index + str-length($search)), $search, $replace);
}
@return $string;
}
//get unitless percentage
@function getPercentageFrom($valueA, $valueB) {
$percentage: percentage(strip-units($valueA)/strip-units($valueB));
@return ($percentage);
}
//now the magic
//we know the witdh of the image containing the sprites
$image: url(http://www.cssguy4hire.com/codePenAssets/sprite_test.png);
$image_width: 965px;
//the amount of strech we want to aply
$stretchTo: 175;
//we know the current sprite measures we going to set
$sprite_width: 150px;
$sprite_height: 150px;
//left is 0 cuz is first sprite
$sprite_left: 0%;
//stretch sprite
$stretch: stretchImage($sprite_width, $sprite_height, $stretchTo);
$width: nth($stretch, 1);
$height: nth($stretch, 2);
//set background size and position
$bkg-size: getPercentageFrom($image_width * ($stretchTo / 100), $width);
//default position 0
$bkg_left: $sprite_left;
//compose the css
#image {
margin: auto;
width: $width;
height: $height;
position: relative;
display: block;
background: #00f00f $image $bkg_left 0 no-repeat;
background-size: $bkg-size;
border: 5px solid #cccccc;
//we chage the sprite
&.sprite_1 {
//the amount of strech we want to aply
$stretchTo: 250;
//we know the current sprite measures we going to set
//0 is te first sprite starting left to right
$sprite_width: 250px;
$sprite_height: 75px;
$sprite_left: 150px;
//stretch sprite
$stretch: stretchImage($sprite_width, $sprite_height, $stretchTo);
$width: nth($stretch, 1);
$height: nth($stretch, 2);
//set background size
$bkg-size: getPercentageFrom($image_width * ($stretchTo / 100), $width);
$bkg_left: percentage($sprite_left / ($image_width - $sprite_width) );
//compose the css
width: $width;
height: $height;
background-size: $bkg-size;
background-position: $bkg_left 0;
}
&.sprite_2 {
//the amount of strech we want to aply
$stretchTo: 80;
//we know the current sprite measures we going to set
$sprite_width: 140px;
$sprite_height: 120px;
$sprite_left: 400px;
//stretch sprite
$stretch: stretchImage($sprite_width, $sprite_height, $stretchTo);
$width: nth($stretch, 1);
$height: nth($stretch, 2);
//set background size
$bkg-size: getPercentageFrom($image_width * ($stretchTo / 100), $width);
$bkg_left: percentage($sprite_left / ($image_width - $sprite_width) );
//compose the css
width: $width;
height: $height;
background-size: $bkg-size;
background-position: $bkg_left 0;
}
&.sprite_3 {
//the amount of strech we want to aply
$stretchTo: 125;
//we know the current sprite measures we going to set
$sprite_width: 290px;
$sprite_height: 134px;
$sprite_left: 540px;
//stretch sprite
$stretch: stretchImage($sprite_width, $sprite_height, $stretchTo);
$width: nth($stretch, 1);
$height: nth($stretch, 2);
//set background size
$bkg-size: getPercentageFrom($image_width * ($stretchTo / 100), $width);
$bkg_left: percentage($sprite_left / ($image_width - $sprite_width) );
//compose the css
width: $width;
height: $height;
background-size: $bkg-size;
background-position: $bkg_left 0;
}
&.sprite_4 {
//the amount of strech we want to aply
$stretchTo: 153;
//we know the current sprite measures we going to set
$sprite_width: 135px;
$sprite_height: 56px;
$sprite_left: 830px;
//stretch sprite
$stretch: stretchImage($sprite_width, $sprite_height, $stretchTo);
$width: nth($stretch, 1);
$height: nth($stretch, 2);
//set background size
$bkg-size: getPercentageFrom($image_width * ($stretchTo / 100), $width);
$bkg_left: percentage($sprite_left / ($image_width - $sprite_width) );
//compose the css
width: $width;
height: $height;
background-size: $bkg-size;
background-position: $bkg_left 0;
}
}
http://codepen.io/wolfitoXtreme/pen/BymKyP
Upvotes: 0
Reputation: 3394
This is the best responsive example I have found to solve the problem of sprite!
Cross-browser, responsive resizing/stretching of CSS sprite images
This method does not rely on background-size, so it will work in older browsers.
This example uses an image that is 800 wide x 160 high. This image contains 6 equal size sprites (160x160 each).
If your sprite size is different all you need to change is the max-width property of .sprite to match the individual sprite width.
To set the visible sprite: Set the left value of .sprite to: 0 = 1st sprite -100% = 2nd sprite -200% = 3rd sprite etc... Easy!
If you want images to stretch larger than their natural size: Add the class .no-limit to .stretchy. This removes max-width:160px from .stretchy and add min-height:100% to .sprite Alternatively you could set a larger max-width using a px value, e.g. 300px.
The spacer image can be any size, as long as it is propotional to the dimensions of the individual sprites.
Upvotes: 4
Reputation: 503
This is a simpler solution, check this
.my_picture{
//target your sprite
background: url(my_img.jpg) no-repeat;
//Specify it full image
backgound-size: 100%;
//Position of the targeted picture
background-position: left 0 bottom x%;
//Zoom in or out on the position
width: x%;
//Scale height by playing with padding
padding-bottom: x%;
//Set height to 0 because of sprite size
height: 0;
}
How does it work? To target any sprite pictures easily, we have to specify sprite size to original, “100%”. We will then target a picture position from corresponding bottom, with left 0.
Because the sprite size is set to max 100%, we have to disable height, and the only option to set height now, is to play with padding-bottom, in percentage too.
Your image is now fully responsive, just play with width values (in percentage), to zoom in or out, and that’s all, you have a fully responsive css sprite.
Original article on my blog here: http://creativcoders.wordpress.com/2014/05/05/css-responsive-sprites/
Upvotes: 5
Reputation: 3101
You can use websites to find out the exact coordinates of your sprite. I personally use http://www.spritecow.com/
Upvotes: 2