Reduce Image Requests with CSS Sprites: Optimizing Social Media Icons for Performance

Edo Cuadrado

Eduardo Cortez

1 October, 2025

Css sprites

Every image you load creates a request to the server. Even if HTTP/2/3 reduces that overhead, fewer requests still mean:


  • Faster page loads
  • Less decoding overhead
  • Smoother performance


One tried-and-true technique for this is called a CSS sprite: combining many small icons into a single image, then showing the right piece with CSS. In this article we’ll:


  • Build a social media icon sprite
  • Scale icons cleanly
  • Tint icons with CSS masks
  • Use hover states with one request
  • Wrap it all in a reusable vanilla JS component


Our Example Sprite: 3×3 Social Media Grid


We’ll use a 120×120 PNG sprite (iconos.png) with 9 icons (40×40 each) in a 3×3 grid:


Download the sprite (PNG)


Icons: LinkedIn, Instagram, Google | GitHub, Figma, Facebook | Clubhouse, Discord, Dribbble.




Option A — Classic background-position



HTML
<i class="sicon sicon--linkedin"></i>
<i class="sicon sicon--instagram"></i>
<i class="sicon sicon--google"></i>



CSS
:root {
  --icon-size: 40px;
  --sprite-cols: 3;
  --sprite-rows: 3;
  --sprite-url: url('/assets/iconos.png');
}


.sicon {
  display:inline-block;
  width:var(--icon-size);
  height:var(--icon-size);
  background-image:var(--sprite-url);
  background-repeat:no-repeat;
  background-size: calc(var(--sprite-cols) * var(--icon-size))
                   calc(var(--sprite-rows) * var(--icon-size));
  background-position:
    calc(var(--col,0) * -1 * var(--icon-size))
    calc(var(--row,0) * -1 * var(--icon-size));
}


.sicon--linkedin  { --col:0; --row:0; }
.sicon--instagram { --col:1; --row:0; }
.sicon--google    { --col:2; --row:0; }


Scaling: override --icon-size.



Option B — Tint Icons with CSS Masks

CSS
.sicon-mask {
  width: var(--icon-size);
  height: var(--icon-size);
  background-color: currentColor;
  -webkit-mask-image: var(--sprite-url);
  mask-image: var(--sprite-url);
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
  -webkit-mask-size: calc(3 * var(--icon-size)) calc(3 * var(--icon-size));
  mask-size: calc(3 * var(--icon-size)) calc(3 * var(--icon-size));
  -webkit-mask-position:
    calc(var(--col,0) * -1 * var(--icon-size))
    calc(var(--row,0) * -1 * var(--icon-size));
  mask-position:
    calc(var(--col,0) * -1 * var(--icon-size))
    calc(var(--row,0) * -1 * var(--icon-size));
}


HTML
<i class="sicon-mask sicon--instagram" style="color:#E1306C"></i>


Option C — Hover States with Sprites


A neat benefit of sprites: hover states cost zero extra requests.

Place two icon states (default + hover) stacked vertically in the same cell height, then switch background-position on hover.


Example: normal LinkedIn icon above, hover state below in the sprite.



CSS
.sicon--linkedin {
  --col:0;
  --row:0; /* default */
}
.sicon--linkedin:hover {
  --row:1; /* hover state right below */
}


That way, you only load one file for both states, keeping performance high and alignment pixel-perfect.



Option D — A Reusable JS Component


You don’t need to calculate positions by hand. Here’s a vanilla JS custom element <sprite-icon> and a utility for dataset attributes.


(We covered the full code earlier with accessibility fixes, fallbacks, and input guards — see snippet in article body.)



Usage:


HTML

<sprite-icon src="/assets/iconos.png" cols="3" rows="3" col="1" row="0" size="24"></sprite-icon>
<sprite-icon src="/assets/iconos.png" cols="3" rows="3" col="1" row="0" size="24" mode="mask" tint="#E1306C"></sprite-icon>


Accessibility


  • Decorative icons → aria-hidden="true
  • Meaningful icons → add role="img" + aria-label="LinkedIn"


Our JS component auto-handles this correctly.




Conclusion


Reducing requests is still a core web performance win. CSS sprites—though an older name—remain a simple, powerful tool for icons:


  • One request for many graphics
  • Easy scaling and theming
  • Hover states without extra files
  • Simple integration via CSS or reusable JavaScript


If you’re working with a fixed set of raster icons (like social media logos), this is one of the fastest optimizations you can make in 2025.