Confused at how max and min media queries work [duplicate] - css

This question already has answers here:
CSS media queries - Order matters?
(3 answers)
Closed 8 months ago.
So I understand the (min-width: 1400px) and (max-width: 1400px) are break points for when the CSS reaches those breakpoints it supposed to go back to its default sizing.
This is what I have done. I have my main CSS file that has its default sizing and another CSS file called query.css that controls the responsiveness of the web page.
This is how I have certain parts of both files to adjust accordingly
main CSS
.h1,.h2,.h3 {
font-size: 70px;
font-family: Cinzel, sans-serif;
}
.nav-link {
padding-left: 10rem !important;
}
query CSS
#media (min-width: 1400px) {
.h1,.h2,.h3 {
font-size: 1em;
}
.nav-link{
padding-left: 5em !important;
}
}
This is where it confuses me. The main CSS file settings are meant to be the main one, but the query CSS seems to overwrite the main CSS and it really messes up when I try and do responsive design.
I get that this min-width:1400px is meant to say if it goes from 2000px down to 1400px it must keep the min-width:1400px, but then what is the point of having the main CSS if the min-width:1400px just negates the main CSS file settings.
Its very frustrating working like this.

... it must keep the min-width:1400px ...
That's not how min-width works with media queries.
The min-width rule effectively says "apply this block of CSS if the viewport is at least this wide", in this case at least 1400px. if the viewport width is less than 1400px then the CSS surrounded by the media query will not be applied and the styles defined in main.css will take precedence.
#media (min-width: 1400px) {
/* CSS that is only applied if the viewport is >= 1400px */
}
Also, be careful about the order that the CSS files are included in the page. If query.css was included before then the media query it contains would always be over-ruled by the CSS in main.css.
It's a little more complicated than this when you take specificity in to account, but you should get the general idea.
For more info, take a look at the documentation for the media query min-width rule.

An important aspect of media-queries is structuring them correctly - especially if you're using a combination of #media (min-width: x) and #media (max-width: x).
CSS is read from top to bottom - this means that the last property applied to your desired selector will take priority, as long as its valid. This means that a more "precise/accurate" media-query rule prop will not take priority over another, if the media-query is placed below the other and both of their rules are valid. This means you can't just throw in media-queries at random locations in your CSS-file, because the CSS is just going to be overwritten.
Note that this doesn't apply on more specific selectors, but in my personal preference, I don't like mixing the specificity on a selector across multiple media-queries.
Because of this, you should always make media-query-rules with:
A descending pixel value if you're using max-width
An ascending pixel value if you're using min-width
In this example, the min-width-media-queries below the max-width-media-queries
This way, the first media-query will always take priority as long as its rules apply. When the second media-query's rule apply, that will take priority instead and so on. Try dragging the screen size of this code snippet in full page and you'll see how this code structuring works.
div {
width: 150px;
height: 150px;
background-color: red;
}
#media screen and (max-width: 412px) {
div {
background-color: green;
}
}
#media screen and (max-width: 360px) {
div {
background-color: yellow;
}
}
#media screen and (min-width: 320px) {
div {
background-color: orange;
}
}
#media screen and (min-width: 414px) {
div {
background-color: black;
}
}
#media screen and (min-width: 428px) {
div {
background-color: purple;
}
}
#media screen and (min-width: 768px) {
div {
background-color: pink;
}
}
#media screen and (min-width: 800px) {
div {
background-color: gray;
}
}
#media screen and (min-width: 820px) {
div {
background-color: limegreen;
}
}
#media screen and (min-width: 834px) {
div {
background-color: blue;
}
}
#media screen and (min-width: 884px) {
div {
background-color: teal;
}
}
<div></div>

Related

Style "splitting" at breakpoint, mediaqueries

