Media queries: Overriding CSS rules vs defining screen specific CSS rules - css

I assume that, just like the media queries that are used in link tags, the media queries which we define in our CSS files are parsed/overwritten or omitted by the browser according to their media query rules (Actually I know that, although the CSS files requested by the link tags with unmatched media are anyway downloaded, they are not render blocking the browser).
So, from the CSSOM build optimization stand point, isn't it better to separate the generic CSS rules that applies to all screen devices from the mobile specific CSS rules and encapsulate the mobile specific rules in a max-width media query? So that browser will parse less CSS to build CSSOM without the need of overwriting them for tablet, desktop etc. I wonder if that would affect the building of CSSOM performance or is it just overkill?

<link> tags with unmatched media queries are download with low priority so that they don't block page rendering, but are still downloaded in order to be available in case media properties change (for example by rotating a smartphone or by zooming out a desktop browser). There is an advantage in having separate stylesheets for different media types, but there is also a disadvantage in creating multiple HTTP requests.
Media blocks inside a stylesheet are already downloaded and I would assume that they are compiled anyway, so it's not really the same as a media query in the tag. But if a certain set of rules is only relevant to a certain width and is always overriden in wider screens, it makes sense to tell the browser that by encapsulating it inside a media query. It's not just about the original page rendering but about any change to the window or to the DOM that requires a redraw - the less rules the browser would need to evaluate, the faster it would be.

Related

Which media query method is more efficient? [duplicate]

It seems to me that it is infinitely better to define media queries in the HTML file within the link> tag rather than by using #media only... in external CSS files.
You can have a large number of specific files modularized quite nicely and extremely specifically depending on what device is being targeted, and only the files you need will be retrieved. I can't think of a single reason not to use this method, or a single instance where it would not be superior.
And yet, I've been unable to verify this. Can anyone offer any scientific evidence / proof to support or invalidate my theory?
Thanks
You can have a large number of specific files modularized quite nicely and extremely specifically depending on what device is being targeted, and only the files you need will be retrieved.
This (the emphasized portion) is a very common misconception about stylesheets loaded via media queries in <link> elements. (What you said about modularization of files still holds true.)
All files will be loaded regardless of the media queries being applied to <link> elements. A file is not loaded only when a media query is met, because there is no guarantee that the browser won't meet it (or even stop meeting it) when some of its properties change while viewing the same page.
For instance if you rotate a mobile device from portrait to landscape, it would stop matching (orientation: portrait) and start matching (orientation: landscape). It needs to make sure the styles in the latter are ready to apply as it switches to that format, so the styles have to be loaded beforehand.
The HTML5 spec for the <link> element does not make any mention of how the media attribute should determine whether or not a resource should be loaded. The Media Queries spec doesn't define how style sheets should be loaded with respect to media queries, however it does state this in a note:
User agents are expected, but not required, to re-evaluate and re-layout the page in response to changes in the user environment, for example if the device is tilted from landscape to portrait mode.
A better alternative is to use #import followed by media queries. It does not load the external CSS if the media query is not supported or does not apply to the browser. This means, however, #import files with conditional queries based on screen orientation either imports the file when the screen orientation changes, or never loads the CSS at all even when the orientation switches.

Do media queries cause a rendering performance hit?

While refactoring my main css into a modular approach I'm using #media all {} to wrap css modules in the IDE. This approach makes it much more easy to scan the files' content as we can't use a preprocessor like less or sass right now.
My only concern is that all those media queries (one for each css module / set of coherent selectors) might cause a performance hit while rendering the site. I am NOT concerned about the file size of our css files as this is a minor issue with a slim modular css framework and proper zipping.
Do media queries like #media all {} have an impact on the performance (both on desktop and mobile/other) devices if used to frequently?
The answer is no... and yes. Having a bunch of media queries will not make the site harder to render. But more lines of code makes a file larger and that technically takes longer to load. Still this isn't much of a performance hit.
But when resizing the browser, it will be taxing on the browser to recalculate a bunch of different mq settings. Read more here: Web Performance: One or thousands of Media Queries?
But...if you want to be proactive about this, with out a preprocessor, just use Pleeease. Pleeease gives you preprocessor like ability with vanilla css. AND it provides a PostProcessor function called mqpacker. It will find all similar media queries in your style sheet and merge them into related media queries. But again, if you are gzipping your stylesheet on the server, you don't need to worry about it.
Good luck! Stay awesome!

