EDIT
As #Joe pointed out in his answer, the problem here with IE has nothing to do with media queries.
I have therefore updated the old title: ("media queries GLITCH in IE") with the current one. (thanks also to some meta advice)
Just to be sure, I created a new FIDDLE containing just the calc function, and low and behold - I see the same (bad) behavior in IE as I did in my original fiddle with the media queries.
Also, one interesting observation which I noticed was that this only happens when I use division in the calc operation, but if I use something simpler like calc(100% - x px) -
IE handles it ok.
I am using media queries to justify a list of boxes.
Basically, I set up a media query for each #columns states, where I then use calc() to work out the margin-right on each of the elements (except the ones in the last column).
Here's the fiddle
Now this is working fine in chrome and firefox - but when I run this in IE9+
I see a glitch between media query states (including flickering and disobeying the media queries).
Here is a screenshot of what i'm talking about
[screenshot taken at browser window width of 710px] :
Is this an IE bug or have I done something wrong?
FIX:
here is a smoothly working jsfiddle of my solution
further investigating the math i had a hunch internet explorer is having trouble trying to do something stupid ( what else is new ), and that was to allow decimal values ie margin-left:250.123px; thus causing VERY miniscule inconsistencies and ruining your layout.
to correct this issue i temporarily subtracted 1px from all of your calculations and everything is looking smooth as can be
#media (max-width: 350px) {
.container > div {
margin-left: calc(((100% - 150px)/2) - 1px);
margin-right: calc(((100% - 150px)/2) - 1px);
background:black;
}
}
#media (min-width: 350px) and (max-width: 550px) {
.container > div {
margin-right: calc((100% - 300px) - 1px);
background:red;
}
.container > div:nth-child(2n) {
margin-right: 0;
}
}
#media (min-width: 550px) and (max-width: 750px) {
.container > div {
margin-right: calc(((100% - 450px) / 2) - 1px);
background:purple;
}
.container > div:nth-child(3n) {
margin-right: 0;
}
}
#media (min-width: 750px){
.container > div {
margin-right: calc(((100% - 600px) / 3) - 1px);
}
.container > div:nth-child(4n) {
margin-right: 0;
}
}
EDIT:
ive added colors to the media queries to help troubleshoot the source of the problem and have ruled them out as the issue. ive also ruled out compatibility mode as the cause of this issue and your calc formatting looks just fine.
take a look at the updated fiddle
were the media queries breaking we would see inconsistencies in the color flickering as well... this leads me to beleive it is a mathematical calculation error specific to our margin / spacing definitions... further investigating coming soon
i have encountered a few issues with media queries in ie... a few bugs worth mentioning are
compatibility mode - make sure this is turned off can cause unexpected behavior or just break media queries all together
doctype - not declaring one or not having an html5 doctype can be the cause of even more media query inconsistencies
<!DOCTYPE html>
ive noticed you are using calc() my first reaction was to make sure all mathematical operators are surrounded by white space... this is another issues ive encountered, where
calc(2px+5px)
has the tendency to fail where the proper syntax should be
calc(2px + 5px)
Related
So this question seems to be asked a lot but in the reverse.. I'm having the issue where my media query is overriding the previously set styles in a mobile first design and I don't know why. Mobile should be padding: 33rem 0 and desktop should be padding: 18rem. See below.
.description {
background-image: linear-gradient(#b676fa,#14D8EB);
padding: 33rem 0;
}
#media only screen and (min-width: 900px) {
.description {
padding: 18rem;
}
}
Works fine for me.. All brackets closed? Run it through a CSS validator perhaps - https://codepen.io/pmackey-deveire/pen/vYBvxQz
Have you checked the inspector to see what styles are being applied as you change the window size?
Perhaps using PX instead of REM for testing.. 33rem appears to be smaller than 18rem on mobile so you might be tricked into thinking it's not working
Let's say that I have default font size set to 16px (this should be redundant since it's default in most browsers):
For brevity, my site contains some box with size 10em x 10em.
body, html
{
font-size: 16px;
}
.box {
border: 1px green solid;
background-color:green;
width:10em;
height:10em;
}
My site is already responsive with min-width media queries for specific breakpoints targetted at em values (36, 62 and 85em).
The only thing my site does is change width and color of the box.
#media (min-width:36em) {
.box {
width: 36em;
border:1px red solid;
background-color:red;
}
}
#media (min-width:62em) {
.box {
width: 62em;
border:1px blue solid;
background-color:blue;
}
}
#media (min-width:85em) {
.box {
width: 85em;
border:1px orange solid;
background-color:orange;
}
}
Now let's say that I have some device with resolution 1440x900 where browsers decide that the device's pixel density is 2dppx by default. As result, everything looks much bigger than it should be. And I don't like it.
But the solution should be easy, right? Just add a media query at start for 2dppx pixel density and since it's twice as much pixels, I just reduce the font size by half...that should work, right?
And since I use "em" on everything then by changing the font-size by half I automatically reduce size of everything "em"-sized by half...right?
#media ( min-resolution: 2dppx) {
body, html {
font-size: 50%;
}
}
relevant jsFiddle
Well I found it does not work as I thought it would...I tried to google answers but did not find anything relevant, I suspect I misunderstand how font-sizes, ems and pixel density works...
Reducing font-size by 50% reduces the font-size by much more than by half. The original size is 16px but font-size: 50%; results in a font much smaller than font-size:8px ... Tested in Firefox and Chrome. Does anyone know why is that?
When I set font-size:8px; in the media query for 2dppx then media queries for min-width:36em, 62em and 85em do not trigger as I would have expected, at least when I change layout.css.devPixelsPerPx in Firefox. The min-width in media query behaves like the font-size is still at 16px eventhough it's changed with the dppx media query. Tested in Firefox and Chrome. Does anyone know why is that?
UPDATE
Looks like media queries are loaded in 1dppx context, it does not matter if you use "em", it seems they are cached on load and values such as min-width are fixed to the first value and eventhough you change the base font-size in different media query, other queries don't refresh.
The only solution I can think of right now is to multiply all media queries. One media query for px value in 1 dppx context and another media query for px value in 2 dppx context (which is 50% of the first value).
Thanks to Mr Lister in comments, I found out that this:
#media ( min-resolution: 2dppx) {
body, html {
font-size: 50%;
}
}
...is not what I intended to do. The 50% rule works for <html> tag AND for <body> tag. The resulting font size is not 8px in body, but 4px, because 50% in html is 8px and another 50% in nested body tag results in 4px.
What I intended to do was this:
#media ( min-resolution: 2dppx) {
html {
font-size: 50%;
}
}
Font-size issue is solved.
For the media query: I found out that sizes in #media queries ignore pixel density but sizes in the CSS rule body do not. Since I use "em" sizes and SASS, I can simply replace all #media queries with this mixin (example with 2dppx):
#mixin media-min-width($min-width) {
#media(min-width:$min-width), (min-width: $min-width / 2) and (min-resolution: 2dppx) {
#content;
}
}
I have a Chrome-only problem with my Bootstrap (v3.3.5) layout css at exactly 767px where the layout styles simply aren't being applied.
Here's the behaviour after experimenting with the console on 3 browsers...
Chrome
-window.innerWidth of <= 766 - correctly shows mobile layout
-window.innerWidth of == 767 - incorrectly applies no layout styles
-window.innerWidth of >= 768 - correctly shows full screen layout
Firefox
-window.innerWidth of <=766 and ==767 - correctly shows mobile layout
-window.innerWidth of >=768 - correctly shows full screen layout
Safari
-behaves fine although window.innerWidth doesn't correctly correspond to the breakpoints (perhaps something to do with Safari not accounting for scrollbars in the same way)
All my media queries have been created as follows...
#media (max-width: 767px) {
/*small view*/
}
#media (min-width: 768px) {
/*full view*/
}
I've experimented changing these values so there's an overlap (e.g. a min-width of 767px) but it has no effect.
Apologies if this is a little vague, but I don't really know where to go from here in investigating the problem and have found only one report of similar behaviour from a previous version of bootstrap (https://github.com/twbs/bootstrap/issues/1531).
Does anyone know of any possible reason that I'd be seeing this on Chrome only? Either way, any advice on an appropriate way to investigate would be very much appreciated.
-- EDIT --
After hours of research I tested this simple file...
<html>
<head>
<style>
#media (max-width: 767px) {
.headlineText {
font-size: 10px;
color: red;
}
}
#media (min-width: 768px) {
.headlineText {
font-size: 10px;
color: green;
}
}
</style>
</head>
<body>
<h1 class="headlineText">this is a headline</h1>
</body>
</html>
On Chrome only - at 767px the text is neither green or red - it's black, Times New Roman, and considerably bigger than 10px. Of course I can't replicate this by uploading to a fiddle/codepen - so it must be something to do with the fact I'm running on a localhost (via MAMP). Absolutely zero ideas why that would be the case, but at least it doesn't seem to be something that will affect me in a live environment
Chrome (for me version 89.0.4389.82 on Win10) seems to work with fraction of pixels. Hence, increasing all lower breakpoint thresholds by .9px solved the issue for me. So for example
max-width :767px needs to become max-width :767.9px
Make this full screen and resize your window. It works for me in Chrome and has no display of "does not work" in between.
.works {
display: none;
}
.does-not-work {
display: block;
}
#media(max-width:767px){
.works {
display: block;
}
.works::before {
content: 'max-width: 767px | ';
}
.does-not-work {
display: none;
}
}
#media(min-width:768px){
.works {
display: block;
}
.works::before {
content: 'min-width: 768px | ';
}
.does-not-work {
display: none;
}
}
<span class="works">works</span>
<span class="does-not-work">does not work</span>
Side note, based on comments: About a year ago I had the same issue with a huge website. Result of a team of 6's work of nearly two years. Bits of code pouring in from all sides. I was the one gluing front-end together, making sure it all worked. You can imagine #media queries were a mess. I only got rid of the bug by refactoring all queries using mobile first principle - I grouped all #media's using Bootstrap's exact order. Fixed it for me. To this day I don't know what caused it. It was (slightly) broken on (exactly) 768px and 992px before.
Created a responsive site in Dreamweaver CS6 using the Fluid Grid system. All break points initially worked fine, and I had 3 separate layouts for desktop, tablet, and mobile; with different resolutions, each Fluid Grid Layout Div Tag would rearrange on the page into different columns. Every div on the page is set up with width: __%; in the CSS so that they expand and contract with the browser size.
Everything is responsive on the page and works correctly; however, somewhere during development I lost the Tablet break point, in a sense. When the browser reaches the 768px width which should break the page into the Tablet layout, it instead jumps straight to the mobile formatting, which should not happen until 480px.
In Dreamweaver, I can view the formatting I have set for the Tablet layout, in Design mode it will show me the correct layout of columns of DIVs and content; however, once I place DW in Live mode, or preview in a browser, it no longer has the Tablet functionality, just Desktop and Mobile formatting.
I will post the CSS code for the #media queries and the subsequent .gridContainer code - trying to see if a solution could be found without having to post the entire CSS code, as there's quite alot. Please let me know if I need to edit my question and include more code - perhaps the truncated code of a few DIVs and their responsive values for each layout? I'd be happy to post any more information if it will help resolve this issue.
Thank you in advance for any support or advice!
CSS:
/* Mobile Layout: 480px and below. */
.gridContainer:before, .container:after {
display:table;
content:"";
zoom:1 /* ie fix */;
}
.gridContainer:after {
clear:both;
}
.gridContainer {
width: 96%;
padding-left: 1.5%;
padding-right: 1.5%;
border:1px solid #00133e;
background: #004aa1;
}
/* Tablet Layout: 481px to 768px. Inherits styles from: Mobile Layout. */
#media only screen and (min-width: 481px) {
.gridContainer:before, .container:after {
display:table;
content:"";
zoom:1 /* ie fix */;
}
.gridContainer:after {
clear:both;
}
.gridContainer {
width: 96%;
padding-left: 1.5%;
padding-right: 1.5%;
}
}
/* Desktop Layout: 769px to a max of 1232px. Inherits styles from: Mobile Layout and Tablet Layout. */
#media only screen and (min-width: 769px) {
.gridContainer:before, .container:after {
display:table;
content:"";
zoom:1 /* ie fix */;
}
.gridContainer:after {
clear:both;
}
.gridContainer {
width: 96%;
padding-left: 1.5%;
padding-right: 1.5%;
}
}
Found the solution:
Near the end of my mobile layout CSS style code, there was an extra curly brace. Removed the brace, responsiveness returns.
Very simple solution; thanks to #MrRO for pointing me in the right direction to look!
Assuming, this is copy paste of actual code. In the given CSS, I believe you have have missed one curly braces, which was suppose to close the style for <480 width devices.
background: #004aa1;
} <-- Here one more "}" needed
/* Tablet Layout: 481px to 768px. Inherits styles from: Mobile Layout. */
#media only screen and (min-width: 481px) {
.gridContainer:before, .container:after {
The cascade is what makes CSS special and powerful. But in the case of media queries, overlap can seem problematic.
Consider the following CSS (continuing rules for CSS media query overlap):
/* Standard - for all screens below 20em */
body { color: black; font-size: 1em; }
/* Query A - slightly wider, mobile viewport */
#media (min-width: 20em) and (max-width: 45em) {
body { color: red; } /* supposed to be unique for this width */
}
/* Query B - everything else */
#media (min-width: 45em) {
body { font-size: larger; } /* because viewport is bigger */
}
So when the screen is exactly 45em wide, the overlap at 45em will be treated according to the standard CSS cascade:
All max-width: 45em definitions will be applied first,
and all min-width: 45em will be applied thereafter.
Consider these two conditions:
All text would normally be black, but Query A is unique and has color: red.
Since Query B is for larger viewports, it's text has the CSS font-size: larger.
Therefore, at a width of exactly 45em, we'd get big and red text. What would be the best solution to avoid this?
I see two possibilities:
Re-declare the text to have color: black in Query B, but then you're managing two declarations if you choose to change the color in the future. (Of course, not such a problem with this single line of code, but imagine there's a lot of other declarations and selectors.)
Avoid overlap by using pixel values like max-width: 799px and min-width: 800px, but then you're using pixels — I guess they could be 49.9375em and 50em, respectively. Though what if the default is no longer 16em and something gets rounded? And we're still not certain what happens at that gap. (A black hole that breaks the space-time continuum?)
Both have their drawbacks... any other ideas?
The only reliable way to create two mutually exclusive #media blocks for any given media query is to use not to negate it in one of the blocks. Unfortunately, this means repeating your media query once for each #media block. So, instead of this for example:
#media (max-width: 49.9375em) {
body {
color: red;
}
}
#media (min-width: 50em) {
body {
font-size: larger;
}
}
You would have this:
/*
* Note: Media Queries 4 still requires 'not' to be followed by a
* media type (e.g. 'all' or 'screen') for reasons I cannot comprehend.
*/
#media not all and (min-width: 50em) {
body {
color: red;
}
}
#media (min-width: 50em) {
body {
font-size: larger;
}
}
Interactive jsFiddle demo
This is very effective at closing the gap with range media features like width and height since it essentially turns this into an either-or scenario. But, like your first two options, it isn't perfect: as mentioned, you have to repeat the same media query twice, and add not to one of them. There is no if/else construct for #media as described in Conditional Rules 3.
Although I mention this in my answer to your previous question:
From my experiments it would seem Safari on iOS rounds all fractional pixel values to ensure that either one of max-width: 799px and min-width: 800px will match, even if the viewport is really 799.5px (which apparently matches the former).
It should be noted, still, that I've noticed some quirks when it comes to rounding. That said, I haven't been able to find a fractional value that would evade both media queries and end up not receiving styles from either set of rules (which, by the way, is the worst that can happen, so don't worry about potentially creating a space-time rift). That must mean browsers — at least, Safari as I've tested — do a reasonable job of ensuring they satisfy media queries even if you have values that differ (by exactly 1 CSS pixel).
When it comes to units with larger gaps that can be observed on desktop browsers, though, like ems, there is a much larger margin of error. For example, one comment suggests using 49.99999em instead of something more arbitrary than 49.9375em, but apparently there is a difference, at least with a default font size of 16px.
I simplified your code, changed the media queries to use decimal values, and put the code in jsFiddle:
#media (max-width: 49.9375em) {
body {
color: red;
}
}
#media (min-width: 50em) {
body {
font-size: larger;
}
}
If you resize the Result pane to exactly 800 pixels (the text will update to guide you along), you actually end up with different results depending on whether #media (max-width: 49.9375em) is used, or #media (max-width: 49.99999em) is used (I was surprised by this too)...
Either way, you're right: option 2 has its drawbacks too. I'm not particularly fond of it, to be honest, because I wouldn't want to crack my head over device and user agent quirks which are out of my control. If you're like me, I suppose it would be better to go through the inconvenience of redeclaring your rules at the cost (?) of being more vigilant around your code, as that's at least still within your control as an author.
For me, the best way is to keep a gap of 0.01em:
#media (min-width: 20em) and (max-width: 44.99em) {
body { color: red; } /* supposed to be unique for this width */
}
#media (min-width: 45em) {
body { font-size: larger; } /* because viewport is bigger */
}
I recommend you to read this article for the details and the comparison of the different solutions to prevent media query overlapping.
Cheers,
Thomas.