Search code examples
ioscssspritescalecss-sprites

What is the proper use of high-res sprites on iOS with CSS?


I am having some serious trouble trying to get my sprites to show up right on a iPhone4+ using a high res (2x) version of my navigation sprite. Here's the code I'm using right now.

.pixelj a, .games a, .team a, .forums a {
    width: 156px;
    height: 35px;
    background-image: url('/assets/blogtext2x.png');
    background-repeat: no-repeat;
/*  background-size: 156px 17px;*/  
    text-indent: -9999px;
    overflow: hidden;
    display: block;
    float: left;
    }

As you can see this is for a navigation where I have all the navigation word elements in a single sprited image. I tried using "background-size" but that just squished the whole sprite into the width/height provided. If I get rid of it it shows the 2x images but doesn't make them 50% so they view correctly.

What am I doing wrong here? Here's the @media query I am using to target high-res devices:

@media (min--moz-device-pixel-ratio: 1.5),
  (-o-min-device-pixel-ratio: 3/2),
  (-webkit-min-device-pixel-ratio: 1.5),
  (min-device-pixel-ratio: 1.5),
  (min-resolution: 1.5dppx),
  (max-device-width: 640px) {

Solution

  • You're absolutely on the right track here.

    Essentially the process here with providing 'retina' graphics in a sprite via CSS is:

    • Set up your normal sprite, with the relevant positioning/etc within your CSS to feed to non-retina devices,
    • Set the background-size of this image,
    • Use a media query to feed the @2x variant of the image to those devices that support it.

    There are a few key things to bear in mind:

    • setting background-size requires several declarations with different vendor prefixes to get the best browser coverage - see my code below to see what I mean
    • background-size is the size of the non-retina variant of the background image, not the size of the element it sits within. So, if the normal-size sprite image is 200px by 400px (and the high-resolution version is 400px by 800px), then it's 200px 400px that you declare.
    • background-size values are declared as <width> <height>.
    • You have to declare background-size in the first declaration, not in the retina media-query overwrite.
    • Although using @2x is becoming common-practice, it's not essential in web development: you could use a totally different image name.

    It's very difficult to help you with your specific question without all the code, or a live URL to look at, but here's a high-level example.

    In this example, I have a background-image which is 100px wide and 50px high which is positioned in the middle of the element

    /* the element */
    .element{
        background: url(../img/site/background-image.png) 50% 50% no-repeat;
    
        /* vendor-specfic declarations for background-size */
        -webkit-background-size: 100px 50px;
        -moz-background-size:  100px 50px;
        -o-background-size:  100px 50px;
        background-size:  100px 50px;
    }
    
    /* for retina users */
    @media screen and (-webkit-min-device-pixel-ratio: 2), 
    screen and (max--moz-device-pixel-ratio: 2),
    screen and (min-device-pixel-ratio: 2){ 
        .element{
            /* we only over-write background-image here */
           background-image: url(../img/site/[email protected]);
        }
    }
    

    This will mean that those devices which fall into the second media query will load the @2x version of the background image, and will scale it to the background-size dimensions as declared.

    Because the image is scaled back to the dimensions you set, if you're using sprites you only have to declare all the element's background-positions once as you usually would, and not twice to account for the larger retina graphic dimensions.

    EDIT: Having now seen your site, I can see exactly the problem you're having with your navigation:

    Screenshot

    The reason it looks like this is your CSS here (line 972 of style2.css):

    .pixeljam a, .games a, .team a, .forums a {
        background: no-repeat url('/assets/blogtext2x.png');
    }
    

    If you change that to background-image and remove the no-repeat, then it will work (otherwise background resets your previous background positions).

    .pixeljam a, .games a, .team a, .forums a {
        background-image: url('/assets/blogtext2x.png');
    }