Search code examples
htmlcsscss-sprites

How to deal with CSS sprite (using background-position) issue causing blurry images on mobile devices?


Firstly, when using CSS with normal image, we set width:50px and this applies OK on both desktop and mobile devices (of course the image quality and natural size is high enough).

However when using CSS sprite with a simple trick with background-position, with that same size (width of 50px), the displayed image will be blurry (due to scaling or something like that).

I know that we must provide a better spritesheet image (with larger size of course). But in that case the width:50px will not work, I mean it must be some larger value as well. I don't know how to determine that value. Because as I said at first, any box/element having width of 50px will be dealt by the mobile devices somehow automatically. If I set a larger value, the result image may have a larger size unexpectedly (although the quality may be as desired).

.item {
    background: url(/sprites.png) 0px 0px;
    width: 50px;
    ...
}

How could you deal with this problem?


Solution

  • For anyone caring about a solution that uses PNG sprites, this is exactly what you can do. To help render the sprites smoothly on mobile (as well as high DPI screen) devices we need a larger image (about x2 the sizes, e.g: the normal screen requires a spritesheet width of 500px, you need at least another one with width of 1000px).

    All the background-position and background-size are the same on all devices (mobiles & desktop pcs), the only difference here is the background-image. On desktop pcs you can use the normal (small) spritesheet whereas on mobiles you can use the larger one (as mentioned above).

    Here are the 2 snippets of CSS code applied for desktop pcs & mobiles:

    This is the common CSS:

    .item {
       background-position: 0px 0px;
       background-size: 500px 300px;
       background-repeat: no-repeat;
    }
    

    This is applied for desktop pcs:

    .item {
       background-image: url(your_normal_sprites_500.png);
    }
    

    This is applied for mobiles:

    .item {
       background-image: url(your_large_sprites_1000.png);
    }
    

    To switch the style/css programmatically for desktop/mobiles, we can take the benefit of window.devicePixelRatio. This is not supported on some old browsers, but it should be available on most popular modern browsers now.

    var isHiResScreen = (window.devicePixelRatio || 1) > 1;
    if(isHiResScreen){
       //pick style for mobile
    }
    else {
       //pick style for desktop pc
    }
    

    Of course you should consider using SVG spritesheet instead if possible as @Dejan.S has mentioned in his comments (and of course I've known about this thanks to him). It's very promising :)