Can you explain the guidelines for overlapping CSS media queries?

When it comes to spacing out media queries accurately to prevent overlap, how should we approach it?

Let's examine the following code as an example:

@media (max-width: 20em) {
    /* styles for narrow viewport */
}

@media (min-width: 20em) and (max-width: 45em) {
    /* styles for slightly wider viewport */
}

@media (min-width: 45em) {
    /* styles for everything else */
}

What happens at exactly 20em and 45em across different browsers that support these queries?

I've noticed that some people use specific pixel values like 799px and then 800px, but what about situations where the screen width is something like 799.5px? Especially on high-resolution displays like retina screens.


I'm particularly interested in understanding the specifications behind this query handling.

Answer №1

What are the guidelines for CSS media query overlap?

Cascade.

@media rules follow the cascade, meaning that when multiple @media rules match simultaneously, browsers should apply styles from all matching rules and resolve any conflicts through cascading.1

What occurs in all supported browsers at exactly 20em and 45em width?

When the viewport is precisely 20em wide, both your first and second media queries will match. Browsers will apply styles from both @media rules, resolving conflicts by giving precedence to the last-declared rule. The same applies when the viewport width is exactly 45em for the second and third media queries.

In your provided example code with actual style rules:

@media (max-width: 20em) {
    .sidebar { display: none; }
}

@media (min-width: 20em) and (max-width: 45em) {
    .sidebar { display: block; float: left; }
}

At exactly 20em wide, both media queries will be true. In this case, display: block overrides display: none, and float: left will be applied to elements with the class .sidebar.

The cascade operates as if the media query conditions did not exist initially:

.sidebar { display: none; }
.sidebar { display: block; float: left; }

To prevent overlap, ensure that your media queries do not intersect.

Remember, both min- and max- prefixes signify "minimum inclusive" and "maximum inclusive," respectively. Thus, (min-width: 20em) and (max-width: 20em) will both match a viewport of exactly 20em in width.

Regarding fractional pixel values such as 799.5px, it's unclear how browsers handle them precisely due to logical pixels in CSS. Safari on iOS appears to round fractional values to ensure they fit within defined ranges like max-width: 799px or min-width: 800px.


1 While not explicitly stated in the Conditional Rules module or the Cascade module (which is set for revision), the standard implies normal cascading behavior, instructing browsers to apply styles from all matching @media rules without special hierarchy.

Answer №2

Following the recommended approach, I attempted the following:

@media screen and (max-width: calc(48em - 1px)) {
    /*mobile styles*/
}
@media screen and (min-width: 48em) {
    /*desktop styles*/
}

Unfortunately, this method proved to be ineffective as it did not work on Chrome either on my Ubuntu desktop or Android phone. This issue is discussed further here: calc() not working within media queries. However, I discovered an alternative solution...

@media screen and (max-width: 47.9999em) {
    /*mobile styles*/
}
@media screen and (min-width: 48em) {
    /*desktop styles*/
}

Success!

Answer №3

calc() can be utilized in order to address this issue

(min-width: 50em and max-width: calc(50em - 1px)
will be displayed correctly stacked), however, due to poor browser support, I do not recommend it.

@media (min-width: 20em) and (max-width: calc(45em - 1px)) {
    /* for slightly wider viewport */
}

Information:

Some have suggested that avoiding the em unit would improve the stacking of your queries.

Answer №4

Recently, I made an interesting discovery while experimenting with device emulation in MS Edge (v118.0.2088.46) within DevTools. When selecting Responsive dimensions and setting a width of 599px, I noticed that the specified media query was not being applied as expected:

@media (max-width: 599px) {
    ...
}

Strangely, adjusting the display width to 598px or slightly modifying the media query to max-width: 599.5px results in the desired outcome. It seems like there may be some sort of internal rounding issue causing this behavior.

I also observed the same issue in Chrome version 118.0.5993.89 and Firefox version 118.0.2.

Answer №5

Starting from March 2023, newer browsers (check out Can I Use) have implemented support for the new range syntax. This allows for more concise expressions of queries. For instance, you can now write width <= 20em instead of max-width: 20em.

What's interesting about this syntax is that it not only supports the <= and >= operators (similar to min-width and max-width comparisons), but also includes < and >. You now have the ability to make a decision on whether or not to include the endpoints of your range!

Take for example your original query:

@media (width < 20em) {
    /* styles for narrow viewport */
}

@media (20em <= width < 45em) {
    /* styles for slightly wider viewport */
}

@media (width >= 45em) {
    /* styles for everything else */
}

This eliminates any uncertainty when dealing with specific viewport widths like exactly 20 em. It clarifies that only the second rule will apply in that scenario. Similarly, at exactly 45 em, only the third rule will take effect.

If desired, you can modify some of the <= comparisons to < and vice versa. This way, when the viewport is exactly 20 em wide, the first rule will be triggered instead of the second. You also have the option to have both rules applied at the breakpoints if needed. The key point here is that you now have control over what happens at precise width points in your design.

Answer №6

If you only have two options, you can utilize the not operator:

@media (max-width: 20em) {
    html { background-color: red; }
}

@media not all and (max-width: 20em) {
    html { background-color: blue; }
}

Please Note: Including all in the query is necessary to use not.

