开发者

Why do all browsers download all CSS files - even for media types they don't support?

If I specify a CSS link with an unsupported media type ("bork") it still gets downloaded by every browser I've tried (including both desktop and several mobile browsers).

<link href="bork.css" media="bork" rel="stylesheet" type="text/css" />

And it gets worse...

If the file bork.css @imports an other CSS file (also with an unsupported media type) that second CSS file also gets downloaded.

/* Inside "bork.css" */
@import url("bork2.css") bork, bork;

Why!?

My first assumption was that some browsers might be searching for nested @imports or @media blocks with media types that they supported - and then apply the styling rules contained within those files...

/* Inside "bork2.css" */
@import url("all.css");
@media all {
  /* rules */
}

...but as far s I can tell, not a single browser does that. (Fortunately, as that would be a bug.)

So all this downloading seems wholly redundant - unl开发者_如何学Pythoness there's some explanation that I've missed all along.

EDIT: What I'm trying to understand is that motivates browser makers to go:

"Hey! We're trying to make our browser crazy fast! Let's download a bunch of CSS files that we have no intention of applying, and halt the loading of other resources meanwhile!"


I think the answer is this:

Browsers are allowed and encouraged to parse media descriptors - no matter what the descriptor - as a way to make them future friendly

Future versions of HTML may introduce new values and may allow parameterized values.

*From: http://www.w3.org/TR/html4/types.html#h-6.13

In this way, media may one day include 3d-glasses or other descriptors, including bork ;-)

EDIT:

The latest CSS3 spec on media queries says this, which supports the above, to a certain degree:

Unknown media types evaluate to false. Effectively, they are treated identically to known media types that do not match the media type of the device.

*From: http://dev.w3.org/csswg/css3-mediaqueries/#error-handling

So they are treated as known and downloaded to be used, just not at that time/for that device.


Thinking that the real reason that they load all media queries is because many devices CHANGE their responses to these queries after load.

Imaging an iPhone5 that is in portrait on page load (reporting 'width' as 640px, but not 'portrait, unfortunately the iSeries do not support those queries)... you then decide to turn the iPhone sideways, and the browser now activates the pseudo landscape mode (again, triggered from width @ 1126 rather than 'landscape').

Most likely, a responsive web design has been designed to feed different stylesheets to a browser displaying at 640 (rather narrow, probably a phone/tablet) than it does to a browser displaying at 1126 (more likely a laptop).

If it hadn't bothered to load the additional media query sheets, then it would suddenly have to stop, shoot an http request out, wait for the sheet to load, and then parse it to display. This could result in a rather ugly delay.

As most browsers follow a pattern of code reuse, and the core chunks of Webkit or Gecko, for example, may not be aware whether they are on a laptop or a tablet (as if those lines aren't beginning to blur anyway), it simply loads each media query regardless of whether or not they choose to display it.

While this saves each browser from looking bad, overall it breaks a good chunk of the utility behind media queries.

A cell phone or a cheap android tablet shouldn't have to download the additional files (especially on limited data plans) that it will simply never need.

At the moment, my designs DO use media queries, but I use them sparingly. Much of the media queryishness on my sites is implemented through javascript loading of required files to eliminate this waste. The remaining queries are used in cases of javascript being shut off, or for sheets that need to be loaded 'just in case' (my 640px layout, for example, is usually always loaded, as most devices might display it in one situation or another).

If anyone out there has a better, cleaner, method of handling this, please let me know.

In the meantime, if you can think of a simply to implement functionality that might circumvent this (maybe android-style manifests built into browsers?), you might want to drop a line to the Mozilla or Chromium teams... seem like they could use a hand on this one.


After thinking about this more, I formed the theory that there might be a general "rule" at work - that any stylesheet, image or script would be downloaded, no questions asked, regardless of the specified mime-type or media attribute.

However, after a quick test, the results are a bit ambigious...

  1. <script src="bork.js" type="bork/bork"></script>
  2. <script src="bork2.js" type="text/bork"></script>

Chrome 12 downloads neither.
IE8 downloads #2.
Firefox 4 downloads both.
Opera 11 downloads both.
Safari 5 Win downlads both.

Still no parsing or running takes place in any of the browsers. A javascript alert(); inside either file does not run. And this is slightly different from the CSS loading case, because there the browsers parse the bork-media CSS code for @include directives and downloads those resources recursively.


The answer may come down to media queries. Consider these for example:

<link rel="stylesheet" media="(min-width: 300px)" href="example1.css" />
<link rel="stylesheet" media="(min-width: 1000px)" href="example2.css" />

If a browser with a window size of 600px is used, the example1.css stylesheet will be applied. If the window is resized to 1200px then the stylesheet example2.css can be immediately applied without waiting for it to download first.

Its worth noting that even though the non-matching media query stylesheet is still downloaded, it does not block rendering while it is downloading (normally all CSS files need to be downloaded before rendering will begin).


Sometimes, it's necessary to consider the prosaic answer. It's possible that all stylesheets are downloaded by browsers simply because the authors of each browser only really consider the case where there is a single (master) stylesheet when optimizing for speed, and the practice of a lot of sites of having a single stylesheet encourages this behavior. If nobody is testing for it, it's almost certainly not a case that's being optimized, as people prefer to work on results that are visible (or at least measurable). Maybe your question will encourage someone to change the testing regime…

Also, I'd venture that the overwhelming majority of sites' stylesheets are static documents, and so capable of being very highly cached (and delivered by CDN too, if the site owners choose to pay).


The only logical reason I can think of is that when you are changing dynamically (javascript) the faulty attribute's value of the <link> element to a recognized one, the file must be available immediately.
In fact in certain cases it could be considered a feature if you wanna load the file but defer its appliance for later.


So if you really do not want to download the CSS file until something happens, the you can try to validate when the page loads if certain conditions are meet and if so, then you can do a "lazy load" and store the commented code (type 8 element, that would be in this case your style tag) inside a newly created style tag child, and that will make the browser to validate the newly created content and will download the CSS file for the style to work.

Any question you may face trying to implement it, do not hesitate in asking some clarification, maybe i can help you with your problem. It works for almost anything (images, js, css, etc..) you do not want to be downloaded or processed until something occurs or some restrictions are meet.

I already tested it and IT WORKS :D, so you can use this code to start, hope it helps

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>TEST CODE</title>
<script type="text/javascript"> 

    function test(){
        var elems = document.body.childNodes;
        alert(elems);
        for (var i = 0, il = elems.length; i < il; i++) {
           var el = elems[i];
           alert(el.nodeType);
           if (el.nodeType == 8) {
           var style = document.createElement('style');
           style.innerHTML = el.nodeValue;
           document.getElementById("css").appendChild(style);
           break;
           }
        }
    }
 </script >

 <style id="css">
 </style>
 </head>
 <body onload="test()">
 <!--@import url(red.css) (min-width:400px) and (max-width:599px);-->
 </body>
 </html>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