How are media queries counted in IE's CSS selectors limit? - css

Any idea how does IE treat media queries regarding this CSS selector limit?
Does it see it as a single CSS rule or it sees it as 1 rule (the #media declaration) + number of rules inside the #media rule?
This being for IE9 as from what i know IE9 is the only IE that supports media queries while also having this issue with 4095 selectors.
I'm trying to write a tool to split the CSS accordingly and I'm not sure how to count the rules, as in a #media rule will be counted as 1 or will be counted as 1 + nr of rules inside?

It appears that media queries are not included in the selector limit. All rules within all media queries are counted though.
I wrote a test that performs a binary search to find the turning point where the last selector is ignored. It is available at https://robwu.nl/s/css-selector-limit-test.html. The binary search runs over the range 0 - 4200 and reports how often the input selector fits until the last selector is not applied any more. If the result is greater than 4096, the test case reports "infinity".
Results:
Turning point at 4095 for: #DUMMY{color:red;}
Turning point at 4095 for: #media screen(min-width:9px) { #DUMMY {color:red;} }
Turning point at 2047 for: #media screen(min-width:9px) { #DUMMY, #DUMMY {color:red;} }
Turning point at 1023 for: #media screen(min-width:9px) { #DUMMY {color:red;} #DUMMY, #DUMMY, #DUMMY {color:red;} }
Turning point at 1364 for: #media screen(min-width:9px) { #DUMMY {color:red;} } #media screen(max-width:9px) {#DUMMY, #DUMMY {color:red}}
Turning point at 1364 for: #media screen(min-width:9px) { #DUMMY {color:red;} } #media screen(max-width:9px) {#DUMMY {color:red;}} #media screen(max-width:9px){ #DUMMY {color:red;}}
Turning point at infinity for: #media screen (min-width:9px) { }
Turning point at infinity for: #media screen (min-width:9px) { } #media screen (min-width:9px) { } #media screen (min-width:9px) { }
Turning point at infinity for: #font-face { font-family: "blablablablabla"; }
The last three tests show that media queries (and other at-rules such as #font-face) are not counted in the selector limit.
I have seen many "css rule" counter scripts here on Stack Oveflow (e.g. https://stackoverflow.com/a/20496041 and https://stackoverflow.com/a/12313690), but all of them are wrong, unfortunately. A media query appears as one entry in the cssRules/rules list. The right way to count the number of selectors in a stylesheet is to recursively process the style sheet to deal with (nested) #media at-rules.

I'm not sure whether it will be counted as 1 or 1+nr but I would suggest that you don't split the CSS between media queries.
A non-efficient hack
Use a counter and go upto 4095.
Trace back and try to find the most recent #media query and split the CSS from there. You can add a check if media query doesn't come till 3000 while backtracking then don't count that case etc.

Related

Correctly apply CSS for responsive text

I am trying to reduce the size of some titles of my commerce in responsive version. I have tried a bit of css but nothing has worked.
At the moment, I have the following for the main slider text:
#media only screen and (max-width: 600px) {.zphero-banner-style-11 .zpheading, .zshero-banner-style-11 .zpheading {font-size: 22px;;}}
This is my web
enter image description here
Where am I going wrong?
Your css path currently looks like this.
#media only screen and (max-width: 600px) {
.zphero-banner-style-11 .zpheading, .zshero-banner-style-11 .zpheading {
font-size: 22px;;
}
}
Without the associated HTML its hard to say but my initial guess is the classes that are already applied on it have greater importance than your new media query. I would try this adding !important and if it doesnt work make your selector more specific.
#media (max-width: 600px) {
.zphero-banner-style-11 .zpheading, .zshero-banner-style-11 .zpheading {
font-size: 22px !important;
}
}
fun things to note about selector importance:
100 points for IDs
10 points for classes and pseudo-classes
1 point for tag selectors and pseudo-elements
Note: If the element has inline styling that automatically wins (1000 points)
Among two selector styles browser will always choose the one with more weight. Order of your stylesheets only matters when priorities are even - that's why it is not easy to override Bootstrap.
currently your media query css selectors have a value of 20 points because there are 2 class names pointing to the change
CSS declarations marked as important override any other declarations within the same cascade layer and origin. Although technically, !important has nothing to do with specificity, it interacts directly with specificity and the cascade. It reverses the cascade order of stylesheets. Not the best practice but it works well often

Build a media query for print and screen with min-width

I want to have a stylesheet that is appropriate for print and screens of decent width.
I hope my intent is obvious when I type:
#media print or (screen and (min-width: 801px)) {
Rules here
}
Sadly, this won’t work.
What is the correct syntax?
Try this (a comma seperates several independent condtions/queries):
#media print, screen and (min-width: 801px) {
Rules here
}
Try this:
#media print, (min-width: 801px) {
Rules here
}
That would be for OR.
Just FYI, an AND structure would look like this:
#media print and (min-width: 801px) {
Rules here
}
#media print, screen and (min-width: 801px) {
.intro_text{
border: solid 1px blue;
}
}
works on a Mac (Safari, Chrome and Firefox.) Note the comma and fewer parentheses per:
2.1 Combining Media Queries
"Several media queries can be combined into a comma-separated media query list."
I would think, given:
2.4. Media Features
Media features are always wrapped in parentheses and combined with the and or or keywords, like (color) and (min-width: 600px), rather than being separated with semicolons.
2.5. Combining Media Features
"Media conditions can be grouped by wrapping them in parentheses () which can then be nested within a condition the same as a single media query."
It is invalid to mix and and or and not at the same “level” of a media query. For example, (color) and (pointer) or (hover) is illegal, as it’s unclear what was meant. Instead, parentheses can be used to group things using a particular joining keyword, yielding either (color) and ((pointer) or (hover)) or ((color) and (pointer)) or (hover). These two have very different meanings: if only (hover) is true, the first one evaluates to false but the second evaluates to true.
that some set of parentheses would work, but I can't find one. This must be due to the difference between "Media Queries" and "Media Features." The spec language seems a little unclear at places to me, e.g. the reference to "semicolons" above.

