There are at least two ways to use an image in CSS:
with an HTTP request;
url(/path/to/image.png)
with a data URL.
url(data:image/png;base64,BASE64_ENCODED_DATA_HERE)
But I was wondering, as base64-encoded data takes 33% more space, therefore 33% more time to load, is it worth it, or should I just make an HTTP request--using a sprite if there're several images?
A separate request is almost always preferable because with data: URIs,
it doesn't work in older IEs and is limited to 32k in IE8
it can be argued that it goes against separation of styling and content
Style sheet files get blown up, which may cause trouble if the browser's developers never expected CSS files to reach these kinds of sizes
I would use it only when there is no other choice.
The web server should take care of the 33 % more space by GZIP-ing all text files so that should not be that big of a problem. This together with reducing the number of HTTP requests (which is very important performance-wise) makes the method worthwhile. Also, the images are still cached but now in the CSS file instead of in separate files.
Preferably the embedding should be done with a build script that inserts the data URIs. That way we don't have to care about large chunks of base64-encoded data when editing the CSS files. Also, remember to have a good solution if images occur more than one time in the file, e.g. re-writing the CSS rules. We don't want the file to be larger than necessary.
There are problems with IE though. IE<=7 can't handle data URIs at all and IE8 can't handle them for larger URIs than 32K. The latter could be solved by simply not embedding too large images (maybe you shouldn't anyway). Regarding IE<=7 the problem can be solved by using MHTML instead and specifying different CSS files for different browsers using IE conditional comments.
Here is a good blog post about embedding images in CSS and how to fix the problems for IE: http://blog.meebo.com/?p=2320
Personally, I would always go with a separate request. I've had trouble in the past with Internet Explorer and data:url images.
It seems IE8 limits url length to 32KB, which is often not enough for images.
Wikipedia on Browser Support
Related
Specifically, does the browser cache only the text content of the stylesheet — so it doesn't have to fetch it again from the network — or does it also cache an internal representation it has of the contained CSS rules after parsing, so neither fetching nor parsing of a cached file is necessary?
If only the text content is cached, what are the benefits of caching a stylesheet over inlining it (where it cannot be cached)?
Caching is aimed at reducing load time by replacing the typically slow network download with the typically fast local file reading. As such, is a generic solution (you can cache any kind of asset, from HTML to CSS, JavaScript, PDFs, Excel...) and it can accomplish great time savings (normally seconds, even minutes for really slow networks). It also plays well with dynamic HTML.
What you propose is a very specific caching solution for a very specific data set (the nodes of an HTML document together with the CSS rules that apply to them) that typically needs milliseconds to process and can be continually changing thanks to JavaScript. It looks really difficult to implement, it'll be confusing for dynamic sites (when a page loads, everybody expects to get the initial HTML state, not whatever you were doing last time) and there's hardly any benefit on it. I'm not aware of any browser that has even tried it. There're certainly JIT compilers for JavaScript code, but nothing remotely similar to this.
If only the text content is cached, what are the benefits of caching a
stylesheet over inlining it (where it cannot be cached)?
I'd say cache itself is a valid benefit, isn't it? Generating inline CSS means more work for the webmaster (you either need to write server-side code that injects CSS files or enjoy the maintenance mess of not even having them). It also increases the size of HTML documents.
Looking at the source of a website today I came across something that surprised me. They had the images included in the css file (see http://static.a.gs-cdn.net/webincludes/css/production-uri.css?20120521.1)
This surprised me, surely loading one large file with all the images embedded would take longer on a modern browser (ie chrome fires off lots a simultaneous requests for the content it needs) and make it harder to debug any css issues. Is that correct and are there any advantages to this approach?
There's nothing really wrong with including images in CSS, although it may be more efficient to use CSS sprites.
It makes sense to use CSS sprites for UI elements (but not content elements) because it reduces the number of HTTP requests.
This is a good article detailing a few of the pros and cons of such an approach.
Pros:
The biggest reason: it saves HTTP Requests. Other than pure document size, this is the #1 factor concerning how fast a page loads. Less = better.
Cons:
It's hard to maintain site with embedded data URIs for everything. It's easier to just update an image and replace it.
You should only use this in documents that are heavily cached, like your CSS should be. Having a CSS file that is 300k instead of 50k is fine if it saves 6 HTTP requests, but only if that CSS file is cached just as well as those images would be.
Personally, I never use it. It saves on HTTP requests, but bloats your CSS with things that are, in my opinion, not appropriate. For a clean separation of concerns, images should be just that - images.
Plus, you'll have a harder time caching all the resources - if you make one change to your CSS, that's all the image data getting re-downloaded for no reason.
I'm building a site with a lot of similar css between pages. I've decided that a good approach would be to have the css generated as strings by php functions (with parameters) and outputed as an internal stylesheet in every page that i serve. The benefits:
this way if i make a change it will reflect throughout the entire site without having to maintain duplicates
i can send only the necessary css for a certain page
it's better than having small css files and sending a lot of css headers at inclusion
the possibility that the content might be displayed before the stylesheet is loaded is gone
i can calculate dimensions by using parameters
i can create a layer that will minify the result received from these functions or serve cached minified css
I haven't seen this done anywhere else unfortunately so i'm thinking that this might be because of SEO. The generated internal stylesheet will be at around 15kb max (before minifying the stylesheet).
I need your opinion on this approach and your thoughts about the impact a long internal stylesheet will have on SEO.
Many thanks.
Not an answer to your question (which is interesting enough!), but most of your arguments for inline CSS are wrong. An external style sheet is always the better and faster solution.
The first point you can handle by adding a version number to the style sheet's file name
The second point is moot because an external file gets cached, so no additional requests
The third point is moot for the same reason
The fourth point won't really matter once the style sheet is cached
The fifth point can be sorted using inline CSS for only the properties that need to be
updated dynamically - usually a tiny fraction of the whole CSS code base
The sixth point I don't get.
Go for an external style sheet. Just make sure it gets served with the correct caching headers!
Like long blocks of inline JavaScript, they are ignored.
Bots look at the content, not the layout. If you want a better representation of what they see, try the Lynx browser.
Unfortunately they will not be cached on the user's browser either, as external CSS and JS are, making each page load slower. It is actually more efficient to have a large external stylesheet than server up related "css snippets" with each page.
Assuming by 'internal stylesheet' you mean inline CSS included using the <style> tag, I'd recommend against this. If you use an external stylesheet, visitors download it once on the first request, and it will then be cached. By including all of your CSS inline, you're adding page weight to every single HTML request.
Although it might seem more efficient to just serve CSS for the current page, or split your CSS into lots of different page-specific stylesheets; in practice it's usually better just to have one stylesheet. Serving this compressed and with appropriate expires headers will almost always be faster than the alternatives.
Regarding SEO, robots ignore CSS, so this won't have any affect. If you had so much CSS that it substantially slowed down loading of your page, in theory you might start having issues, but you would need an inhuman amount of inline CSS before this could even potentially be an issue.
To the extent of my knowledge, your CSS sheet plays a minimal role in SEO, what is more important is your HTML markup and execution.
Following the order of '< h1 > - < h5 >' for your heading tags, with accompanying '< p >' tags instead of '< font >' or similar approaches is what will effect a web crawlers ability to recognise and prioritise the content in your page.
While you can use CSS to hide paragraph that you only want to appear in search engines and similar techniques it has little importance compared to the HTML structure.
All benefits you said apply. Search engines doesn't care too much about CSS and javascript (of course, if your page takes too long to wrap and send, this will affect, but I don't think it is the case).
I've seen this kind of solution before, but people tend to avoid use scripting to serve, once you can use media queries instead, writing just only one external stylesheet. I think you should take a look on this.
However, I see you are trying to optimize the CSS sent. This is good, but talking about 80k for all sheets, makes me think if you are not over complicating the rules.
Well, as last opinion, you can cache many different responses and make use of "canonical" thing on page head.
I have an ASHX handler that I am using to display images that are stored in a database. I display the images as thumbnails and then full size if the user mouses over them.
How can I combine the images at runtime to produce CSS sprites for use in this situation?
If it can be done does anyone have suggestions on where to start?
UPATE
It seems like most people are saying this is not a good situation to use sprites in. I'm new to the sprite concept so please bear with me.
If I am going to be loading 30 thumbnails on a page from my database everytime why would it not make sense to pass them from the server to the client as one large image instead of passing 30 individual images? Wouldn't this be faster? Isn't this the purpose of CSS Sprites?
As far as the browser is concerned, an HTTP resource is an HTTP resource and it is irrelevant if the server produced it by reading a file from a hard disk, taking data out of a database, or spewing the content of a random number generator through an algorithm that would output valid PNG data.
You just need to generate your images from the data as normal.
That said, since the images are content, CSS would be an inappropriate tool to include them in the document. You should use an <img> element.
You have a couple options.
Your handler can combine the images on the fly that it gets from the database and send the whole thing down to the browser.
OR (and I like this one better)
You create the merged image at the time the images are uploaded to your site.
The second is better as the conversion only has to happen once and therefore means that you only have to spend those resources once. It does mean you are essentially storing 2 copies of the image, but that's fine.
UPDATE
I believe I misinterpreted what you were trying to do. I thought you were trying to combine the thumbnail with the full blown image. Instead, you appear to be really asking how to combine all of the thumbnail images.
In that case, it's even more of a bad idea. As David Dorward stated CSS is used to control layout. You're talking about content. However, the semantic issue aside, in the event you want to make tweaks to the layout your going to have to modify your code which creates the sprites to begin with. What if you decide to do 35 images? Or, change that to do 18?
By going the sprite route your pretty well screwed by being forced to modify code for any layout change which is NOT good style.
To cover that last question: wouldn't it be faster? Probably not. Under this scenario you would have to create the sprite on the fly, which introduces server overhead, which slows everything down. At most it might be a wash in the delivery time. At worst, you incur a large server and development performance negative impact.
Check out http://www.RequestReduce.com. It not only creates the sprite file automatically, but it does it on the fly through an HttpModule along with merging and minifying all CSS. It lso optimizes the sprite image using quantization and lossless compression and it handles the serving of the generated files using ETags and Expires headers to ensure optimal browser caching. The setup is trivial involving just a simple web.config change. See my blog post about its adoption by the Microsoft Visual Studio and MSDN Samples gallery.
I completely agree with David. Just a quick note regarding David's last point: That's only if the images are content. However, if they were part of the layout, then CSS would be appropriate.
That said, with this use case, sprites aren't a good choice. One of the purposes of thumbnails is to cut down loading time, which a sprite would make worse for a gallery. A better pattern might be using a lightbox or something similar with two images rather than one, with the larger being requested on demand.
Sprites are not a good solution here.
To answer your update, sprites are ideal for many small images, where the overhead of a new HTTP request outweighs the few bytes being sent for a small png or gif (e.g. 16x16 icons, etc). For larger images the time of the HTTP request becomes less important overall as the download time increases.
Packing images into a sprite also means that they will execute one longer request and other requests will have to queue behind it. If the important thing is to get the thumbnails showing quickly, then make sure those get loaded first before starting to load any larger views of the same images.
Any larger files that don't display at the initial page load should be late-loaded (window.onload) or lazy-loaded (as needed by click or hover actions).
We're being told that fewer HTTP requests per page load is a Good Thing. The extreme form of that for CSS would be to have a single, unique CSS file per page, with any shared site-wide styles duplicated in each file.
But there's a trade off there. If you have separate shared global CSS files, they can be cached once when the front page is loaded and then re-used on multiple pages, thereby reducing the necessary size of the page-specific CSS files.
So which is better in real-world practice? Shorter CSS files through multiple discrete CSS files that are cacheable, or fewer HTTP requests through fewer-but-larger CSS files?
Your first port of call is using YSlow or Google Speed to figure out what is going slowest on your site. Sometimes a badly compressed (large) image or two can be slowing the entire thing down. You are told to reduce HTTP requests because each request has a setup cost associated with it but if taken to the extreme can lead to worse performance. In your case having a CSS file for each page is bad form as it means it is harder for browsers to cache.
Taking one method to the extreme is bad practice and you should attempt to approach this problem from a wide angle such as:
Properly compress images or use CSS sprites (reduces HTTP requests)
Implement proper web caching using Expres, ETag etc (so clients don't have to rerequest everything)
Optimise your CSS and Javascript files using YUI or another similar tool
Improve your CSS / javascript code for performance. Certain CSS selectors can lead to the browser taking longer to render a page
Replace images with pure CSS where possible i.e. background colors etc.
Use GZip compression on any text output i.e. html, css, js
If in doubt, look at the source page for the Google home page. They optimise that page heavily and it will give you good clues on what to do.
I would go for combining all CSS into one single CSS file. Even if you have some redundant styles that won't apply to all pages, after compressing it with Gzip the size should be small enough. And after the browser has cached it, the size no longer matters. Just insert all CSS into one file. However, you have one problem: the styles change for different pages. You have to take another route. You could do, for example, something like:
index.html
<div class="navigation_index"></div>
about.html
<div class="navigation_about"></div>
And then share the similar styles along with the navigation classes like:
.navigation_about, .navigation_index {
color: #000;
}
and specify different options in separate styles:
.navigation_about {
font: sans-serif,
}
.navigation_index {
font: serif,
}
Browsers will cache the css files what ever its big or small, so i prefer making bigger css files with fewer requests.
But this is not a rule, i just try to do that as i can.
well crap, i think theoretically it depends on the site type. If people are going to hit the pages of the site one time, and one time only and theres a lot of pages and such, then having the broken up css files ends up working out better on a graph. Versus a site or web app where everything is getting hit constantly or often enough anyway, then having specialized/compiled css for each page might have a bigger hit at first (on a graph anyway), but then gets cached and you win in the long run b/c of fewer http requests. And then theres some overlap-age there somewhere in the nether regions of mass css hysteria.
Now get away from the graphs and look at your average site, it probably doesn't matter unless you taking on some really serious traffic. But overall ima vote for the latter here.