Note: The not operator will negate the entire query regardless of parentheses, see: Inverting a query's meaning

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Personalized Pinterest button to link to a custom URL (Text Link, Image, or Both)

I've been searching for a solution without success. I'm looking to customize the image for my Pinterest (Pin It) button and pin a specific image by URL, not just the current page. Here is the custom link I created: <a href="http://pinterest. ...

Having trouble with the Wordpress JS CSS combination not functioning properly and unable to determine the cause

I recently set up a page on my WordPress site using the Twenty Seventeen theme. At the top of the page, I created a toolbar for users to easily adjust the font size and background color. Check out the image below for reference: See Image for Bar Here&apo ...

Getting rid of all CSS properties currently set for the Mobile view

Utilizing third-party library components in my project. The library includes components that come with predefined styles for mobile devices. I am seeking to completely UPDATE these properties within my own code. When I say "update," I mean removing all th ...

`The height attribute of the textarea element is not being accurately adjusted`

When I tried to match the width(178px) and height(178px) of my table to the width and height of a text area upon clicking a button, I encountered an issue. While setting the width works perfectly fine, the height is being set to only 17px. It seems like ...

In a Twitter Bootstrap environment, the button cursor transforms into an I-beam when activated

After utilizing twitter bootstrap to construct a small blog site and integrating a third-party file upload application into the project, I encountered an issue. The CSS files in the file uploader style the "upload button," but when my cursor hovers over it ...

What is the best method for resetting the CSS style of a specific DOM subtree?

While working on a Chrome Extension, I encountered a problem where an HTML subtree and CSS style sheet injected into the original page were being affected by the original CSS. Despite my attempts to override the styles, it seemed unfeasible to manually set ...

How can CSS be used to format an unordered list around images?

Can anyone suggest ways to improve the formatting of this HTML list when wrapping around a left-floated image? I often encounter this small problem while working on client websites: The image has a right-margin, but it doesn't seem to affect the ... ...

The properties of margin:auto and text-align:center are failing to function as expected

I'm facing an issue while creating a website. The 'margin: auto' and 'text-align: center' properties in my CSS code seem to not be functioning as expected. Can someone please review my code in inspect element and identify the probl ...

How to Ensure an Absolutely Positioned Element Occupies the Full Width of its Container

My main content area has a sidebar positioned absolutely to the right side due to various reasons. However, I am facing an issue where if the main content area is shorter, the sidebar extends beyond the content. Do you know of any CSS technique that can h ...

Struggling with a CSS problem that jQuery can't seem

I recently experimented with Infogrid on my website. After adding a header and footer, I noticed that the text in the last block of iron man was being cut off. Even though I removed overflow:hidden; from the body and html, the issue persisted with the te ...

Improper Alignment of Bootstrap 4 Navbar Link: Troubleshooting Required

Take a look at the image for the issue: https://i.stack.imgur.com/u9aCy.png As shown in the image, the NavBar links are stacked instead of being displayed in one row. This is the HTML code I have used: <!doctype html> <html> <head> ...

Issue with vertical alignment in form input text area not functioning properly

Need some help aligning inputted text with the top of a textarea on an HTML form. I've scoured forums for solutions, but no luck so far. I attempted using: textarea{ vertical-align:top;} and input["textarea"]{ vertical-align:top;} Tried adding ...

Creating a flexible grid layout with DIVs that share equal width dimensions

Struggling with my HTML and CSS code, I need a way to structure nested DIV blocks into a responsive grid where each block has the same width. Despite my efforts, nothing seems to work as expected. Currently, the nested DIVs are stacked vertically one on to ...

Tips for applying personalized CSS to individual Toast notifications in Angular

MY QUESTION : I am looking to customize the CSS of a single toast used in Angular components. While there may be multiple toasts, I specifically want to style one particular toast differently. For example, the toast image can be viewed here: example toast ...

Avoiding duplicate touch events with an if statement

I am currently working on a module for a responsive website that involves tapping the initial screen to reveal a panel from the right. The user can then tap a close button to hide the panel. However, there is an issue where if the user taps multiple times ...

Having trouble with Python Bottle <br /> not functioning properly?

I encountered a perplexing issue and I am unsure of how to resolve it: There is a text area where users can input their text. For example, let's say the following is entered : This is the user's text After storing this in my database and ret ...

Tips on changing the outline color by clicking

I'm working on a simple code where I need to change the outline color when a user clicks on a text field. <input type="text" id="box1" /> <input type="password" id="box2" /> <input type="email" id="box3" /> <input type="submit" ...

Introducing a new feature that allows automatic line breaks when using the detail

Looking to achieve centered text for a summary where the arrow, when clicked, reveals additional details. However, currently, the text and arrow are on separate lines. The goal is to have the arrow on the same line as the summary text and perfectly center ...

Issue with multiple dropdown menus not closing when clicked on

The current implementation provides the functionality to convert select boxes into list items for styling purposes. However, a drawback of the current setup is that once a dropdown is opened, it can only be closed by clicking on the document or another dr ...

The Autoprefixer script crashes with the error message: TypeError - Patterns can only be a string or an array of strings

After successfully installing autoprefixer and postcss-cli, I embarked on setting up a simple build process with NPM scripts using my command prompt and VS code. As someone with only 2 months of coding experience, I was following a tutorial on CSS/SASS top ...