Media queries running weird because of non-integer width

Can't say is it a real problem or I'm just being paranoid but this behavior of media queries is really driving me crazy for last couple of hours.
Let's consider this really simple CSS.
body {background:yellow}
#media (max-width:399px) {
body {background:red}
}
#media (min-width:400px) {
body {background:blue}
}
Problem happens when width is 399.333px! (or any float-value between 399 and 400 integers)
My logic says that by using this CSS style page will never turn yellow, right? It should be red when viewport size is shorter than 400px in width and blue when it's 400px and over.
Weird behavior happens with Opera browser (I'm using 36.0 at the moment) on Windows when page is zoomed-in. I understand that viewport width is calculated using real viewport width and current zoom-level and this value should always be integer. But...
Looks like Opera doesn't round/floor/ceil that value which affects on entire page. I'm getting yellow background when Opera finds out that viewport-width is not 399px or 400px but it's 399.333px!? So none of media queries fulfills condition.
I've already tried to find an answer here and web-wide but nothing is close enough to this problem. This problem already happened to me when I was using em units so I could work around and turn them to pixels, but I can't affect user's decision about using browser's zoom feature.
Is there something I can do to prevent this or that's just the way it is?
The easiest way to simulate this behavior is hitting CTRL,+ three times and than easily move vertical slider in Object Inspector.
update:
Yes, I can fix it with "mobile/desktop first" approach by linking each media break-point to previous one but that's not part of my question. Also, default body style is here as visual aid only and changing that really doesn't solve problem.
A simple solution could be the following:
body {background:yellow}
#media (max-width:400px) {
body {background:red}
}
#media (min-width:400px) {
body {background:blue}
}
The rules in the last media query will simply overwrite any parameters that exist previously, just because of the order.
That way there won't be a situation/width which isn't covered by these two media queries: Everything up to 399.9999... (whatever) fulfills the first condition, everything above 400 will meet the second condition, and if the width is exactly 400, the rules in the second media query will overwrite the previous ones due to their order.
Similar layout
The answer to this question should be to avoid the problem altogether, and simply leave one of the media queries out, and let one media query override the other:
body {background: red;}
#media (min-width: 400px)
{
body {background: blue;}
}
However, when you need a fundamentally different layout, this would cause a lot of additional code simply to reset one case from the other. As is the case in the following example:
.some-element {background-color: red;border-left: 30px;}
#media (max-width: 399px)
{
.some-element {border-left: none;padding-bottom: 40px;}
}
Whereas it would be shorter and more elegant to write:
.some-element {background-color: red;}
#media (min-width: 400px)
{
.some-element {border-left: 30px;}
}
#media (max-width: 399px)
{
.some-element {padding-bottom: 40px;}
}
But neither of the media-queries in the last example code will take effect if the width is for instance 399.5px. Read the next part of this answer, if you still wish to write such code with perfect coverage.
Use floating-point numbers
Unfortunately the media queries for min-width and max-width values are always inclusive. A browser uses fractional pixels when it has zooming capabilities. Therefore, a simple solution to this problem is to increment your threshold pixel value of 400px with the lowest possible fraction, for instance to 400.00001px. However, the crucial question then remains, what is the lowest possible fraction?
The CSS specification does not say anything about which data types are used to store numbers:
A <number> can either be an <integer>, or it can be zero or more digits followed by a dot (.) followed by one or more digits.
But according to the answer to 'Why does Bootstrap use a 0.02px difference between screen size thresholds in its media queries?':
Indeed, cross-browser compatibility is the reason: according to Bootstrap's source, 0.02px is used "rather than 0.01px to work around a current rounding bug in Safari.
Apparently, bootstrap being a widely used framework, it seems that 0.02 would be the correct value to use in this specific case.
In your case, to get a perfect coverage of your media queries - and thereby prevent a yellow background, the solution would look like this:
body {background: yellow;}
#media (max-width:400px) {
body {background: red;}
}
#media (min-width:400.02px) {
body {background: blue;}
}
Use CSS4
As of CSS4 you may use intuitive operators for media queries such as >= and <= instead of min- and max-, and more importantly, additionally you may use exclusive operators such as > and < which immediately solves the problem (see here).
However, it may not be widely supported. Unfortunately, this feature is not yet on Can I Use to check browser support. You may check it yourself using this codepen. It seems to work in the latest version of Firefox.
The solution would then be as simple as:
body {background: yellow;}
#media (width <= 400px) {
body {background: red;}
}
#media (width > 400px) {
body {background: blue;}
}

