LESS restricting CSS-files to certain viewports (Shopware) - css

I ran into a problem at working with Shopware today. I want to restrict the usage of certain CSS files (mobile css and desktop css).
Problem is: both files are being used and it seems to not letting me restrict the files to the viewports. What did I do wrong?
Would be great if you could help me out here, since Ive just started in LESS templating. Cheers!
{extends file='parent:frontend/index/header.tpl'}
#phoneLandscapeViewportWidth: 30em;
#tabletViewportWidth: 48em;
#tabletLandscapeViewportWidth: 64em;
#desktopViewportWidth: 78.75em;
when (#media screen and (min-width: #tabletLandscapeViewportWidth)=true) {
{block name="frontend_index_header_css_screen" append}
<link type="text/css" media="screen, projection" rel="stylesheet" href="{link file='frontend/_public/src/css/custom.css'}" />
{/block}
}
#media screen and (max-width: #tabletLandscapeViewportWidth) {
{block name="frontend_index_header_css_screen" append}
<link type="text/css" media="screen, projection" rel="stylesheet" href="{link file='frontend/_public/src/css/mobile.css'}" />
{/block}
}

First of all: As the comments already state out, you're mixing up different languages.
By now - from your example - you're dealing with three things, that cannot be combined in that way as you try it:
LESS: This is a preprocessor language that - at least in a Shopware 5 context is meant to be compiled and generates your CSS
files (there is a way of including LESS files directly, but this is not recommended for production, so I'd leave this part out).
CSS: Your stylesheets that are rendered. If you statically include them into your template (I mean if you're not using Javascript to dynamically change your DOM) you WILL have to decide whether you use one or another CSS-File before you render the DOM.
This brings us to the next CSS related-topic:
Media Queries: The concept of media queries is not meant to dynamically change the DOM (i.e. clearing out one CSS-Stylesheet and bringing in another).
Imagine the following case: You sit at your Desktop-PC and slowly drag the window of your browser smaller and smaller until your viewport-width is smaller than 64em (#tabletLandscapeViewportWidth). What is the media-query supposed to do? Request the server to load another resource?
Remember: Media Queries are CSS and CSS is all about style of your Website. In a normal case it is served once when the page loads and the rest of the magic happens in your client. There is no further communication with the server (and this is what you'd try to do, i guess).
Smarty (.tpl): The third part you mix up here is the .tpl files, and these come from the Smarty-Template-Engine. So we have to be clear here: Smarty renders your template. This happens server-side before the page is delivered to the requesting client.
That means you can decide to load one or the other css at this point (but not by media-queries, I'll come back to that later) but once the page is delivered to the client, Smarty's work is over and it will do nothing without another server-request (i.e. by an AJAX-call).
I must confess that I am not absolutely understanding what exactly you want to achieve. If you only some CSS definitions to a certian viewport width, you don't need to go into the template at all.
Let's assume you only want your styles that are in the custom.css apply when the viewport is larger than #tabletViewportWidth and everything below should serve mobile.css.
Since you can nest media-queries in CSS3 it shouldn't be a problem to wrap the whole less file into a media-query like that:
#media screen and (min-width: #tabletLandscapeViewportWidth) {
// all your custom.css content
}
#media screen and (max-width: #tabletLandscapeViewportWidth) {
// all your mobile.css content
}
But please keep in mind that this excludes all other media-types, so you maybe should go with #media all.
If you really want to change the stylesheets dynamically you should go with a library like Modernizr and make an AJAX-Request that dynamically changes the stylesheet, but imho this is kind of an ugly solution that only makes (no real, but with a bit of fantasy a little bit) sense if no stylesheet is loaded (or a base-stylesheet with styles, that both .css-files share) and the call is made to request a smaller CSS-File.
But if the production-css-file is minified this shouldn't be worth the effort.
As you can see, in the offered solution we are not even touching a smarty-tpl-file. But i want to mention a little thing if you work with smarty:
You're extending a file here, therefore every junk of code needs to be inside of the {block}-tags you're extending. Smarty doesn't know where to put the code otherwise and will throw an error (even though, as explained LESS-Code won't work anyways here ;) ).
regards

Related

Why are my stylesheets with media="all" getting listed as render-blocking resources?

In the PageSpeed Insight report for my site, it's listing all of my css files as "render-blocking resources". My css links all look like this:
<link rel="stylesheet" type="text/css" media="all" href="https://example.com/something.css" />
In the documentation, it says <link rel="stylesheet"> tags are listed as render-blocking stylesheets if they don't have a media attribute that matches the user's device. Since my stylesheets all have media="all", why are they getting listed as render-blocking resources?
The documentation is very misleading.
What they are trying to say is they will not flag something as render blocking if you have a media query that matches the users device only (so a max or min width or an orientation for example).
However even then they will flag it under 'critical CSS' and even if they don't flag it, it is still render blocking if that CSS is required for the 'above the fold' content.
Further down the page you linked in your question they explain it slightly better
Another approach to eliminating render-blocking styles is to split up
those styles into different files, organized by media query. Then add
a media attribute to each stylesheet link. When loading a page, the
browser only blocks the first paint to retrieve the stylesheets that
match the user's device.
That part is the important part, they are trying to get you to put your mobile styles in one style sheet, desktop in another so you only load the bear minimum CSS to render the page initially.
What really matters
Ignore all the confusing stuff, here is the simplest way to tackle a few audits at once.
Inline your critical CSS - the only step you really need
Any CSS that is required to render the 'above the fold' content should be inlined within your HTML within a style tag.
I will warn you, this is difficult, none of the tools out there do this perfectly and it must have every single style rule included to work. (e.g. if you missed just one class that is required to render something 'above the fold' the browser will wait for the style sheet that contains that rule to be loaded and block the rendering.)
Designing for this from the start is the best option
I keep all my 'above the fold' styles in a separate file and inline them at runtime.
I split these files into 2 types - global (site header, general styles used on multiple pages above the fold etc.) and page-specific (e.g. hero for home page, form styling for contact forms etc... whatever is 'above the fold' on each page that is unique enough to not add to the global above the fold styles.)
This will deal with render blocking resources, critical request chains (for CSS) and give you super fast First Contentful Paint and First Meaningful Paint.
Then you just do as they suggest having styles for mobile and desktop separate and make sure you remove unused CSS if you can (yet again a very difficult task so best to design for it from the start).

Is loading additional CSS in the HEAD, according to screen size, a bad practice?

I'm using the tablesaw script to fit tables to smaller screens.
My developer inserted the relevant CSS inside the head tag, this way:
<link rel="stylesheet" type="text/css" href="/tablesaw.css" media="screen and (max-width: 767px)">
The problem is that it is hurting my Google Page-Speed Score for mobile devices, since this is a render blocking element, that comes in addition to my general CSS file.
Therefore, I figure I can just take the whole Tablesaw CSS block, and insert it inside the general CSS file, right at the end of it, But I will need to wrap it like this:
#media screen and (max-width: 767px){[General TableSaw Content][by #media-type Table Saw Content]}
And this indeed increased my page speed score.
So is this a better practice?
Any disadvantages over the method I'm currently using (loading the additional CSS in the head section)?

Separate css style sheet for mobile devices and another for desktop - no media queries

I know this type of question has been asked a 1000 times, and 99% of the time someone hurries in and gives media queries as the solution. It no longer is the optimum answer.
The Situation: I have video in the background on a webpage - that does not render on a mobile device, so I want to use an agent to detect mobile and simply swap the css page to a mobile friendly version.
Please do not post a media query as the solution because my cell phone is 800x1200 and my tablet is 1900x1200, more than my desktop:1600x900 so a media query wont work.
Hoping someone can post an entire solution with the agent and insert where the css reference goes becuase I dont want to mess that up..
Im presently using an agent that redirects to a separate mobile page but that means maintaining 2 pages vs. one with stripping css instead. (1 page and 2 css files)
I think many here will find this answer helpful as many with this question have no answer.
thank you..
PS - please be detailed Im a noob.
thanks
If your using http://code.google.com/p/php-mobile-detect/ something along the lines of the code below should work.
<?php
include 'Mobile_Detect.php';
$detect = new Mobile_Detect;
if ($detect->isMobile())
{
?>
<link rel="stylesheet" type="text/css" href="mobile.css">
<?php
}
else
{
?>
<link rel="stylesheet" type="text/css" href="noneMobile.css">
<?php
}
?>
Very simple example but would work in your case. You could go into more detail with $ddetect->isTablet() etc, full list here http://code.google.com/p/php-mobile-detect/wiki/Mobile_Detect
In direct defiance of the question, I'm going to say that as of 10/12/21, Media Queries are absolutely an option once again, as in most situations they will work.
If you're looking to target the page width, you'll use the following. This is a quick fix, and most likely is the main reason for OP's question, as it doesn't address the fact that some devices have resolutions shared by desktops, yielding a mobile experience on desktop, or vice-versa.
#media (max-width:400px)
To circumvent this, you want to use the following to check for the device width instead:
#media (max-device-width: 400px)
This deals with the DISPLAY size, versus the webpage size. It's not perfect, but combining this with device heights, and vendor-specific queries, you can fix most situations with CSS. The bonus is that you can keep the web page optimized without needing extra JavaScript or PHP, or any other additional web technology, and for the fringe cases, you can use the options provided here.

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>

Maintaining print CSS stylesheet files

How do you usually handle changes to screen and print CSS files? I typically have one screen CSS and one print CSS file and for the most part the I would copy the contents of screen CSS to print CSS file and then modify some properties, classes or ids, maybe set some display:none to certain classes etc.
The problem is, while working on a site or web app I make numerous changes to screen CSS and usually forget about print CSS then I have to sync them from time to time and I just don't think that the most optimal way.
For print stylesheets I tend to also apply the media="screen" stylesheet to the media="print" as well as a second stylesheet that appears later, which essentially, just removes the elements I don't want to print.
It's a fairly simplistic approach, though, and only works to any potential if it's regularly reviewed, so I couple it with a policy of always revising (or, at least, checking) it when I revise the screen-stylesheet.

Resources