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
And here's an example
div {
margin: 3px;
display: inline-block;
}
.sprite {
background-image: url('https://i.stack.imgur.com/AEYNC.png');
background-size: 400% 200%; /* 4x2 sprites so 400% 200% */
}
.s0x0 { background-position: -0% -0%; }
.s1x0 { background-position: -100% -0%; }
.s2x0 { background-position: -200% -0%; }
.s3x0 { background-position: -300% -0%; }
.s0x1 { background-position: -0% -100%; }
.s1x1 { background-position: -100% -100%; }
.s2x1 { background-position: -200% -100%; }
.s3x1 { background-position: -300% -100%; }
<div class="sprite s3x1" style="width: 45px; height:20px"></div>
<div class="sprite s3x1" style="width: 128px; height:30px"></div>
<div class="sprite s3x1" style="width: 64px; height:56px"></div>
<div class="sprite s2x1" style="width: 57px; height:60px"></div>
<div class="sprite s3x0" style="width: 45px; height:45px"></div>
<div class="sprite s0x1" style="width: 12px; height:100px"></div>
<br/>
<div class="sprite s0x0" style="width: 45px; height:20px"></div>
<div class="sprite s1x0" style="width: 128px; height:45px"></div>
<div class="sprite s2x0" style="width: 64px; height:56px"></div>
<div class="sprite s3x0" style="width: 57px; height:60px"></div>
<br/>
<div class="sprite s0x1" style="width: 45px; height:45px"></div>
<div class="sprite s1x1" style="width: 12px; height:50px"></div>
<div class="sprite s2x1" style="width: 12px; height:50px"></div>
<div class="sprite s3x1" style="width: 12px; height:50px"></div>
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.
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.
- at 31x 27y size 45w 32h
- at 500x 370y size 105w 65h
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
div {
margin: 3px;
display: inline-block;
}
.sprite {
background-image: url('https://i.stack.imgur.com/mv9lJ.png');
}
.s1 {
background-size: 1422.2222% 1500%;
background-position: 5.210084033619603% 6.026785714285714%;
}
.s2 {
background-size: 609.5238095238095% 738.4615384615385%;
background-position: 93.45794392523367% 89.1566265060241%;
}
<div class="sprite s1" style="width: 45px; height:20px"></div>
<div class="sprite s1" style="width: 128px; height:30px"></div>
<div class="sprite s1" style="width: 64px; height:56px"></div>
<div class="sprite s1" style="width: 57px; height:60px"></div>
<div class="sprite s1" style="width: 45px; height:45px"></div>
<div class="sprite s1" style="width: 12px; height:50px"></div>
<div class="sprite s1" style="width: 50px; height:40px"></div>
<hr/>
<div class="sprite s2" style="width: 45px; height:20px"></div>
<div class="sprite s2" style="width: 128px; height:30px"></div>
<div class="sprite s2" style="width: 64px; height:56px"></div>
<div class="sprite s2" style="width: 57px; height:60px"></div>
<div class="sprite s2" style="width: 45px; height:45px"></div>
<div class="sprite s2" style="width: 12px; height:50px"></div>
<div class="sprite s2" style="width: 50px; height:40px"></div>