jacques.io

Performant CSS Sprite Sheets in React

February 21, 2020

My original implementation for rendering for a single tile was causing performance issues. It was slow because whenever the client added a row (scrolling to the next row/column), there was some lag as it read the 250kb image from the cache for each new tile. This caused my game to drop frames unless the entire (small) map was already on screen. The offending code was something like this:

MapTile.js

import React from react;

export const MapTile = props => (
  <div
    style={{
      // ...
      background: `url(${props.tileset})
        -${props.tileX * TILE_SIZE}px
        -${props.tileY * TILE_SIZE}px`,
    }}
  />
);

I send a Tiled map from the server to the client. These maps use tilesets, which are large images with hundreds of tiles, so I wanted to implement CSS sprite sheets inside of a React component.

My final solution is this:

  1. Create a CSS file containing all of the tileset names used in tiled. For example:

MapTile.module.css

.tilea {
  background-image: url(/assets/tilea.png);
}
  1. Assign the class to the div that holds the tile sheet and only explicitly specify the backgroundPosition with inline styles.
import React from 'react';
import styles from './MapTile.module.css';

export const MapTile = props => (
  <div
    className={styles[props.tileset]}
    style={{
      // ...
      backgroundPosition: `-${props.tileX}px -${props.tileY}px`,
    }}
  />
);

See it in action on YouTube