Is there a better solution than CSS sprites?

2019-05-29 21:25发布

this is not a question about a specific programming problem, it's about examining different concepts. If the moderators don't feel this is ok, delete my question.

I need to display 100 png images in a table td, and the images are 75x16 PNGs. In order to reduce the number of HTTP requests, I grouped all 166 images (only roughly 100 are shown at one time) in a big spritesheet, and have used the IMG tag to display the output, one image at a time. This is the code:

CSS:

.sprites {background-image:url('folder/spritesheet.png');background-color:transparent;background-repeat:no-repeat;display:inline;}
#png3  {height:16px;width:75px;background-position:0px 0;}
#png5  {height:16px;width:75px;background-position:-75px 0;}

PHP:

$classy = "png" . $db_field['imageid'];
echo "<td>" , "<img src='transparent.gif' class='sprites' id='$classy' alt='alt' align='absmiddle'/>" , "</td>";

$classy is a variable which is calling the correct image based on the SQL query output. transparent.gif is a 1px transparent gif. And this is the result, images are shown correctly inside a table:

CSS sprites used to display images inside a table td

The page loading speed increased significantly, maybe 50-60%. In one of my earlier questions some concerns were raised over this being good practice or not. But it works.

The only other solution I've found is using jar compression, but that concept works for Firefox only. This is the code which is used for displaying these same images using jar compression (PHP, no CSS):

$logo = "jar:http://www.website.com/logos.jar!/" . $db_field['imageid'] . ".png";
echo "<tr>" , "<td>" , "<img src='$logo' alt='alt' width='75' height='16'/>";

All of the 166 images are compressed in a jar archive and uploaded to the server, and as jar is a non-solid archive, only the called image is extracted, not all of them. This solution is lighting fast and I've never seen a faster way of displaying that many images. The concept is here and deserves a link. Another advantage over CSS sprites is that with jar each image can be individually optimized for size (e.g one is optimized to 64 colors, another one to 128, 32...depending on the image) and a large spritesheet can not be optimized as it contains a lot of colors.

So, does anyone know of a solution which would be equally fast as jar? If using CSS sprites to display content is bad practice - what is good practice which gives the same result? The key here is the loading speed of the website with as few HTTP requests as possible.

2条回答
做个烂人
2楼-- · 2019-05-29 21:39

I embed small images/icons in the style sheet:

.someicon{
    background-image:url('data:image/png;base64,iVBORw0KGg....');
}

this works with all modern browsers, and does not require me to create sprites (plus it even saves one additional file to load).

In development, the images are defined in the style sheet normally like so:

.someicon{
    background-image:url('../images/someicon.png');
}

and I have a system that generates the final style sheet (including consolidating all CSS into one, minifying and replacing the image reference with the data: url) automatically whenever I make a change to a style sheet.

This works well and saves me a ton of work. When compressed with gzip, the CSS file is not much bigger than the individual files added together. After optimizing the PNG/JPG files, the CSS for my start page is 63K uncompressed. Even with a slightly smaller sprite file, I would probably not save more than a fraction of a second in load time for the average user, so I do not bother with sprites.

查看更多
仙女界的扛把子
3楼-- · 2019-05-29 21:46

Not really an expert on this but I had my share in these thing also

HTTP Requests

Ever heard of the "2 concurrent connections" (recent browsers have around 6-8). Loading a lot of stuff means if 2 are loading at the same time, the others have to wait in line. Loading it in one big chunk is better. This is the main reason why spriting is used. Aside from the connection limit, you manage those "same purpose" images in one image.

Cache

Now, one big chunk I say but you might ask "Does that make it even worse?". Nope, becasue I have an ace up my sleeve and that's where "cache" comes in to play. One page load is all you need, and then, poof! The rest of the pages that need that image are like the speed of light and Saves you from another HTTP request. Never underestimate the power of the cache.

Images

Other things you can do is to optimize your images. I have used Fireworks and I really love it's image optimization tools. To optimize, here are personal guidelines i follow which you can use in your situation:

  • GIFs for icons, JPGs for images, PNGs for transparent stuff.

  • remove unused colors. yes, you can do this in some tools. cuts down size

  • never resize images in the html. have resized versions instead.

  • lose quality. yes, there is such thing. lower your image quality to reasonable limits. losing it too much makes your image too "cloudy" or "blocky"

  • progressive loading images. What it does is it "fast-loads" a blurred image then clears it up later.

  • avoid animated images. they are a bloat, not to mention annoying.

Server Tricks

There are connection limits - but that does not prevent you from using other domains or even subdomains! Distribute your content to other domains or subdomains to increase the number your connections. For images, dedicate a subdomain or two for it, like say img1.mysite.com and img2.mysite.com or another domain mysite2.com. not only is it beneficial for your user, it's beneficial to distributing server load.

Another method is using a Content Delivery Network (CDN). CDN has a global network of servers, which contain "cached" versions of your website resources. Like say i'm in Asia, when i view your site with CDN'ed resources, it finds that resource in the server nearest Asia.

Mark-up

Not necessarily related speed and semantics but the use of id should be reserved for more important purposes. If you use ID to mark images for their styles, what if there was another element that needs the same image? IDs need to be unique, they can't be used twice. So i suggest using multiple classes instead.

also, IDs take precedence over classes. to avoid unexpected overrides, use classes. learn more about CSS specificity.

.sprites {
    background-image:url('folder/spritesheet.png');
    background-color:transparent;
    background-repeat:no-repeat;
    display:inline;
    height:16px; /*same width and heights? place them here instead*/
    width:75px;
}
.png3  {
    height:16px; /* in cases you need a different dimension, this will override */
    width:75px;  
    background-position:0px 0;
}
.png5  {
    background-position:-75px 0;
}

$classy = "png" . $db_field['imageid'];
echo <img src='transparent.gif' class='sprites {$classy}' alt='alt' align='absmiddle'/>";
查看更多
登录 后发表回答