I'm working on developing a style for a site and I'm using media queries as breakpoints. At the breakpoint, the page suddenly decides to listen to some style from the first interval, and some from the second. Please help.
I've tried changing the values of the viewports but this doesn't work. I hope this problem is obvious to someone with more experience than I, because I really don't know what to do.
#media (min-width: 500px) and (max-width: 768px) {
(ex.) #randomDiv {
background-color: blue;
width: 100px;
}
}
#media (min-width: 768px) and (max-width: 1023px) {
(ex.) #randomDiv {
background-color: red;
width: 300px;
}
}
When the viewport hits 768px it decides to mix styles, p.e. the background color changes to red, but the width doesn't change. Does anyone know what I'm doing wrong? After 768px (769px <) everything works just fine, as well as before 768px. Please help.
When using media queries to make your frontend code responsive, it is quite useful to think about the base or starting styles then use the queries to alter those styles in one direction only. What I mean is instead of using max-width and min-width in your queries, start with the non-query styling then override those rules with either min-width OR max-width but not both. This way the changes are seamless and you only need to think about the exact breakpoint location and which styles are being overridden.
In using this approach the order of the media queries in your stylesheet matter too. Notice the widest query goes first here, if I were using min-width instead it would go the other way around.
Try looking at this in "Full page" mode and change the size of your screen down from full width.
#randomDiv {
color: white;
margin: 0 auto;
padding: 20px;
/* only background-color & width will change */
background-color: purple;
width: 90%;
}
#media (max-width: 1023px) {
#randomDiv {
background-color: red;
width: 300px;
}
}
#media (max-width: 768px) {
#randomDiv {
background-color: blue;
width: 100px;
}
}
<div id="randomDiv">I am so random.</div>

Safari: Media query not firing at the expected width

I have written a CSS media query
like this -
#media screen and (max-width: 59.9375em) {
.left {
display: none;
}
}
This works fine across all the browsers except Safari 10.0.4 and below.
Safari seems to be handling the media queries differently.
Other browsers seem to be taking the window.innerWidth as viewport width for triggering media queries, but safari seems to be taking document.documentElement.clientWidth as viewport width and triggers the media queries accordingly.
I can see a difference of 15px between the actual and expected breakpoint.
I am looking for a cross-browser way for dealing with this issue.
Thoughts are welcome, thanks in advance.
The window width vs actual width is actually a super interesting topic. Snuggug has a really extensive explanation for it, but in short it's based on how the scroll bars are placed in different browsers.
Some browsers overlay the scroll bar on top of the content/site. Other browsers shorten the width of the content/site and have the scroll bar next to it. This obviously creates some discrepancies in how different browsers calculate the width of the viewport.
A potential problem is your usage of em as a unit of measurement.
It is important to remember that em is a measurement unit based on your current font size, and is therefore open to browser interpretation.
Depending on your font-family and overall font-size, 60em is usually around the area of 800px. Which means your query would be more specific looking like this:
#media screen and (max-width: 800px) {
.left {
display: none;
}
}
If you are unsure about the styling being overridden, you can always apply an important rule like this:
#media screen and (max-width: 800px) {
.left {
display: none !important;
}
}
If you would prefer to not use the !important tag in your CSS, then you will need to ensure that you look out for the two scenarios listed below:
CSS reads from Top to Bottom
This means that if you have a rule specified for your .left element, it needs to be placed before your media query and not after
The WRONG layout would look like this:
#media screen and (max-width: 800px) { //media query BEFORE rule
.left {
display: none;
}
}
.left {
.display:block;
}
The CORRECT layout would look like this:
.left {
.display:block;
}
#media screen and (max-width: 800px) { //media query AFTER rule
.left {
display: none;
}
}
The next bit to keep in mind is:
Nested CSS selectors take precedence
Use the same amount of parent selectors (or more) in your media query rule.
The WRONG series of selectors:
.container .left { //2 selectors used in query
.display:block;
}
#media screen and (max-width: 800px) {
.left { //only 1 selector used in query therefore overwritten by the previous rule - this should have atleast 2 selectors to overwrite the previous rule
display: none;
}
}
The CORRECT series of selectors:
.container .left { //2 selectors used in query
.display:block;
}
#media screen and (max-width: 800px) {
body .container .left { //3 selectors used in query
display: none;
}
}
use px (pixels) instead of em.
em is not fixed but it is relative. parsed different for different browsers.
#media screen and (max-width: 59.9375px) {
.left {
display: none;
}
}
try this css hack :
#media screen and (min-color-index:0) and(-webkit-min-device-pixel-ratio:0) {
#media {
.left {
display: none;
}
}}
Source : https://jeffclayton.wordpress.com/2015/04/28/css-hacks-for-safari-6-1-7-and-8-not-chrome/
You should read these two articles:
https://zellwk.com/blog/media-query-units/
https://adamwathan.me/dont-use-em-for-media-queries/
Then you'll understand why you have the problem you've asked about.
TLDR: em values are based on root font-size values, but in the case of Safari vs other browsers, em is either relative to the initial value or the root value (browsers pick one or the other for media queries, but not both, which can cause discrepancies across browsers)
you have to use media query after .left class as per the css rule
For example
.left {
display:inline;
}
#media screen and (max-width: 59.9375em) {
.left {
display: none !important; //important will override all the .left class.
}
}

CSS : Using same class within different media queries

