Loading...

CSS Image Sprites

Optional Advanced just covered !important — a rare override flag. This session is a different optional topic: image sprites. You will see them in older stylesheets and some legacy icon sets. The idea is simple: one picture file, many icons, with background-position choosing which tile peeks through a small window.

Direct answer

A CSS image sprite is a single sheet image that stores several icons (or button states) side by side. Each UI element gets a fixed width and height, the same background-image, and a background-position that slides the sheet until the wanted tile fills that box. Sprites cut request counts in the old “one file per icon” web. For new work, prefer SVG icons, inline SVG, or a small icon system — keep sprites when you maintain an existing sheet or must match a legacy design.

Why sprites existed

Years ago, every icon often meant another HTTP round-trip. Combining twenty tiny PNGs into one sheet meant one download and one cache entry. Browsers then painted different “windows” onto that sheet with CSS. HTTP/2 and modern bundling reduced that pain, and scalable vector icons usually look sharper — but the positioning pattern is still useful literacy when you open old CSS.

The three pieces

You need:

  1. One sheet — e.g. icons.png with tiles laid out in a row or grid
  2. A box — width and height matching one tile (often with display: inline-block or a block link)
  3. An offset — background-position so the correct tile sits under the box
    background-repeat: no-repeat keeps the sheet from tiling. You are not loading a separate file per icon; you are cropping by position.

First tile on a shared sheet

Imagine a sheet where each icon is 32×32 pixels. The first icon sits at the top-left. The element’s box is 32×32, and the background starts at 0 0:

First icon tile from a shared sheet

css
.icon {
display: inline-block;
width: 32px;
height: 32px;
background-image: url("icons.png");
background-repeat: no-repeat;
background-position: 0 0;
}

The box acts like a viewport. Only the top-left 32×32 of icons.png is visible. The rest of the sheet is there — just clipped by the element’s size.

Second icon: slide the sheet

If the next icon starts 32px to the right, move the background left by 32px (negative X). Same image, same box size, different window:

Second icon with a horizontal offset

css
.icon-home {
display: inline-block;
width: 32px;
height: 32px;
background-image: url("icons.png");
background-repeat: no-repeat;
background-position: 0 0;
}

.icon-search {
display: inline-block;
width: 32px;
height: 32px;
background-image: url("icons.png");
background-repeat: no-repeat;
background-position: -32px 0;
}

Negative X pulls the sheet left so the second tile fills the window. A second row of icons would also change the Y value (for example -32px -32px). Measure from your real sheet — do not guess offsets from memory.

Hover from another tile

Button sets often put default and hover (or active) states on the same sheet. On :hover, change only background-position:

Hover state from another sprite tile

css
.btn-icon {
display: inline-block;
width: 40px;
height: 40px;
background-image: url("btn-sheet.png");
background-repeat: no-repeat;
background-position: 0 0;
}

.btn-icon:hover {
background-position: -40px 0;
}

No second image file — just another crop. Keep the box size stable so the control does not jump.

Calm sheet habits

Always pair the sheet with an explicit box and no-repeat. Name classes by role, not by pixel math alone:

Named sprite roles and no-repeat

css
.sprite {
display: inline-block;
background-image: url("icons.png");
background-repeat: no-repeat;
}

.sprite--mail {
width: 24px;
height: 24px;
background-position: 0 -48px;
}

.sprite--bell {
width: 24px;
height: 24px;
background-position: -24px -48px;
}

Document the tile grid in a short comment (tile size, row order) so the next maintainer is not reverse-engineering magic numbers.

Sprites then vs icons now

📊 Sprite sheets vs modern icon approaches

Approach Best when Watch out
CSS image sprite (PNG sheet) Legacy UI you must keep; one cached sheet already in the project Raster scales poorly; offsets break if the sheet changes
Inline SVG / SVG sprite Crisp UI icons at any size; easy theming with currentColor Slightly more markup or build setup
Icon font Very old stacks that already ship one Accessibility and ligature quirks; harder to theme than SVG
Separate PNG per icon Rare one-off graphics Many requests on old HTTP/1 connections
Real <img> photos Content images, galleries, product shots Not a job for background-position sprites

Image gallery and responsive images lessons use real <img> (flex thumbs, object-fit, srcset). Sprites are usually decorative chrome in the background — not a substitute for meaningful content pictures with alt text.

Prefer modern icons for new UI

For a fresh interface, start with SVG (inline or a small SVG sprite system). You get sharper edges, simpler color changes, and no fragile pixel offsets. Reach for a classic PNG sprite only when the design pack is already a sheet, or when you are patching CSS that already depends on one.

When a sprite is the wrong tool

css
/* Content photo — use <img>, not a sprite crop */
.hero-photo {
max-width: 100%;
height: auto;
}

/* UI chrome — sprite OK only if the sheet already exists */
.toolbar .icon-save {
width: 16px;
height: 16px;
background-image: url("legacy-toolbar.png");
background-repeat: no-repeat;
background-position: -64px 0;
}

Try it yourself

  1. Sketch a 3-icon row on paper (or open a real sprite). Note tile width (e.g. 32px).
  2. Create .icon-a with background-position: 0 0 and a matching box.
  3. Add .icon-b with -32px 0 (or your real second offset).
  4. Add a hover rule that moves to a third tile without changing width/height.
  5. Write one sentence in a comment: why this sheet still exists (legacy) or why you would use SVG instead next time.

Common mistakes

  • Putting content photos in a sprite and losing proper alt / semantics
  • Forgetting width and height so the whole sheet shows or nothing crops cleanly
  • Using positive offsets when you meant to slide the sheet the other way
  • Leaving background-repeat on so tiles duplicate inside the box
  • Building a brand-new app on PNG sprites by default instead of SVG
  • Copying offsets from a tutorial without measuring your sheet

Summary

  • A sprite is one sheet; background-position chooses which tile fills a fixed box
  • Historically this reduced HTTP requests for many tiny icons
  • Keep no-repeat, stable sizes, and named roles; document the grid
  • Prefer SVG (or similar) for new UI; keep sprites for legacy sheets
  • Content images stay real <img> — galleries and responsive images are a different job
  • Optional Advanced continues next with multiple columns (multi-column)

🧠 Test Your Knowledge

Ready to Start

Test Your Knowledge

Challenge yourself with this interactive quiz and see how well you understand the topic

❓
7
Questions
🎯
70%
To Pass
♾️
∞
Time
🔄
∞
Attempts

📝 Instructions

  • Read each question carefully
  • Select the best answer for each question
  • You can retake the quiz as many times as you want
  • Your progress will be shown at the top