CSS media queries - many vs few

Suppose 1 css file, and 3 #media formats, say:
#media (min-width:1280px)
#media (min-width:640px) and (max-width:1279px)
#media (max-width:639px)
Is there a significant performance difference between using each #media format once and cramming all appropriate CSS rules inside, such as:
#media (min-width:1280px) {
/* all css for this format */
}
#media (min-width:640px) and (max-width:1279px) {
/* all css for this format */
}
#media (max-width:639px) {
/* all css for this format */
}
VS
Using as many #media declarations as necessary (about as many as you have CSS rules/sections)... such as:
div.some-class-name {
/* styles */
}
#media (min-width:1280px) {
div.some-class-name {
/* styles for this format */
}
}
#media (min-width:640px) and (max-width:1279px) {
div.some-class-name {
/* styles for this format */
}
}
#media (max-width:639px) {
div.some-class-name {
/* styles for this format */
}
}
I personally prefer version 2 (though maybe not so excessive), as it's much easier to track a specific pair of styles for each #media query.
thx for feedback!
I'm not an expert on this, but I found a decent article addressing this:
https://helloanselm.com/2014/web-performance-one-or-thousand-media-queries/
It doesn’t matter if you use one big or multiple media-queries in your code assuming your values are mostly the same. It shouldn’t matter if your values are different for each(!) of your hundreds of media-queries but could affect performance (found no way to track this down). The only thing I could add here is that using many inline media queries often is that they’re increasing the size of your CSS (unless your gzipping it) and that affects performance as it’s loaded blocking.
Makes sense to me. I personally like to group element styles rather than grouping media queries (version 2 in your question). In my mind, CSS's goal is to style your elements and styling them based on screen size is a secondary goal.
In practise no there shouldn't be a significant performance difference, there shouldn't be one at all. Browsers generally serialise and strip out duplicate media queries.
The only potential issue is if the extra MQs add bloat to your css file and thus it takes longer to download, delaying the render. It is pretty unlikely for this to happen.
You can read a little more about it here
The performance difference issues in your examples are extremely small. The only thing I can tell you about performance is this: If you use stylesheets, ALL stylesheets will be loaded by the browser. Only the one that matches the media query will be applied.
Basically, just use whichever method is easier to change, organize, etc. . . my guess is stylesheets.
About the NUMBER of queries, there will be no performance changes. Most browsers automatically calculate the width, height, screen, type etc., even without media queries.
Hope that helps!
Your version 1 is very similar to v2. The difference I see is you wrote "all CSS" versus "styles for this format". In the case of writing all of the CSS you will have a much larger file than V2. Loading a larger file takes extra time than a smaller file, so version 2 will be more efficient.
In any case, use these 2 rules for performance:
1) Shorten your CSS as much as possible. Avoid redundancy wherever you can. If in the top media query you use "h2 {padding: 0 }, then don't use that in the other queries as that would be completely unnecessary.
2) Look at the number of characters or file size of your CSS. The smaller file will always load faster.

