[css] How can I scale an image in a CSS sprite

In this article, http://css-tricks.com/css-sprites/, it talks about how can I crop off a smaller image from 1 bigger image. Can you please tell me if it is possible/how I can crop off a smaller image and then scale the cropped off region before I lay it out?

Here is an example from that article:

A
{
  background-image: url(http://www.jaredhirsch.com/coolrunnings/public_images/3deb155981/spriteme1.png);
  background-position: -10px -56px;
}

I would like to know how can I scale that image after I crop it from from spriteme1.png

Here is the URL of the example: http://css-tricks.com/examples/CSS-Sprites/Example1After/

So I would like to know if I can make the icons next to Item1,2,3,4 smaller?

This question is related to css css-sprites

The answer is


Use transform: scale(0.8); with the value you need instead of 0.8


This seems to work for me.

If the sprites are in grid, set the background-size to 100% number of sprites across and 100% number of sprites down. Then use background-position -<x*100>% -<y*100>% where x and y are the zero based sprite

In other words if you want the 3rd sprite from the left and 2nd row that's 2 over and 1 down so

background-position: -200% -100%;

For example here's a sprite sheet 4x2 sprites

enter image description here

And here's an example

_x000D_
_x000D_
div {_x000D_
  margin: 3px;_x000D_
  display: inline-block;_x000D_
}_x000D_
.sprite {_x000D_
  background-image: url('https://i.stack.imgur.com/AEYNC.png');_x000D_
  background-size: 400% 200%;  /* 4x2 sprites so 400% 200% */_x000D_
}_x000D_
.s0x0 { background-position:    -0%   -0%; }_x000D_
.s1x0 { background-position:  -100%   -0%; }_x000D_
.s2x0 { background-position:  -200%   -0%; }_x000D_
.s3x0 { background-position:  -300%   -0%; }_x000D_
.s0x1 { background-position:    -0%  -100%; }_x000D_
.s1x1 { background-position:  -100%  -100%; }_x000D_
.s2x1 { background-position:  -200%  -100%; }_x000D_
.s3x1 { background-position:  -300%  -100%; }
_x000D_
<div class="sprite s3x1" style="width: 45px; height:20px"></div>_x000D_
<div class="sprite s3x1" style="width: 128px; height:30px"></div>_x000D_
<div class="sprite s3x1" style="width: 64px; height:56px"></div>_x000D_
<div class="sprite s2x1" style="width: 57px; height:60px"></div>_x000D_
<div class="sprite s3x0" style="width: 45px; height:45px"></div>_x000D_
<div class="sprite s0x1" style="width: 12px; height:100px"></div>_x000D_
_x000D_
<br/>_x000D_
<div class="sprite s0x0" style="width: 45px; height:20px"></div>_x000D_
<div class="sprite s1x0" style="width: 128px; height:45px"></div>_x000D_
<div class="sprite s2x0" style="width: 64px; height:56px"></div>_x000D_
<div class="sprite s3x0" style="width: 57px; height:60px"></div>_x000D_
<br/>_x000D_
<div class="sprite s0x1" style="width: 45px; height:45px"></div>_x000D_
<div class="sprite s1x1" style="width: 12px; height:50px"></div>_x000D_
<div class="sprite s2x1" style="width: 12px; height:50px"></div>_x000D_
<div class="sprite s3x1" style="width: 12px; height:50px"></div>
_x000D_
_x000D_
_x000D_

If the sprites are different sizes you'd need to set the background-size for each sprite to the a percent such that that sprite's width becomes 100%

In other words if image is 640px wide and the sprite inside that image is 45px wide then to get that 45px to be 640px

xScale = imageWidth / spriteWidth
xScale = 640 / 45
xScale = 14.2222222222
xPercent = xScale * 100
xPercent = 1422.22222222%

Then you need to set the offset. The complication of the offset is that 0% is aligned left and 100% is aligned right.

enter image description here

As a graphics programmer, I'd expect an offset of 100% to move the background 100% across the element, in other words entirely off the right side but that's not what 100% means when used with backgrouhnd-position. background-position: 100%; means right aligned. So, the forumla for taking that into account after scaling is

xOffsetScale = 1 + 1 / (xScale - 1)              
xOffset = offsetX * offsetScale / imageWidth

Assume the offset is 31px

xOffsetScale = 1 + 1 / (14.222222222 - 1)
xOffsetScale = 1.0756302521021115
xOffset = offsetX * xOffsetScale / imageWidth
xOffset = 31 * 1.0756302521021115 / 640
xOffset = 0.05210084033619603
xOffsetPercent = 5.210084033619603

Here's a 640x480 image with 2 sprites.

  1. at 31x 27y size 45w 32h
  2. at 500x 370y size 105w 65h

enter image description here

Following the math above for sprite 1

xScale = imageWidth / spriteWidth
xScale = 640 / 45
xScale = 14.2222222222
xPercent = xScale * 100
xPercent = 1422.22222222%

xOffsetScale = 1 + 1 / (14.222222222 - 1)
xOffsetScale = 1.0756302521021115
xOffset = offsetX * xOffsetScale / imageWidth
xOffset = 31 * 1.0756302521021115 / 640
xOffset = 0.05210084033619603
xOffsetPercent = 5.210084033619603

yScale = imageHeight / spriteHEight
yScale = 480 / 32
yScale = 15
yPercent = yScale * 100
yPercent = 1500%

yOffsetScale = 1 + 1 / (15 - 1)
yOffsetScale = 1.0714285714285714
yOffset = offsetY * yOffsetScale / imageHeight
yOffset = 27 * 1.0714285714285714 / 480
yOffset = 0.06026785714285714
yOffsetPercent = 6.026785714285714

_x000D_
_x000D_
div {_x000D_
  margin: 3px;_x000D_
  display: inline-block;_x000D_
}_x000D_
.sprite {_x000D_
  background-image: url('https://i.stack.imgur.com/mv9lJ.png');_x000D_
}_x000D_
.s1 {_x000D_
  background-size:      1422.2222% 1500%;_x000D_
  background-position:  5.210084033619603% 6.026785714285714%;_x000D_
}_x000D_
.s2 {_x000D_
  background-size:      609.5238095238095% 738.4615384615385%;_x000D_
  background-position:  93.45794392523367% 89.1566265060241%;_x000D_
}
_x000D_
<div class="sprite s1" style="width: 45px; height:20px"></div>_x000D_
<div class="sprite s1" style="width: 128px; height:30px"></div>_x000D_
<div class="sprite s1" style="width: 64px; height:56px"></div>_x000D_
<div class="sprite s1" style="width: 57px; height:60px"></div>_x000D_
<div class="sprite s1" style="width: 45px; height:45px"></div>_x000D_
<div class="sprite s1" style="width: 12px; height:50px"></div>_x000D_
<div class="sprite s1" style="width: 50px; height:40px"></div>_x000D_
<hr/>_x000D_
<div class="sprite s2" style="width: 45px; height:20px"></div>_x000D_
<div class="sprite s2" style="width: 128px; height:30px"></div>_x000D_
<div class="sprite s2" style="width: 64px; height:56px"></div>_x000D_
<div class="sprite s2" style="width: 57px; height:60px"></div>_x000D_
<div class="sprite s2" style="width: 45px; height:45px"></div>_x000D_
<div class="sprite s2" style="width: 12px; height:50px"></div>_x000D_
<div class="sprite s2" style="width: 50px; height:40px"></div>
_x000D_
_x000D_
_x000D_


Try this: Stretchy Sprites - Cross-browser, responsive resizing/stretching of CSS sprite images

This method scales sprites 'responsively' so that the width/height adjust according to your browser window size. It doesn't use background-size as support for this in older browsers is non-existent.

CSS

.stretchy {display:block; float:left; position:relative; overflow:hidden; max-width:160px;}
.stretchy .spacer {width: 100%; height: auto;}
.stretchy .sprite {position:absolute; top:0; left:0; max-width:none; max-height:100%;}
.stretchy .sprite.s2 {left:-100%;}
.stretchy .sprite.s3 {left:-200%;}

HTML

<a class="stretchy" href="#">
  <img class="spacer" alt="" src="spacer.png">
  <img class="sprite" alt="icon" src="sprite_800x160.jpg">
</a>
<a class="stretchy s2" href="#">
  <img class="spacer" alt="" src="spacer.png">
  <img class="sprite" alt="icon" src="sprite_800x160.jpg">
</a>
<a class="stretchy s3" href="#">
  <img class="spacer" alt="" src="spacer.png">
  <img class="sprite" alt="icon" src="sprite_800x160.jpg">
</a>

Well I think found a simpler solution for scaling images : example - lets say there is an image with 3 equal sized sprites which you would want to use, use CSS to scale the image

background-size : 300% 100%;

and then specify the custom height and width that needs to be applied to your html element eg:

 width :45%;
 height:100px;

A sample code would look something like this :

.customclass {
    background: url("/sample/whatever.png") 0 0 no-repeat ;
    background-size : 300% 100%;
    width :45%;
    height:100px;
}

im pretty new to css ,and styling is not my best area this could be a wrong way of doing it.. but it worked for me in Firefox/Chrome/Explorer 10 ,hope it works in older versions too..


transform: scale(); will make original element preserve its size.

I found the best option is to use vw. It's working like a charm:

https://jsfiddle.net/tomekmularczyk/6ebv9Lxw/1/

_x000D_
_x000D_
#div1,_x000D_
#div2,_x000D_
#div3 {_x000D_
  background:url('//www.google.pl/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png') no-repeat;_x000D_
  background-size: 50vw;   _x000D_
  border: 1px solid black;_x000D_
  margin-bottom: 40px;_x000D_
}_x000D_
_x000D_
#div1 {_x000D_
  background-position: 0 0;_x000D_
  width: 12.5vw;_x000D_
  height: 13vw;_x000D_
}_x000D_
#div2 {_x000D_
  background-position: -13vw -4vw;_x000D_
  width: 17.5vw;_x000D_
  height: 9vw;_x000D_
  transform: scale(1.8);_x000D_
}_x000D_
#div3 {_x000D_
  background-position: -30.5vw 0;_x000D_
  width: 19.5vw;_x000D_
  height: 17vw;_x000D_
}
_x000D_
<div id="div1">_x000D_
  </div>_x000D_
  <div id="div2">_x000D_
  </div>_x000D_
  <div id="div3">_x000D_
  </div>