I have the following code :
#media (min-width: 1200px) {
.color {
color: blue;
}
}
#media (min-width: 992px) {
.color {
color: red;
}
}
#media (min-width: 768px) {
.color {
color: green;
}
}
#media (max-width: 767px) {
}
<div class="color">Wow ji</div>
No matter what the screen size, Wow ji appears in green color only. What am I doing wrong here ?
In CSS, it is the last corresponding style that is applied, so in your code, as long as the screen is at least 768px, it will appear green.
You need either to set a max-width in the first tests, or do them in the inverse order.
Because what you are saying is at 768px or higher you want .color to be green you need to swap the order of your media queries around or use max-width
You have a bad syntax and usage, it's not even the same each time.
I would recommand doing like this :
#media screen and (max-width: 768px) { // or whatever screen size
.color {
color: green;
}
}
And you better add a <meta> viewport in your HTML to make your media queries working fine.
Some docs:
MDN - media queries
MDN - Using the viewport meta tag to control layout on mobile browsers
max-width is the maximum width at which these styles will be shown. A screen wider than the specified number will not use the styles associated with that rule. Similarly, min-width is the minimum width at which these styles will be shown. A screen narrower than the specified number will not use the styles associated with that rule. I have changed your code with max-width now its working fine all media queries , just resize the browser
#media ( min-width : 1200px) {
.color{
color: blue;
}
}
#media ( max-width : 992px) {
.color{
color: red;
}
}
#media(max-width:768px){
.color{
color: green;
}
}
#media(max-width:767px) {
.color{
color: yellow;
}
}
<div class="color">Wow ji</div>

Responsive design. Setting min-width in em

First example :
#media only screen and (min-width: 400px) {
body { background-color: blue; }
}
Rule will work with extensions more screen 400px.
Today met a different style to set rules :
#media only screen and (min-width: 40em) {
body { background-color: blue; }
}
What is the idea of using 40em ...? It's not even a fixed width. Under what conditions will apply this rule?
When to use this rule?

Using Sass mixin to set global variable [duplicate]