How to disable media queries support in firefox?

I have a mobile website that is styled with extensive use of CSS3 Media Queries.
I want to do a version for browsers that don't support Media Queries by adding an extra css file for them, that overwrites some of the css rules.
I was wondering if there is a way to disable Media Queries support in Firefox (21.0) to be able to develop, since I don't have anything else to test with.
A Chrome solution would also work out, although I prefer using firebug.
You could always try testing in IE 8.
Media queries is something you define in your CSS, if a browser does not understand media queries, it has no support for it, it will not execute the CSS that makes the site responsive.
As a result you will have a not responsive site in a browsers that not supports media queries, thats the whole point of media queries.
There is no option in any browser to disable media queries.
If you want to test your site without the media queries kicking in, comment out the rules in your CSS. With this approach you can continue testing in Firefox, without having the need to test in Internet explorer 8
You have it backwards. Media Queries and corresponding rules are implicitly ignored by browsers which do not support them. The common/basic rules must therefore come before the specialized ones, not vice-versa.
You should always test in the target environments. If that is not an option, you can put the media-specific rules in a separate stylesheet and disable that stylesheet, for example with HTML comments or the Web Developer extension (apparently this feature of the extension is not available in Chromium/Chrome, but you can disable "Handheld Styles"). Equally with Web Developer and Chrome Dev Tools you can test media-specific stylesheets as if you were using the corresponding viewports. But do not rely on that; there is more to it than just viewport size.

Can I make font loading in CSS Optional for mobile devices?

My current Website-Design is built with the Bootstrap responsive framework. It uses several custom fonts, which make up about 50% of the document size. The fonts are included via CSS, the way of inclusion can not be changed.
My goal now is to stop mobile devices from requesting these fonts, in order to reduce their bandwidth consumption.
Is there a CSS way, like #media (min-width: 480px), to not load the fonts in the responsive layout?
In most implementations, background images that are referenced in CSS media queries get pre-downloaded. (Unless you do some fiddling with your use of display:none;, but that won't be supported in all browsers.)
The same applies to any fonts you've included via media queries — even if they're specified for a larger/different viewport.*
Why?
This allows for a smoother transition if viewport size is changed, e.g. from portrait to landscape.
Solution?
Considering the constraints you mentioned, I don't see a clean way to do this only with CSS. You could do something with JS (but make sure it degrades gracefully), or PHP.
But the easiest ways to reduce HTTP requests and how much your visitors have to download include doing one or all of the following:
Using less fonts, or web-safe fonts instead.
Using a CDN for fonts.
Including 'minified' font files that only have the characters you'll
be using them for.
Check out Google Web Fonts for the latter two.
If you expect or get a lot of mobile traffic that's important for the site, it's always worth re-thinking a website's design and markup from a mobile-first approach: what's necessary and what isn't. (That approach can often help to even reduce clutter on the desktop version of your site.)
* The fiddling approach could be useful for fonts too, but you'd have to do browser testing yourself, as so far it's undocumented.
You could create two different stylesheets, one for mobile and one for desktop, then use PHP browser detection or various other methods to see if the user is on a mobile device or desktop device, and provide them with the corresponding stylesheet.
Take a look at the PHP get_browser function: http://php.net/manual/en/function.get-browser.php
All background images aren't necessarily pre-downloaded if referenced in your media queries -
http://timkadlec.com/2012/04/media-query-asset-downloading-results/
perhaps this technique would also work for fonts too. Not if you're using anything that'd need JS (like typekit, google) your font's will be requested because of the JS anyways afaik.

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 - unless 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...
<script src="bork.js" type="bork/bork"></script>
<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>

Resources