_x000D_
_x000D_
_x000D_


Here's what I did to do this. Keep in mind it won't work on IE8 and below.

#element {
  width:100%;
  height:50px;
  background:url(/path/to/image.png);
  background-position:140.112201963534% 973.333333333333%;
}

The background image's width will scale down as the parent of #element scales down. You can do the same with its height, too, if you convert height to a percentage. The only tricky bit are figuring out the percentages for background-position.

The first percentage is the width of the targeted area of the sprite when at normal width divided by the sprite's total width, and multiplied by 100.

The second percentage is the height of the targeted area of the sprite before being scaled divided by the sprite's total height, and multiplied by 100.

The wording on those two equations is a little sloppy, so let me know if you need me to explain it better.


Old post, but here's what I did using background-size:cover; (hat tip to @Ceylan Pamir)...

EXAMPLE USAGE
Horizontal circle flipper (hover on front side image, flips to back with different image).

EXAMPLE SPRITE
480px x 240px

EXAMPLE FINAL SIZE
Single image @ 120px x 120px

GENERIC CODE
.front {width:120px; height:120px; background:url(http://www.example.com/images/image_240x240.png); background-size:cover; background-repeat:no-repeat; background-position:0px 0px;}

.back {width:120px; height:120px; background:url(http://www.example.com/images/image_240x240.png); background-size:cover; background-repeat:no-repeat; background-position:-120px 0px;}

ABBREVIATED CASE FIDDLE
http://jsfiddle.net/zuhloobie/133esq63/2/


Use transform: scale(...); and add matching margin: -...px to compensate free space from scaling. (you can use * {outline: 1px solid}to see element boundaries).


When you use sprites, you are limited to the dimensions of the image in the sprite. The background-size CSS property, mentioned by Stephen, isn't widely supported yet and might cause problems with browsers like IE8 and below - and given their market share, this isn't a viable option.

Another way to solve the problem is to use two elements and scale the sprite by using it with an img tag, like this:

<div class="sprite-image"
     style="width:20px; height:20px; overflow:hidden; position:relative">
    <!-- set width/height proportionally, to scale the sprite image -->
    <img src="sprite.png" alt="icon"
         width="20" height="80"
         style="position:absolute; top: -20px; left: 0;" />
</div>

This way, the outer element (div.sprite-image) is cropping a 20x20px image from the img tag, which acts like a scaled background-image.


2018 here. Use background-size with percentage.

SHEET:

This assumes a single row of sprites. The width of your sheet should be a number that is evenly divisible by 100 + width of one sprite. If you have 30 sprites that are 108x108 px, then add extra blank space to the end to make the final width 5508px (50*108 + 108).

CSS:

.icon{
    height: 30px;  /* Set this to anything. It will scale. */
    width: 30px; /* Match height. This assumes square sprites. */
    background:url(<mysheeturl>);
    background-size: 5100% 100%; /*  5100% because 51 sprites. */
}

/* Each image increases by 2% because we used 50+1 sprites. 
   If we had used 20+1 sprites then % increase would be 5%. */

.first_image{
    background-position: 0% 0;
}

.ninth_image{
    background-position: 16% 0; /* (9-1) x 2 = 16 */
}

HTML:

<div class ="icon first_image"></div>
<div class ="icon ninth_image"></div>

try using background size: http://webdesign.about.com/od/styleproperties/p/blspbgsize.htm

is there something stopping you from rendering the images at the size you want them in the first place?


Set the width and height to wrapper element of the sprite image. Use this css.

{
    background-size: cover;
}

It took me a while to create a solution to this problem I was happy with:

Problem:

  • An SVG sprite of icons - say 80px x 3200px

  • We want to scale each use of them in content selectors (:before/:after) in various places over various sizes without re-defining the co-ords of each sprite based on the size used.

So this solution allows you to use the same sprite co-ords in a <button> as a <menuitem> whilst still scaling it.

[data-command]::before {
    content: '';
    position: absolute;
    background-image: url("images/sprite.svgz");
    background-repeat: no-repeat;
    background-size: cover;
}

button[data-command]::before {
  width: 32px;
  height: 32px;
}

menuitem[data-command]::before {
  width: 24px;
  height: 24px;
}

[data-command="cancel"]::before {
  background-position: 0% 35%;
}

[data-command="logoff"]::before {
  background-position: 0% 37.5%;
}

By using percentages (to 2 decimal places) in background-position rather than background-size as suggested by others here, you can scale the same icon declaration to any size, without needing to redeclare it.

The position-y percentage is the original sprite height/icon height as a % - in our case here 80px*100/3200px == each sprite is represented by a y-position of 2.5%.

If you have hover/mouseover states you can double the width of the sprite and specify in the position-x coordinate.

The disadvantage of this approach is that adding more icons at a later date will change the sprite height and so y-position %, but if you don't do that then your sprite co-ordinates will need change for each scaled resolution you require.


You could use background-size, as its supported by most browsers (but not all http://caniuse.com/#search=background-size)

background-size : 150% 150%;

Or

You can use a combo of zoom for webkit/ie and transform:scale for Firefox(-moz-) and Opera(-o-) for cross-browser desktop & mobile

[class^="icon-"]{
    display: inline-block;
    background: url('../img/icons/icons.png') no-repeat;
    width: 64px;
    height: 51px;
    overflow: hidden;
    zoom:0.5;
    -moz-transform:scale(0.5);
    -moz-transform-origin: 0 0;
}

.icon-huge{
    zoom:1;
    -moz-transform:scale(1);
    -moz-transform-origin: 0 0;
}

.icon-big{
    zoom:0.60;
    -moz-transform:scale(0.60);
    -moz-transform-origin: 0 0;
}

.icon-small{
    zoom:0.29;
    -moz-transform:scale(0.29);
    -moz-transform-origin: 0 0;
}

Easy... Using two copies of same image with different scale on the sprite's sheet. Set the Coords and size on the app's logic.