I am working on my second foray into designing a responsive website for my business. I am wondering about best way to organize my css file with browser rendering performance in mind.
There will be only one css file, with all media query included (have three breaks: full size, tablet vertical, phone). Currently all my media queries come at the end of the file (easier to find what I am fine tuning at the moment). I had pondered creating a full css for each break, then calling them individually based on media queries, but was recently reading that tests have shown that browsers still download all the different css files but then only use the appropriate one, which just means more downloading without any benefit.
Once everything is ready would it be better to move the various M-Q's to sit right after their "default" css counterpart (ie the vertical tablet body font size, right after the "default" body font size). Or does the browser read through the entirety of the CSS file before starting to render the page.
Putting the M-Q's as snippets scattered around the css file, makes for a bigger initial css file download due to the replicated #media code for each snippet. But if it causes the browser to render quicker ....
The aspect that got me wondering was base font size, as I will be modifying it slightly for tablets vs phones vs desktop to accommodate the viewing distances. And since all font sizes, padding and margins are based on rem units, changing the base size effects a lot of items.
So from a purely performance point of view (download and browser rendering) is one method preferable over the other(s)?
additional details ...
I guess perhaps what I should be asking, how does a browser use the css file. Does it read through the entire css file and then start to render? Or does it start rendering with the first line of css and then the next line and the next line?
Well, i am not sure, for not having tested this exaustively, but, per example w3.org site is using the 'load by media query' technique.
<link rel="stylesheet" href="/2008/site/css/minimum" type="text/css"
media="handheld, all" />
<style type="text/css"
media="print, screen and (min-width: 481px)">
/*<![CDATA[*/
#import url("/2008/site/css/advanced");
/*]]>*/
</style>
<link href="/2008/site/css/minimum" rel="stylesheet" type="text/css"
media="handheld, only screen and (max-device-width: 480px)" />
<meta name="viewport" content="width=device-width" />
<link rel="stylesheet" href="/2008/site/css/print" type="text/css"
media="print" />
in order to make the browser load assets by media types.
This way, not all has to be loaded at first. Take example with the media="print". The printing style sheet is not loaded except for printing.
In your question you are mentionning 1 single .css file, so, maybe you are stucked, but if you can split your file in 3 different files, the example would help. The counter part is that if you use 'sizing' queries, the browser might have to download the next css file if the user minimize or reduce the viewport.
Also, if your design is NOT to change much, or if the resulting file is quite small, yes, 1 single .css file will be better than different files scoped by media-queries (for maintenance and caching).
Hope this helps
Related
I include 2 stylesheets in a page, one is the version for mobile that is alwys required. on larger screens i would like to load desktop.css in addition. So I link the desktop style so:
<link href="/css/desktop.css" rel="stylesheet" media="all and (min-width: 780px)" />
I thought that the browser would be clever enough to download desktop.css only on large screens. It loads it always however.
Is it possible to prevent the browser from downloading when the media query is not met?
No it is not possible. For media queries the resource is still downloaded (though often at lower priority) but not applied.
This has always been the case even with media=print for example. The exact reasons aren’t clear to me, but there was a brief discussion in this issue, suggesting it broke too many sites - sites presumably that checked the media queries in the CSSOM for even when they didn’t match. That issue clarifies that link rel=“preload” does honour the media query in terms of downloads but there is less risk of breakage there (preload is just an optimisation hint).
The fact that non-matching media queries are downloaded (but not render blocking) actually forms the basis of a bit of a hack to load CSS async with the following code:
<link rel="stylesheet" href="/path/to/my.css" media="print" onload="this.media='all'">
I try to speed up initial loading by eliminating unnecessary downloading.
I split styles in to portrait and landscape css.
And want to load only one style based on media queries.
But is seems they are loading together.
<body>
<link rel="stylesheet" type="text/css" href="style-p.css" media="(orientation: portrait)" />
<link rel="stylesheet" type="text/css" href="style-l.css" media="(orientation: landscape)" />
</body>
The purpose of media attribute in a <link> tag is to decide when the resource applies, not if it loads. It always loads.
So, simply put, what you seem to want is not possible without JavaScript. There is nothing in the current CSS Editor's Draft to indicate it should or will ever be possible using clean HTML + CSS.
If you think about it, this makes a lot of sense. All it takes to flip your device from landscape to portrait is a pet on the back by an enthusiastic colleague. And it would be impossible to provide a decent user experience if you had to wait for a resource to load before the layout change was applied.
The closest the spec gets to the subject is in:
User agents must re-evaluate media queries in response to changes in the user environment that they’re aware of, for example if the device is tiled from landscape to portrait orientation, and change the behavior of any constructs dependent on those media queries accordingly.
But there's an important note on this: most modern browsers made the following (smart) choice: they load <link> resources with media attributes evaluating to false as non-blocking to reduce the time needed to initially render the page to the user.
One of the first articles to go viral on the subject was written by Keith Clark. You might also find Taylor Hunt's follow up interesting.
If you are still interested in loading stylesheets based on #media query conditions, you will need to load them using JavaScript. For performant detection of #media queries in JavaScript, I recommend enquire.js.
As of the moment, browsers still don't have the ability to dynamically load resources in <link> based on its media attribute.
See this article for a more in-depth discussion and implementation of this feature.
Option 1: Keep it as-is
If you're app isn't that big and the styles don't take up much bandwidth, it'd be best to keep them both intact. The cache is your friend. The initial load may be slow, but subsequent requests on the resources will be proxied through the cache.
Option 2: Load the styles with JavaScript
If your styles take about 500KB each, you're probably better off loading them asynchronously with JavaScript.
This will add much more complexity to your application (not to mention if you're using complex build tools like grunt, gulp, or webpack), but it can make initial load faster (or at least, seem faster).
If you want to pursue this path, you can simply include a small script at the bottom of your <body> that checks the user's environment, loads the appropriate css file, inject the contents into a style tag, and append that style tag to the document <head>.
Other notes
Personally, I think separating styles into landscape styles and portrait styles isn't the best way to organize your styles. A better code-separation technique might be to have different styles for different pages of your app, and have only the specific styles load based on the active page. (But it still depends if your layout relies heavily on the portait/landscape media query).
It goes without saying, but these all depend on the environment you're working with and the available server-side solutions you may have access to. It even depends as to how much effort you're willing to give just to reduce your initial load times by 10ms.
I'd say your best bet right now is to merge both files into a single one (so resources loaded pre-HTTP/2 loads faster) and keep it on all your pages. After the first load, it gets cached and that resource will load (almost) instantly. If you absolutely hate white screens, add a fun animated preloaded at the start of your app to entertain your users while they wait for your styles to load on the first render.
something like this could work
<link rel="stylesheet" media="screen and (min-device-width: 800px)" href="800.css" />
<link rel='stylesheet' media='screen and (min-width: 701px) and (max-width: 900px)' href='css/medium.css' />
try using this solution:
https://stackoverflow.com/a/8101452/1964336
https://stackoverflow.com/a/19675410/1964336
https://css-tricks.com/resolution-specific-stylesheets/
more explanation:
CSS syntax: link: https://www.w3.org/TR/css3-mediaqueries/
<link rel="stylesheet" media="mediatype and|not|only (media feature)" href="mystylesheet.css">
media type could be print, screen, all etc.
In media attribute, Use screen and (orientation: portrait) Instead of (orientation: ********)
<link rel="stylesheet" type="text/css" href="style-p.css" media="screen and (orientation: portrait)" />
<link rel="stylesheet" type="text/css" href="style-l.css" media="screen and (orientation: landscape)" />
I started learning less css. Is there any possibility to import different less files
based on view port meta tag. I want to write my own less files for different resolutions.
I also want to know "How does the viewport meta tag works? "
I want to know from the meta tag
how the device width is set to "width" property of the meta tag and the corresponding media
query getting executed.
AFAIK you can't do this with viewport metatag. You can use media queries for this: https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Media_queries
When compiling Less client site (see: http://lesscss.org/#usage) you could do for example this:
<html>
<head>
<link rel="stylesheet" media="(max-width: 767px)" href="green.less" />
<link rel="stylesheet" media="(min-width: 768px)" href="red.less" />
<script src="less.js" type="text/javascript"></script>
</head>
<body>
<p>color this text</p>
</body>
</html>
with:
green.less: p{color:green;} and
red.less: p{color:red;} and
Also read http://andydavies.me/blog/2012/12/29/think-twice-before-using-matchmedia-to-conditionally-load-stylesheets/
In most cases you don't use client side compiling for production. Even preprocessors should be used only during the development process. In the production environment the real resulting CSS code should be used. When install LESS on the server, via npm, a compiler for server side compiling will be installed too.
Instead of using media queries to load different resources you could use them inside your less files. For the example above your less code should look like:
p{color:green;}
#media(min-width: 768px)
{
p{color:red;}
}
By adding media queries to <link> element it won't prevent the browser from downloading that css file.
The css file with the media query will be downloaded but it might not be a critical resource and it might not render blocking.
Finally, note that "render blocking" only refers to whether the browser has to hold the initial rendering of the page on that resource. In either case, the browser still downloads the CSS asset, albeit with a lower priority for non-blocking resources.
More details https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-blocking-css
I have been trying to figure this issue all day and haven't got it yet:
I want to have these 3 css files:
lowerThan960pxForDesktop.css (for fluid layout)
MobileLandscape.css (iphone 960px android 800px etc.)
MobilePortrait.css (iphone 640px android 480px etc.)
I want that the Lanscape.css will use the desktop.css
I want that the Portrait.css will use both the desktop.cssand the Landscape.css
how should my HTML should look like in order to get that right - using media queries or javascript. I have gone over through this a lot of time and each time something goes wrong (either the desktop gets the mobile.css or either the iphone read the Portrait.css even that it is in landscape mode etc.).
maybe the Iphone problem is related to the known viewport width problem? solved with adding this to the html.
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0" />
besides that use media queries to call the css. and in the css file call #import to call the referring css file (e.g landscape would #import desktop etc)
media queries 101:
<link href="css/phone.css" rel="stylesheet" type="text/css"
media="only screen and (max-width: 400px)" >
and more information about the rich world of media queries here.
also adviced to use conditional IE comments to hide the media queries from older IE and let it use just one kind of css
edit: ah I now understand the problem - you need to use different css in different Iphone situations.. you could use jquery mobile and bind a css class change acording to the change from portrait to landscape and back.
hope this helps
I've got a site that isn't mobile enabled, but as part of a campaign, we are going to be sending out a QR code that contains a voucher to link through to a "hidden" page on this site. Of course as users are going to be accessing this page from a mobile phone, this page needs to be mobile enabled.
My question is, how do I go about doing this?
I know that you need a separate mobile style sheet but I've never done this before. Is this the best approach? I only have access to the front end of the site, so is there anything that needs to be done on the back end?
Thanks in advance and apologies if this seems a bit vague.
You need to have this in your <head> in order to make it jump to a mobile layout.
...
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=devide-width, initial-scale=1.0" />
<title> ... </title>
...
<link href="/stylesheets/mobile.css" media="only screen and (max-width: 767px)" rel="stylesheet" type="text/css" />
Then design the site for mobile using the mobile.css stylehsheet and it will be picked up automatically by the media query.
Hope this helps.
My question is, how do I go about doing this?
If you want to use the same page for regular size displays and mobile size displays, then look at media queries so you can do adaptive design (for which mediaqueri.es has some examples.
Whether or not you want to adapt to display size, the only other major factor is testing. Make sure you test on a range of devices and browsers.
You can just fit page to mobile phone screen. For example, page width is maximum 480px, avoid too big pictures, do not use java scripts etc.
you are correct in that you should start with a mobile.css. You should also use a mobile.js, as most heavy javascript will not be needed, and you want to keep the number of requests down and file sizes small.
I would suggest having something on the back-end though, which prevents the regular .css and .js files from loading, possibly based on the user-agent (the best method for this is a whole other topic). Otherwise, you would have to overwrite every style in the original .css file, which is way too much info to feed to a mobile device.
That would be the approach if you wanted to make a mobile version of the whole site.
since you mentioned only one page, you will just need to make a simple .css file and a (simple) page which fills the entire screen of the mobile device, using something like this:
<meta name="viewport" content="width=device-width, height=device-height, user-scalable=no" />
once again, be sure not to load unnecessary .css and .js files