1 <!-- subject: {CSS} sprites as background -->
2 <!-- date: 2013-05-06 02:46:10 -->
3 <!-- tags: html, css, sprites -->
4 <!-- categories: Articles, Techblog -->
6 <p>CSS sprites aren’t anything new. They have been around for years, and are
7 one of the methods to optimise website’s load time. The idea is to
8 incorporate multiple images into one and in this way decrease number of
9 round trips between the server and the browser.
11 <p>In its traditional use, CSS sprites work as a replacement for images and
12 cannot be used as a background. Alas that is exactly what I wanted to do
13 with a quote and flag icons like the following:
15 <figure><img src=
"/d/sprites-bg-example.webp"
16 style=
"max-width: 75%; box-shadow: 0.25em 0.25em 0.2em #042559; border-radius: 2em"
17 alt=
"Example block quote with a quote icon and two paragraphs with flags" /></figure>
19 <blockquote>Update: This website has evolved slightly since
2013. The flags
20 are no longer used (replaced by content negotiation) and quote sprite icon
21 has been replaced by an SVG. While I no longer use this technique, it is
22 of course still valid.
</blockquote>
24 <p>After some playing around I’ve finally figured out how to get this working.
25 Even though there are some caveats, sprites can be used as a top-left
26 no-repeat background image as well.
32 <p>Let’s start with the basics. Sprites incorporate many images into a bigger
33 one and use CSS to display only what is needed. Take the below image with
34 a roll-over effect for example:
37 #html5 { width:
450px; }
38 #html5, #html5 span { height:
100px; }
40 display: inline-block;
43 background-image: url('/d/html5-sprite.jpg');
50 background-position: -
74px
0;
54 background-position: -
126px
0;
58 background-position: -
216px
0;
62 background-position: -
312px
0;
65 background-position:
0 -
110px;
68 background-position: -
74px -
110px;
71 background-position: -
126px -
110px;
74 background-position: -
216px -
110px;
77 background-position: -
312px -
110px;
80 <div id=html5
><span id=spriteh
>H
</span><span id=spritet
>T
</span><span id=spritem
>M
</span><span id=spritel
>L
</span><span id=sprite5
>5</span></div>
82 <p>A naïve approach would require ten separate images for this effect.
83 Sprites in tandem with CSS allows this number to go dawn to one. HTML code
84 is simple and unimpressive:
87 <div id=
"html5
"><span
88 id=
"spriteh
">H
</span
><span
89 id=
"spritet
">T
</span
><span
90 id=
"spritem
">M
</span
><span
91 id=
"spritel
">L
</span
><span
92 id=
"sprite5
">5</span
></div
></pre>
94 <p>In the absence of styles it simply spells ‘HTML5’ so if stylesheet fails to
95 load, user can still sees the message. To make a picture out of those spans
96 their dimension must be set, text content hidden and background image added.
97 The following is would be a good start:
100 #html5 { width:
500px; }
101 #html5, #html5 span { height:
100px; }
104 display: inline-block;
107 background-image: url('html5-sprite.jpg');
110 #spriteh { width:
74px; }
111 #spritet { width:
52px; }
112 #spritem { width:
90px; }
113 #spritel { width:
96px; }
114 #sprite5 { width:
188px; }
117 <p>So far it’s nothing more than regular ‘replace text with a picture’ CSS
118 trick. Because of that, each span would display the image starting with its
119 top-left corner, end result being a rather repetitive image of the letter
120 ‘H’. The missing ingredient is
<code>background-position
</code> CSS
121 property which instructs the browser to start drawing the background from
122 a different offset. With a bit more styling, the code is almost complete:
125 #spritet { background-position: -
74px
0; }
126 #spritem { background-position: -
126px
0; }
127 #spritel { background-position: -
216px
0; }
128 #sprite5 { background-position: -
312px
0; }
</pre>
130 <p>By default, background image spans an infinite plane repeating indefinitely
131 in all directions. Picture’s top-left corner is aligned with element’s
132 top-left corner producing the backdrop for its contents.
134 <figure><img src=/d/html5-sprite-expl
alt=
""></figure>
136 <p><code>background-position
</code> property specifies the origin point of the
137 background image in element’s coordinate system. In other words, it
138 instructs the browser to shift the image by given amounts and than cut
139 whatever overlaps with the element for the background. By setting position
140 to
<code>-
126px
</code>, the
127th pixel of the background image will be
141 aligned with top-left corner of the element.
143 <p>With that knowledge, getting roll-over effect is now trivial:
146 #spriteh:hover { background-position:
0 -
110px; }
147 #spritet:hover { background-position: -
74px -
110px; }
148 #spritem:hover { background-position: -
126px -
110px; }
149 #spritel:hover { background-position: -
216px -
110px; }
150 #sprite5:hover { background-position: -
312px -
110px; }
</pre>
152 <p>Note that the big image has a ten-pixel gap between sprites. It prevents
153 pixels from adjacent sprites ‘bleeding’ over to the other images.
155 <h2>A bit simpler method
</h2>
157 <p>The above is the normal method of using sprites. In the presented example,
158 there’s an easier way. Instead of setting background image for each
159 individual span element, it’s simpler to set background for the wrapping div
160 element and cover it with span’s only when they are hovered. CSS code for
161 that looks as follows:
164 #html5, #html5 span { height:
100px; }
167 background-image: url('html5-sprite.jpg');
170 display: inline-block;
176 background-position:
0 -
110px;
180 background-position: -
74px -
110px;
184 background-position: -
126px -
110px;
188 background-position: -
216px -
110px;
192 background-position: -
312px -
110px;
195 background-image: url('html5-sprite.jpg');
198 <h2>Using sprites for background
</h2>
200 <p>Finally, we arrive at using sprites as background. The trick here is
201 the
<code>no-repeat
</code> value which causes the background image to be
202 painted only once, for example:
206 background: url('…') no-repeat;
211 <p>In regular sprites, the interesting part of the image is cropped thanks to
212 the limited size of the element. Trying to use an image with multiple
213 sprites as a background would result in whatever is on the right or bottom
214 of the icon to be shown as well.
216 <p>However, if there’s nothing on the right or below the icon, if it is the
217 last thing in the sprites image, the above is no longer an issue. And
218 with
<code>no-repeat
</code> value, we instruct the browser not to wrap
219 around the image thus sprites on the left or top of the image aren’t shown
222 <p>It becomes apparent that using a staircase-like image with nothing but
223 transparent background below the diagonal, sprites
<em>on
</em> the diagonal
224 can be used as a top-left no-repeat background icon.
226 <figure><img src=/d/icon-sprites.webp
alt=
"" id=iconsprites
></figure>
227 <script src=/d/icon-sprites.js
></script>
229 <p>With that knowledge, the following styles can be constructed:
232 blockquote, .plFlag, .enFlag {
233 background: url('/d/s.png') no-repeat;
236 background-position: -
100px
0;
240 background-position: -
50px -
50px;
244 background-position: -
75px -
25px;
248 <p>This technique can be extended in certain situations — either when
249 the height or width of the element is specified. In those
250 situations, more icons can be present either on the right or below
251 the sprite used as a background.
253 <p>Certainly limited, but if there are only a few cases when this
254 method needs to be used, it allows more images to be converted
255 into sprites than previously expected. And it’s what enabled me
256 to convert all but one small images on this site to CSS