How to hide a CSS media query from print? "not" logical operator does not work

I am trying to hide a media query from being printed, so I came up with #media not print and (min-width:732px). But for whatever reason, this (and many variations I have tried) does not display as I would expect in browsers.
The only option I can think of is to use #media screen and (max-width:732px), but I would like to avoid this as it excludes all the other media types besides screen.
Media queries grammar is pretty limited to say the least.
But with CSS3 (not CSS2.1) it seems that you can nest #media rules.
#media not print {
#media (min-width:732px) {
...
}
}
This basically executes as (not print) and (min-width:732px).
See https://stackoverflow.com/a/11747166/3291457 for more info.
How about something like this?
body { min-width:732px; }
#media print {
body { min-width:initial; }
}
The min-width will be set to 732 for everything, except print, which will get some other value that you specify. Depending on your situation, you can set a different width, or try something like "thiswontwork" (which sometimes causes the value to be set to the initial value) or "inherit" or something like that.
If I'm correct in my assumptions about the behavior you expected, the issue is that the precedence of not is lower than and.
#media not print and (min-width:732px) means "any media except for printers with at least 732px-wide viewports" (so it will apply to any non-printer and skinny printers) not "any media except printers, as long as that media has at least a 732px-wide viewport" (which is what I assume you expected).
Since parentheses aren't valid around media types and #media rules cannot be nested, working around it is kind of annoying. For simple cases, brentonstrine's answer is a good solution, but for queries which enclose many styles it can be burdensome to make sure they're all overridden properly.
I put together some example media queries when I was trying to figure this out myself earlier today.
As you can't put something like this
#media screen,handheld,projection,tv,tty and (max-width:732px) { ... }
you should write pairs for each media like following:
#media screen and (max-width:732px), handheld and (max-width:732px), projection and (max-width:732px), tv and (max-width:732px), tty and (max-width:732px) { ... }
You could try something like:
#media screen,handheld,projection,tv,tty { ... }
The above nested query didn't work for me, but after a little reading on Media Queries Media Types at MDN, you can exclude you're media query from print styles by specifying the screen type
So if you have a media query like this which doesn't specify a type, it will have an implied type of all, (which will affect print styles)
#media (min-width:400px) {
...
}
To exclude the style from print styles, you'd need to change it to this:
#media screen and (min-width:700px) {
...
}

Resources