I'm trying to combine the use of a Sass variable with #media queries as follows:
$base_width:1160px;
#media screen and (max-width: 1170px) {$base_width: 960px;}
#media screen and (min-width: 1171px) {$base_width: 1160px;}
$base_width is then defined at various points in the stylesheet width percentage-based measurements to produce fluid layouts.
When I do this, the variable seems to be recognized properly but the conditions for the media query are not. For example, the above code produces an 1160px layout regardless of screen width. If I flip-flop the #media statements like so:
#media screen and (min-width: 1171px) {$base_width: 1160px;}
#media screen and (max-width: 1170px) {$base_width: 960px;}
It produces a 960px layout, again regardless of screen width. Also note that if I remove the first line of $base_width: 1160px; it returns an error for an undefined variable. Any ideas what I'm missing?
This is simply not possible. Since the trigger #media screen and (max-width: 1170px) happens on the client-side.
Achieving your expected result would only be possible if SASS grabbed all rules and properties in your stylesheet containing your $base_width variable and copied/changed them accordingly.
Since it won't work automatically you could do it by hand like this:
#media screen and (max-width: 1170px)
$base_width: 960px // you need to indent it to (re)set it just within this media-query
// now you copy all the css rules/properties that contain or are relative to $base_width e.g.
#wrapper
width: $base_width
...
#media screen and (min-width: 1171px)
$base_width: 1160px
#wrapper
width: $base_width
...
This is not really DRY but the best you can do.
If the changes are the same every time you could also prepare a mixin containing all the changing values, so you wouldn't need to repeat it. Additionally you can try to combine the mixin with specific changes. Like:
#media screen and (min-width: 1171px)
+base_width_changes(1160px)
#width-1171-specific-element // additional specific changes, that aren't in the mixin
display: block
And the Mixin would look like this
=base_width_changes($base_width)
#wrapper
width: $base_width
Similar to Philipp Zedler's answer, you can do it with a mixin. That lets you have everything in a single file if you want.
#mixin styling($base-width) {
// your SCSS here, e.g.
#Contents {
width: $base-width;
}
}
#media screen and (max-width: 1170px) {
#include styling($base-width: 960px);
}
#media screen and (min-width: 1171px) {
#include styling($base-width: 1160px);
}
This isn't possible with SASS, but it is possible with CSS variables (or CSS custom properties). The only drawback is browser support – but there's actually a PostCSS plugin - postcss-css-variables - that "flattens" the use of CSS variables (which gives you support for older browsers, too).
The following example works great with SASS (and with postcss-css-variables you get support for older browsers too).
SCSS
$mq-laptop: 1440px;
$mq-desktop: 1680px;
:root {
--font-size-regular: 14px;
--gutter: 1rem;
}
// The fact that we have to use a `max-width` media query here, so as to not
// overlap with the next media query, is a quirk of postcss-css-variables
#media (min-width: $mq-laptop) and (max-width: $mq-desktop - 1px) {
:root {
--font-size-regular: 16px;
--gutter: 1.5rem;
}
}
#media (min-width: $mq-desktop) {
:root {
--font-size-regular: 18px;
--gutter: 1.75rem;
}
}
.my-element {
font-size: var(--font-size-regular);
padding: 0 calc(var(--gutter) / 2);
}
This would result in the following CSS. The repetitive media queries will increase the file size, but I have found that the increase is usually negligible once the web server applies gzip (which it will usually do automatically).
CSS
.my-element {
font-size: 14px;
padding: 0 calc(1rem / 2);
}
#media (min-width: 1680px) {
.my-element {
padding: 0 calc(1.75rem / 2);
}
}
#media (min-width: 1440px) and (max-width: 1679px) {
.my-element {
padding: 0 calc(1.5rem / 2);
}
}
#media (min-width: 1680px) {
.my-element {
font-size: 18px;
}
}
#media (min-width: 1440px) and (max-width: 1679px) {
.my-element {
font-size: 16px;
}
}
Edit: Please do not use this solution. The answer by ronen is much better.
As a DRY solution, you can use the #import statement inside a media query, e.g. like this.
#media screen and (max-width: 1170px) {
$base_width: 960px;
#import "responsive_elements";
}
#media screen and (min-width: 1171px) {
$base_width: 1160px;
#import "responsive_elements";
}
You define all responsive elements in the file included using the variables defined in the media query. So, all you need to repeat is the import statement.
With #ronen's great answer and a map, there's some real power available:
#mixin styling($map) {
.myDiv {
background: map-get($map, 'foo');
font-size: map-get($map, 'bar');
}
}
#media (min-height: 500px) {
#include styling((
foo: green,
bar: 50px
));
}
#media (min-height: 1000px) {
#include styling((
foo: red,
bar: 100px
));
}
It's now possible to have lots more DRY media queries targeting .myDiv with a bunch of different values.
Map docs: https://sass-lang.com/documentation/functions/map
Example map usage: https://www.sitepoint.com/using-sass-maps/
I had the same problem.
The $menu-width variable should be 240px on the mobile view #media only screen and (max-width : 768px) and 340px on the desktop view.
So i have simply created two variables:
$menu-width: 340px;
$menu-mobile-width: 240px;
And here is how i have used it:
.menu {
width: $menu-width;
#media only screen and (max-width : 768px) {
width: $menu-mobile-width;
}
}
Two recommendations
1
Write your "default" CSS statements to be for small screens and only use media queries for larger screens. There's usually no need for a max-width media query.
Example (assuming the element has class "container")
#mixin min-width($width) {
#media screen and (max-width: $width) {
#content;
}
}
.container {
width: 960px;
#include min-width(1170px) {
width: 1160px;
}
}
2 Use CSS variables to solve the problem, if you can.
#mixin min-width($width) {
#media screen and (max-width: $width) {
#content;
}
}
:root {
--container-width: 960px;
#include min-width(1170px) {
--container-width: 1160px;
}
}
.container {
width: var(--container-width);
}
Note:
Since it will have the width of 1160px when the window has a width of 1170px, it may be better to use a width of 100% and max-width of 1160px, and the parent element might have a horizontal padding of 5px, as long as the box-sizing property is set to border-box. There are a lot of ways to solve the problem. If the parent is not a flex or grid container you might use .container { margin: auto }.
This is also possible with %placeholders.
%placeholders can be wrapped in media queries. So you could set up multiple variables to use at different screen sizes, and then the placeholders would automagically pre-process accordingly. I'm using some mixins to shorten my media query declarations here also.
In your _vars.scss file:
$width-1: 960px;
$width-2: 1160px;
In your _placeholders.scss file:
%variable-site-width {
#media screen and (max-width: 1170px) { width: $width-1; }
#media screen and (min-width: 1171px) { width: $width-2; }
}
In your page.scss file:
.wrapper. { #extend %variable-site-width; background: red; etc... }
And this will compile to something similar to:
#media screen and (max-width: 1170px) {
.wrapper { width: 960px; }
}
#media screen and (min-width: 1171px) {
.wrapper { width: 1160px; }
}
Voila!
I use this technique extensively for things like variable font sizes and a raft of other things.

Resources