2

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>

enter image description here

Ju-v
  • 362
  • 3
  • 15

4 Answers4

3

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.

Jerome Indefenzo
  • 967
  • 6
  • 25
  • You make a few general declarations. Like *"Browsers don't check media queries when loading links"*. While this might have been true in the past, it is likely to change, so your answer will gradually become incorrect (it partly already is). Consider backing your answer up with sources for the info and advice you provide. – tao Dec 07 '17 at 19:12
  • 1
    @AndreiGheorghiu as far as I can tell, all the (most-recent) browsers I've tested this on doesn't seem to load these resources dynamically. Neither have I seen any spec on w3c or on CSSOM which specifically says browsers MUST dynamically load css resources based on the `media` attribute. Although, I understand that this may change in the future, thus I've reworded my answer to sound more future-proof. Thanks for the input. – Jerome Indefenzo Dec 07 '17 at 19:29
  • 1
    You might find these resources interesting: [keith clark's piece on async CSS](https://keithclark.co.uk/articles/loading-css-without-blocking-render/) - more than 1 year old, and [taylor hunt's follow up](https://codepen.io/tigt/post/async-css-without-javascript). – tao Dec 07 '17 at 20:28
  • Point being `media` queries ***do get evaluated*** on ``s. And if the current one does not apply, the resource is loaded async, hence non-blocking. So it doesn't do what OP wants (which is not load at all) but it does get eval-ed. Which is different than what you stated. Looking forward to anything that proves me wrong. – tao Dec 07 '17 at 20:55
  • Interesting read. Thanks for the resources! I didn't know these were evaluated and made into non-blocking by some browsers. – Jerome Indefenzo Dec 07 '17 at 23:51
3

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.

tao
  • 82,996
  • 16
  • 114
  • 150
-1

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:

  1. https://stackoverflow.com/a/8101452/1964336

  2. https://stackoverflow.com/a/19675410/1964336

  3. 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.

jatinder bhola
  • 385
  • 1
  • 7
  • 23
  • Could you please explain why adding `screen and` to OP's code makes it work? – tao Dec 07 '17 at 18:31
  • because it is a css syntax. https://www.w3schools.com/cssref/css3_pr_mediaquery.asp – jatinder bhola Dec 07 '17 at 18:32
  • Ok, in that case explain why `media="(orientation: portrait)"` doesn't work. Isn't it still CSS syntax? – tao Dec 07 '17 at 18:34
  • I guess, you are missing **only** according to this syntax `` – jatinder bhola Dec 07 '17 at 18:38
  • Your answer is the only one I haven't downvoted (yet). I'm tempted, because you linked w3schools which, in my opinion is a low quality source of information when it comes to standards and best practices. I suggest replacing it with a more credible source of information, like w3c or mdn. – tao Dec 07 '17 at 19:17
  • @AndreiGheorghiu, correct me if I am wrong. I may have not as experienced as you have (yet). Till then what I read thru w3c if we do not add `media type` it considers as `all`. so for to OP's post, it only declared orientation. which became `all and (orientation: portrait)`. because of what the webpage loads both the css. – jatinder bhola Dec 07 '17 at 19:30
  • I've read the [documentation draft](https://drafts.csswg.org/mediaqueries/#media) through tonight. There is nothing to indicate `media` attribute works any different on `` than `@media` in CSS. Which means the CSS ***is loaded***, (async if media evals to false and blocking if it evals to true). Which makes what OP wants not possible. – tao Dec 07 '17 at 20:57
-2

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)" />
LuFFy
  • 8,799
  • 10
  • 41
  • 59
LPZadkiel
  • 561
  • 1
  • 3
  • 16
  • 1
    Please note *code-only* answers are discouraged on SO. You should briefly explain the principle; why this solution works. If you don't know why it works, at least reference the source of information. – tao Dec 07 '17 at 18:26