{"id":382,"date":"2024-05-16T15:00:00","date_gmt":"2024-05-16T15:00:00","guid":{"rendered":"https:\/\/kerrprogroup.com\/?p=382"},"modified":"2025-03-19T12:20:49","modified_gmt":"2025-03-19T12:20:49","slug":"beyond-css-media-queries","status":"publish","type":"post","link":"https:\/\/kerrprogroup.com\/index.php\/2024\/05\/16\/beyond-css-media-queries\/","title":{"rendered":"Beyond CSS Media Queries"},"content":{"rendered":"

Beyond CSS Media Queries<\/title><\/p>\n<article>\n<header>\n<h1>Beyond CSS Media Queries<\/h1>\n<address>Juan Diego Rodr\u00edguez<\/address>\n<p> 2024-05-16T15:00:00+00:00<br \/>\n 2025-03-19T12:04:52+00:00<br \/>\n <\/header>\n<p>Media queries have been around almost as long as CSS itself \u2014 and with no flex, no grid, no responsive units, and no math functions, media queries were <strong>the most pragmatic choice<\/strong> available to make a somewhat responsive website.<\/p>\n<p>In the early 2010s, with the proliferation of mobile devices and the timely publication of <a href=\"https:\/\/alistapart.com\/article\/responsive-web-design\/\">Ethan Marcotte\u2019s classic article \u201cResponsive Web Design\u201d<\/a>, media queries became much needed for crafting layouts that could morph across screens and devices. Even when the CSS Flexbox and Grid specifications rolled out, media queries for resizing never left.<\/p>\n<p><a href=\"https:\/\/chromestatus.com\/features\">While data on the actual usage of media queries is elusive<\/a>, the fact that they have <em>grown over time<\/em> with additional features that go well beyond the viewport and into things like user preferences continues to make them a <strong>bellwether ingredient for responsive design<\/strong>.<\/p>\n<p>Today, there are more options and tools in CSS for establishing layouts that allow page elements to adapt to many different conditions besides the size of the viewport. Some are more widely used \u2014 Flexbox and Grid for certain \u2014 but also things like responsive length units and, most notably, <a href=\"https:\/\/www.smashingmagazine.com\/2021\/05\/complete-guide-css-container-queries\/\">container queries<\/a>, a concept we will come back to in a bit.<\/p>\n<p>But media queries are still often the <em>de facto<\/em> tool that developers reach for. Maybe it\u2019s muscle memory, inconsistent browser support, or that we\u2019re stuck in our ways, but adoption of the modern approaches we have for responsive interfaces seems slow to take off.<\/p>\n<p>To be clear, <strong>I am all for media queries<\/strong>. They play a significant role in the work we do above and beyond watching the viewport size to make better and more accessible user experiences based on a user\u2019s OS preferences, the type of input device they\u2019re using, and more.<\/p>\n<p>But should media queries continue to be the gold standard for responsive layouts? As always, it depends, but<\/p>\n<blockquote class=\"pull-quote\">\n<p>\n <a class=\"pull-quote__link\" aria-label=\"Share on Twitter\" href=\"https:\/\/twitter.com\/share?text=%0aIt%20is%20undeniable%20that%20media%20queries%20have%20evolved%20toward%20accessibility%20solutions,%20making%20space%20for%20other%20CSS%20features%20to%20take%20responsibility%20for%20responsiveness.%0a&url=https:\/\/smashingmagazine.com%2f2024%2f05%2fbeyond-css-media-queries%2f\"><\/p>\n<p>It is undeniable that media queries have evolved toward accessibility solutions, making space for other CSS features to take responsibility for responsiveness.<\/p>\n<p> <\/a>\n <\/p>\n<div class=\"pull-quote__quotation\">\n<div class=\"pull-quote__bg\">\n <span class=\"pull-quote__symbol\">\u201c<\/span><\/div>\n<\/p><\/div>\n<\/blockquote>\n<h2 id=\"the-problem-with-media-queries\">The Problem With Media Queries<\/h2>\n<p>Media queries seemed like a great solution for most responsive-related problems, but as the web has grown towards bigger and more complex layouts, <strong>the limits of media queries are more prevalent than ever<\/strong>.<\/p>\n<h3 id=\"problem-1-they-are-viewport-focused\">Problem #1: They Are Viewport-Focused<\/h3>\n<p>When writing media query breakpoints where we want the layout to adapt, we only have access to the viewport\u2019s properties, like <code>width<\/code> or <code>orientation<\/code>. Sometimes, all we need is to tweak a font size, and the viewport is our best bud for that, but most times, <strong>context is important<\/strong>.<\/p>\n<p>Components on a page share space with others and are positioned <em>relative<\/em> to each other according to normal document flow. If all we have access to is the viewport width, knowing exactly where to establish a particular breakpoint becomes a task of compromises where some components will respond well to the adapted layout while others will need additional adjustments at that specific breakpoint.<\/p>\n<p>So, there we are, resizing our browser and looking for the correct breakpoint where our content becomes too squished.<\/p>\n<p>The following example probably has the worst CSS you will see in a while, but it helps to understand one of the problems with media queries.<\/p>\n<figure class=\"break-out\">\n<p data-height=\"480\" data-theme-id=\"light\" data-slug-hash=\"xxNwbob\" data-user=\"smashingmag\" data-default-tab=\"result\" class=\"codepen\">See the Pen [Old Media Queries [forked]](https:\/\/codepen.io\/smashingmag\/pen\/xxNwbob) by <a href=\"https:\/\/codepen.io\/monknow\">Monknow<\/a>.<\/p><figcaption>See the Pen <a href=\"https:\/\/codepen.io\/smashingmag\/pen\/xxNwbob\">Old Media Queries [forked]<\/a> by <a href=\"https:\/\/codepen.io\/monknow\">Monknow<\/a>.<\/figcaption><\/figure>\n<p>It\u2019s a pretty embarrassing example, but why exactly is it bad?<\/p>\n<p>If we try to convert the CSS verbatim, it would say, <em>When the page width is smaller than <code>600px<\/code>, these elements will grow and collapse.<\/em> This statement is completely agnostic to the element\u2019s contents or its siblings. What happens if there are more siblings or just one? Or what happens if the element is inside a smaller container? The media query simply lacks the information we need to account for these things, which leads us to a second problem with media queries.<\/p>\n<h3 id=\"problem-2-they-are-difficult-to-manage\">Problem #2: They Are Difficult To Manage<\/h3>\n<p>Nowadays everything is a component. Like nomads, components wander from place to place, sharing space with other components and bringing along their ever-changing content. Again, media queries are completely unaware of the context surrounding a component, and the burden lies on the developer to find that sweet spot for each and every case.<\/p>\n<p>This is cumbersome work because the ideal breakpoint in a media query is <a href=\"https:\/\/css-tricks.com\/magic-numbers-in-css\/\">kind of a hardcoded _magic number<\/a> that we find by resizing our page, and also because it will differ depending on the context surrounding each component, necessitating multiple media queries. If we want to change an element\u2019s content or container, then the media query needs to change, too.<\/p>\n<p>And where do you manage media queries in your stylesheet? Some developers will plop them in at the end, while others may manage them in partial files and rely on a preprocessor to compile them.<\/p>\n<p>The recent CSS Nesting feature makes things cleaner now that we can attach a media query to a component in the same style rule, but now we have to do that for each and every component in the system, which makes for more and more instances to account for when editing styles. This leads to the next problem with media queries as a responsive silver bullet.<\/p>\n<h3 id=\"problem-3-they-aren-t-that-responsive\">Problem #3: They Aren\u2019t That Responsive<\/h3>\n<p>Most times, we want an element to resize itself fluidly with the screen, but writing a new media query each time a component \u201cbreaks\u201d at a specific breakpoint is a lot to manage. If a component becomes too tall on a narrow screen when the viewport is between <code>960px<\/code> and <code>970px<\/code>, do we really need to write a new set of styles that we now have to look after?<\/p>\n<p>I wouldn\u2019t exactly call that <em>responsive<\/em> design but rather some form of adaptive design based on hard numbers for a super-specific situation. There\u2019s no fluidity in that.<\/p>\n<div data-audience=\"non-subscriber\" data-remove=\"true\" class=\"feature-panel-container\">\n<aside class=\"feature-panel\">\n<div class=\"feature-panel-left-col\">\n<div class=\"feature-panel-description\">\n<p>Meet <strong><a data-instant href=\"https:\/\/www.smashingconf.com\/online-workshops\/\">Smashing Workshops<\/a><\/strong> on <strong>front-end, design & UX<\/strong>, with practical takeaways, live sessions, <strong>video recordings<\/strong> and a friendly Q&A. With Brad Frost, St\u00e9ph Walter and <a href=\"https:\/\/smashingconf.com\/online-workshops\/workshops\">so many others<\/a>.<\/p>\n<p><a data-instant href=\"smashing-workshops\" class=\"btn btn--green btn--large\">Jump to the workshops\u00a0\u21ac<\/a><\/div>\n<\/div>\n<div class=\"feature-panel-right-col\"><a data-instant href=\"smashing-workshops\" class=\"feature-panel-image-link\"><\/p>\n<div class=\"feature-panel-image\">\n<img decoding=\"async\" loading=\"lazy\" class=\"feature-panel-image-img lazyload\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"Feature Panel\" width=\"257\" height=\"355\" data-src=\"\/images\/smashing-cat\/cat-scubadiving-panel.svg\"><\/p>\n<\/div>\n<p><\/a>\n<\/div>\n<\/aside>\n<\/div>\n<h2 id=\"you-don-t-need-media-queries-for-resizing\">You Don\u2019t Need Media Queries (For Resizing)<\/h2>\n<p>Fortunately, we\u2019re no longer living in 2012, and there are far better options than media queries, most of them largely adopted and widely supported, led by the likes of <a href=\"https:\/\/css-tricks.com\/snippets\/css\/a-guide-to-flexbox\/\">Flexbox<\/a> and <a href=\"https:\/\/css-tricks.com\/snippets\/css\/complete-guide-grid\/\">Grid<\/a>, <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Learn\/CSS\/Building_blocks\/Values_and_units#numbers_lengths_and_percentages\">responsive units<\/a> and <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/CSS_Functions\/Using_CSS_math_functions\">math functions<\/a>, while others like <a href=\"https:\/\/developer.mozilla.org\/es\/docs\/Web\/CSS\/CSS_containment\/Container_queries\">container queries<\/a> are on the cusp, but still in relatively early days.<\/p>\n<p>I am not going to act like I discovered hot water by pointing out that these modern CSS features exist and are now commonplace tools used by nearly every CSS developer. However, media queries still find their way into CSS for resizing, particularly in situations where a <code>clamp()<\/code> function or a bit of creative thinking with responsive units would not only accomplish the task but do it better than a media query because they are designed for this purpose.<\/p>\n<p>So rather than me trying to teach all these not-entirely-new CSS features (you are awesome, and I am confident you are already aware of them), my focus is on swapping your existing media queries for modern responsive techniques.<\/p>\n<h3 id=\"flexbox\">Flexbox<\/h3>\n<p>Flexbox and media queries are often paired together so that Flexbox establishes a layout in a certain direction, and media queries are used to change direction at certain viewport widths.<\/p>\n<figure class=\"break-out\">\n<p data-height=\"480\" data-theme-id=\"light\" data-slug-hash=\"MWdaYNx\" data-user=\"smashingmag\" data-default-tab=\"result\" class=\"codepen\">See the Pen [Using Media Queries with Flex Items [forked]](https:\/\/codepen.io\/smashingmag\/pen\/MWdaYNx) by <a href=\"https:\/\/codepen.io\/monknow\">Monknow<\/a>.<\/p><figcaption>See the Pen <a href=\"https:\/\/codepen.io\/smashingmag\/pen\/MWdaYNx\">Using Media Queries with Flex Items [forked]<\/a> by <a href=\"https:\/\/codepen.io\/monknow\">Monknow<\/a>.<\/figcaption><\/figure>\n<p>This very simple \u2014 but common \u2014 pattern runs into each of the three problems we discussed earlier:<\/p>\n<ol>\n<li><strong>It\u2019s viewport-focused.<\/strong><br \/>\nWe are only considering the viewport width when choosing where the container changes direction. I found the magic breakpoint number is <code>700px<\/code> after testing, so that is where we would need to establish a new media query.<\/li>\n<li><strong>It\u2019s hard to reuse and manage.<\/strong><br \/>\nSince we are only considering the viewport width, the element can\u2019t be used inside a smaller container or may look awkward if the element has different content within it or around it.<\/li>\n<li><strong>It isn\u2019t that responsive.<\/strong><br \/>\nWe have a breakpoint at <code>700px<\/code>, so devices with narrow screens beyond the threshold may squish the content too much while others get the optimal experience.<\/li>\n<\/ol>\n<p>If we try to fix it by adding more media queries, we\u2019ll be back at Problem #2.<\/p>\n<p>The best solution for this case is to avoid media queries altogether. I would replace them with the <code>flex<\/code> shorthand property that allows the <code><\/p>\n<article><\/article>\n<p><\/code> elements to grow and shrink based on the available space up to a certain point that\u2019s set to <code>400px<\/code>.<\/p>\n<pre><code class=\"language-css\">main {\n display: flex;\n flex-flow: row wrap;\n}\n\nmain article {\n flex: 1 1 400px;\n}\n<\/code><\/pre>\n<p>If we translated the CSS, the former example with the media query says, <em>When the viewport is smaller than <code>700px<\/code>, I will make the elements wrap. Why? I don\u2019t really know.<\/em> Again, the query is aloof to an article\u2019s context. If we translate the updated example, it says something along the lines of, <em>No matter where the element is, I will try my best to make it <code>400px<\/code> but will adjust it if the available space changes.<\/em><\/p>\n<p>Resize the following demo. See how much nicer the articles flow as the screen changes size?<\/p>\n<figure class=\"break-out\">\n<p data-height=\"480\" data-theme-id=\"light\" data-slug-hash=\"jOobPNe\" data-user=\"smashingmag\" data-default-tab=\"result\" class=\"codepen\">See the Pen [Flex Items without Media Queries [forked]](https:\/\/codepen.io\/smashingmag\/pen\/jOobPNe) by <a href=\"https:\/\/codepen.io\/monknow\">Monknow<\/a>.<\/p><figcaption>See the Pen <a href=\"https:\/\/codepen.io\/smashingmag\/pen\/jOobPNe\">Flex Items without Media Queries [forked]<\/a> by <a href=\"https:\/\/codepen.io\/monknow\">Monknow<\/a>.<\/figcaption><\/figure>\n<p>And we pulled it off with less code and zero magic numbers.<\/p>\n<div class=\"partners__lead-place\"><\/div>\n<h3 id=\"grid\">Grid<\/h3>\n<p>The last example is nice, but you may notice that the last flexible item is able to take all the available space in the last row instead of remaining the same size as its siblings. If you want all flexible items to be the same size, you would have to mess with their width and maybe again with media queries. In most cases <strong>where you find yourself slapping a <code>width<\/code> on a flexible item, it\u2019s a sign that you are better off switching to Grid instead<\/strong>, as we can establish specific tracks for columns and rows.<\/p>\n<p>Fortunately, we can make it happen with just two lines of CSS:<\/p>\n<pre><code class=\"language-css\">main {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));\n}\n<\/code><\/pre>\n<p>To briefly break down what happened:<\/p>\n<ul>\n<li><strong><code>auto-fit<\/code><\/strong> fits as many columns as it can and also expands them if there is any leftover space.<\/li>\n<li><strong><code>minmax<\/code><\/strong> specifies a minimum width for the columns, <code>500px<\/code> in this case.<\/li>\n<\/ul>\n<figure class=\"break-out\">\n<p data-height=\"480\" data-theme-id=\"light\" data-slug-hash=\"RwmWPwV\" data-user=\"smashingmag\" data-default-tab=\"result\" class=\"codepen\">See the Pen [Grid without Media Queries [forked]](https:\/\/codepen.io\/smashingmag\/pen\/RwmWPwV) by <a href=\"https:\/\/codepen.io\/monknow\">Monknow<\/a>.<\/p><figcaption>See the Pen <a href=\"https:\/\/codepen.io\/smashingmag\/pen\/RwmWPwV\">Grid without Media Queries [forked]<\/a> by <a href=\"https:\/\/codepen.io\/monknow\">Monknow<\/a>.<\/figcaption><\/figure>\n<blockquote><p><strong>Note<\/strong>: Sara Soueidan has what may be <a href=\"https:\/\/css-tricks.com\/auto-sizing-columns-css-grid-auto-fill-vs-auto-fit\/\">the best explanation of this approach<\/a>, and it is definitely worth a read. It may just be your new favorite CSS snippet.<\/p><\/blockquote>\n<h3 id=\"math-functions-responsive-units\">Math Functions & Responsive Units<\/h3>\n<p>Math functions and responsive units cover most problems related to resizing elements. They set responsive limits without having to painstakingly define specific breakpoints. They are fully supported in modern browsers and already in widespread use, so we\u2019ll simply summarize the <em>what<\/em> and <em>why<\/em> of what\u2019s available.<\/p>\n<p>Using the <strong><code>min()<\/code> function<\/strong>, we can make elements resize depending on a responsive unit like <strong>viewport width (<code>vw<\/code>)<\/strong> or a relative unit like a percentage to establish an upper limit so they don\u2019t grow too much. This element will try to cover its parent full width but won\u2019t grow past <code>300px<\/code>:<\/p>\n<pre><code class=\"language-css\">.min {\n height: 400px;\n width: min(100%, 300px);\n}\n<\/code><\/pre>\n<p>We can make the height resize along the width using the <code>aspect-ratio<\/code> property:<\/p>\n<pre><code class=\"language-css\">.min-and-aspect-ratio {\n aspect-ratio: 1\/1; \/* or 1 *\/\n width: min(100%, 300px);\n}\n<\/code><\/pre>\n<p>Using the <strong><code>max()<\/code> function<\/strong>, we can apply a lower limit. The following CSS allows the element to increase its size to cover up to half of its parent element but won\u2019t ever shrink below <code>300px<\/code>;<\/p>\n<pre><code class=\"language-css\">.max {\n height: 400px;\n width: max(50%, 300px);\n}\n<\/code><\/pre>\n<p>It\u2019s a bit of a mind-bender, right? We use <code>min()<\/code> to establish a maximum width and <code>max()<\/code> to establish a minimum.<\/p>\n<p>Then there is the very popular <strong><code>clamp()<\/code> function<\/strong> that establishes both maximum and minimum limits \u2014 but with the added bonus of setting an \u201cideal\u201d size as the middle argument. We\u2019re \u201cclamping\u201d values with a range it adheres to while attempting to hit that ideal target.<\/p>\n<p>The element in the following demo tries to cover the full available width of its parent element but will not go above <code>300px<\/code> or below <code>200px<\/code>.<\/p>\n<figure class=\"break-out\">\n<p data-height=\"480\" data-theme-id=\"light\" data-slug-hash=\"wvbKaBj\" data-user=\"smashingmag\" data-default-tab=\"result\" class=\"codepen\">See the Pen [math functions [forked]](https:\/\/codepen.io\/smashingmag\/pen\/wvbKaBj) by <a href=\"https:\/\/codepen.io\/monknow\">Monknow<\/a>.<\/p><figcaption>See the Pen <a href=\"https:\/\/codepen.io\/smashingmag\/pen\/wvbKaBj\">math functions [forked]<\/a> by <a href=\"https:\/\/codepen.io\/monknow\">Monknow<\/a>.<\/figcaption><\/figure>\n<h3 id=\"it-is-a-combination\">It Is A Combination<\/h3>\n<p>Making a website that looks great no matter the device relies on more than responsive units or math functions alone. We need the combination of all techniques to create a seamless responsive experience. You can sort of think of it like the <a href=\"https:\/\/www.smashingmagazine.com\/2024\/02\/reporting-core-web-vitals-performance-api\/\">Performance API in JavaScript<\/a> that is a group of standards that work together for performance-related work.<\/p>\n<p><strong>What we have is a group of CSS specifications built around responsive design. They aren\u2019t necessarily<\/strong> <strong><em>replacing<\/em><\/strong> <strong>CSS media queries but are additive and designed to work together for the best possible coverage.<\/strong><\/p>\n<p>For example, we may want a <code>font-size<\/code> value to increase or decrease depending on the width of the viewport. Easy enough with media queries, but now we have additional ways to approach this that could be more efficient or maintainable depending on your project.<\/p>\n<p>We certainly could use <strong>media queries<\/strong> to update the <code>font-size<\/code> value at specific browser widths. We\u2019d likely need to write more than one to get the right size at each breakpoint, but it is possible and valid.<\/p>\n<figure class=\"break-out\">\n<p data-height=\"480\" data-theme-id=\"light\" data-slug-hash=\"oNRjXXz\" data-user=\"smashingmag\" data-default-tab=\"result\" class=\"codepen\">See the Pen [Resizing text using media queries [forked]](https:\/\/codepen.io\/smashingmag\/pen\/oNRjXXz) by <a href=\"https:\/\/codepen.io\/monknow\">Monknow<\/a>.<\/p><figcaption>See the Pen <a href=\"https:\/\/codepen.io\/smashingmag\/pen\/oNRjXXz\">Resizing text using media queries [forked]<\/a> by <a href=\"https:\/\/codepen.io\/monknow\">Monknow<\/a>.<\/figcaption><\/figure>\n<p>Instead of updating the <code>font-size<\/code> with fixed pixels at multiple breakpoints, we can reach for responsive length units instead. For example, the <code>vw<\/code> unit is relative to the viewport width, where each unit represents 1% of the current browser width.<\/p>\n<p>But we can go further than that because viewport units alone will not save us from font sizes that are far too small and large for their contexts. Let\u2019s combine them with the <code>clamp()<\/code> function to establish minimum and maximum limits with our ideal size defined.<\/p>\n<figure class=\"break-out\">\n<p data-height=\"480\" data-theme-id=\"light\" data-slug-hash=\"yLWYNNw\" data-user=\"smashingmag\" data-default-tab=\"result\" class=\"codepen\">See the Pen [Resizing text individually using clamp() and vw [forked]](https:\/\/codepen.io\/smashingmag\/pen\/yLWYNNw) by <a href=\"https:\/\/codepen.io\/monknow\">Monknow<\/a>.<\/p><figcaption>See the Pen <a href=\"https:\/\/codepen.io\/smashingmag\/pen\/yLWYNNw\">Resizing text individually using clamp() and vw [forked]<\/a> by <a href=\"https:\/\/codepen.io\/monknow\">Monknow<\/a>.<\/figcaption><\/figure>\n<p>But wait! We can improve this even more by declaring this directly on the <code><\/code> element\u2019s <code>font-size<\/code>, making all other fonts resize by the same factor. Then, using the <code>rem<\/code> unit, we can write how big or small each element <code>font-size<\/code> should be or opt out and use <code>clamp(),<\/code> or even fixed pixel units in specific elements.<\/p>\n<blockquote><p>It\u2019s worth noting that the difference between <code>rem<\/code> and <code>em<\/code> units is that the former is relative to the \u201croot\u201d element, i.e., <code><\/code>, while the latter is relative to the selector\u2019s parent element.<\/p><\/blockquote>\n<figure class=\"break-out\">\n<p data-height=\"480\" data-theme-id=\"light\" data-slug-hash=\"YzbyXyZ\" data-user=\"smashingmag\" data-default-tab=\"result\" class=\"codepen\">See the Pen [Resizing text by the same factor [forked]](https:\/\/codepen.io\/smashingmag\/pen\/YzbyXyZ) by <a href=\"https:\/\/codepen.io\/monknow\">Monknow<\/a>.<\/p><figcaption>See the Pen <a href=\"https:\/\/codepen.io\/smashingmag\/pen\/YzbyXyZ\">Resizing text by the same factor [forked]<\/a> by <a href=\"https:\/\/codepen.io\/monknow\">Monknow<\/a>.<\/figcaption><\/figure>\n<p>So, yes, none of this is meant to be used in isolation or as a one-to-one replacement for media queries. <strong>Building responsive interfaces takes a village<\/strong>, so to speak, and we have a knapsack of hammers, wrenches, nails, and screws we can use to put it all together.<\/p>\n<div class=\"partners__lead-place\"><\/div>\n<h2 id=\"hello-container-queries\">Hello, Container Queries<\/h2>\n<p>Media queries are adept at modifying layouts on a page-wide basis. Take, for example, a shopping cart. When the viewport width is wide enough to accommodate it, we can display the included products in a wide <code><\/p>\n<table><\/table>\n<p><\/code> where they can breathe comfortably.<\/p>\n<figure class=\"\n \n break-out article__image\n \n \n \"><\/p>\n<p> <a href=\"https:\/\/files.smashing.media\/articles\/beyond-css-media-queries\/cart-desktop.png\"><\/p>\n<p> <img decoding=\"async\" loading=\"lazy\" width=\"800\" height=\"366\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"Cart UI on desktop\" class=\"lazyload\" data-src=\"https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_80\/w_400\/https:\/\/files.smashing.media\/articles\/beyond-css-media-queries\/cart-desktop.png\"><\/p>\n<p> <\/a><figcaption class=\"op-vertical-bottom\">\n Cart UI on desktop. (<a href=\"https:\/\/files.smashing.media\/articles\/beyond-css-media-queries\/cart-desktop.png\">Large preview<\/a>)<br \/>\n <\/figcaption><\/figure>\n<p>That same layout in mobile simply does not work. Tables have their own set of responsive challenges as it is, and while there is <a href=\"https:\/\/css-tricks.com\/responsive-data-table-roundup\/\">no shortage of solutions<\/a>, we may be able to consider another layout using modern techniques that are way less engineered.<\/p>\n<figure class=\"\n \n break-out article__image\n \n \n \"><\/p>\n<p> <a href=\"https:\/\/files.smashing.media\/articles\/beyond-css-media-queries\/cart-mobile.png\"><\/p>\n<p> <img decoding=\"async\" loading=\"lazy\" width=\"800\" height=\"549\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"Cart UI on mobile\" class=\"lazyload\" data-src=\"https:\/\/res.cloudinary.com\/indysigner\/image\/fetch\/f_auto,q_80\/w_400\/https:\/\/files.smashing.media\/articles\/beyond-css-media-queries\/cart-mobile.png\"><\/p>\n<p> <\/a><figcaption class=\"op-vertical-bottom\">\n Cart UI on mobile. (<a href=\"https:\/\/files.smashing.media\/articles\/beyond-css-media-queries\/cart-mobile.png\">Large preview<\/a>)<br \/>\n <\/figcaption><\/figure>\n<p>We are doing much more than simply changing the width or height of elements! Border colors, element visibility, and flex directions need to be changed, and it can only be done through a media query, right? Well, even in cases where we have to completely switch a layout depending on the viewport size, we can better achieve it with <em>container queries<\/em>.<\/p>\n<blockquote class=\"pull-quote\">\n<p>\n <a class=\"pull-quote__link\" aria-label=\"Share on Twitter\" href=\"https:\/\/twitter.com\/share?text=%0aAgain,%20Problem%20#1%20of%20media%20queries%20is%20that%20they%20only%20consider%20the%20viewport%20size%20when%20making%20decisions%20and%20are%20completely%20ignorant%20of%20an%20element%e2%80%99s%20surrounding%20context.%0a&url=https:\/\/smashingmagazine.com%2f2024%2f05%2fbeyond-css-media-queries%2f\"><\/p>\n<p>Again, Problem #1 of media queries is that they only consider the viewport size when making decisions and are completely ignorant of an element\u2019s surrounding context.<\/p>\n<p> <\/a>\n <\/p>\n<div class=\"pull-quote__quotation\">\n<div class=\"pull-quote__bg\">\n <span class=\"pull-quote__symbol\">\u201c<\/span><\/div>\n<\/p><\/div>\n<\/blockquote>\n<p>That may not be a big concern if all we\u2019re talking about is a series of elements that are allowed to take up the full page width because the full page width is very much related to the viewport size, making media queries a perfectly fine choice for making adjustments.<\/p>\n<figure class=\"break-out\">\n<p data-height=\"480\" data-theme-id=\"light\" data-slug-hash=\"ExzVjPj\" data-user=\"smashingmag\" data-default-tab=\"result\" class=\"codepen\">See the Pen [Responsive Cards Using Media Queries [forked]](https:\/\/codepen.io\/smashingmag\/pen\/ExzVjPj) by <a href=\"https:\/\/codepen.io\/monknow\">Monknow<\/a>.<\/p><figcaption>See the Pen <a href=\"https:\/\/codepen.io\/smashingmag\/pen\/ExzVjPj\">Responsive Cards Using Media Queries [forked]<\/a> by <a href=\"https:\/\/codepen.io\/monknow\">Monknow<\/a>.<\/figcaption><\/figure>\n<p>But say we want to display those same elements as part of a multi-column layout where they are included in a narrow column as an <code><\/p>\n<aside><\/aside>\n<p><\/code> next to a larger column containing a <code><main><\/main><\/code> element. Now we\u2019re in trouble.<\/p>\n<p>A more traditional solution is to write a series of media queries depending on where the element is used and where its content breaks. But media queries completely miss the relationship between the <code><main><\/main><\/code> and <code><\/p>\n<aside><\/aside>\n<p><\/code> elements, which is a big deal since the size of one influences the size of the other according to normal document flow.<\/p>\n<figure class=\"break-out\">\n<p data-height=\"480\" data-theme-id=\"light\" data-slug-hash=\"gOJapPo\" data-user=\"smashingmag\" data-default-tab=\"result\" class=\"codepen\">See the Pen [Responsive Cards Using Media Queries Inside Container [forked]](https:\/\/codepen.io\/smashingmag\/pen\/gOJapPo) by <a href=\"https:\/\/codepen.io\/monknow\">Monknow<\/a>.<\/p><figcaption>See the Pen <a href=\"https:\/\/codepen.io\/smashingmag\/pen\/gOJapPo\">Responsive Cards Using Media Queries Inside Container [forked]<\/a> by <a href=\"https:\/\/codepen.io\/monknow\">Monknow<\/a>.<\/figcaption><\/figure>\n<p>The <code>.cards<\/code> element is in the context of the <code><\/p>\n<aside><\/aside>\n<p><\/code> element and is squished as a result of being in a narrow column. What would be great is to change the layout of each <code>.card<\/code> component when the <code>.cards<\/code> element that contains them reaches a certain size rather than when the viewport is a certain size.<\/p>\n<p>That\u2019s where <strong>container queries<\/strong> come into play, allowing us to conditionally apply styles based on an element\u2019s size. We register an element as a \u201ccontainer,\u201d which, in our current example, is the unordered list containing the series of <code>.card<\/code> components. We\u2019re essentially giving the parent selector a great deal of power to influence the current layout.<\/p>\n<pre><code class=\"language-css\">.cards {\n container-name: cards;\n}\n<\/code><\/pre>\n<p>Container queries monitor an element by its size, and we need to tell the browser exactly how to interpret that size by giving <code>.cards<\/code> a <code>container-type<\/code>, which can be the container\u2019s <code>size<\/code> (i.e., in the block and inline directions) or its <code>inline-size<\/code> (i.e., the total length in the inline direction). There\u2019s a <code>normal<\/code> value that removes sizing considerations but allows the element to be queried by its styles.<\/p>\n<pre><code class=\"language-css\">.cards {\n container-name: cards;\n container-type: inline-size;\n}\n<\/code><\/pre>\n<p>We can simplify things down a bit using the <code>container<\/code> shorthand property.<\/p>\n<pre><code class=\"language-css\">.cards {\n container: cards \/ inline-size;\n}\n<\/code><\/pre>\n<p>Now, we can adjust the layout of the <code>.card<\/code> components when the <code>.cards<\/code> container is a certain inline size. Container queries use the same syntax as media queries but use the <code>@container<\/code> at-rule instead of <code>@media<\/code>.<\/p>\n<pre><code class=\"language-css\">.cards {\n container: cards \/ inline-size;\n}\n\n@container cards (width < 700px) {\n .cards li {\n flex-flow: column;\n }\n}\n<\/code><\/pre>\n<p>Now, each <code>.card<\/code> is a flexible container that flows in the <code>column<\/code> direction when the width of the <code>.cards<\/code> container is less than <code>700px<\/code>. Any wider than that, we have the same to lay them out in a <code>row<\/code> direction instead.<\/p>\n<figure class=\"break-out\">\n<p data-height=\"480\" data-theme-id=\"light\" data-slug-hash=\"VwOvLap\" data-user=\"smashingmag\" data-default-tab=\"result\" class=\"codepen\">See the Pen [Responsive Cards Using Container Queries [forked]](https:\/\/codepen.io\/smashingmag\/pen\/VwOvLap) by <a href=\"https:\/\/codepen.io\/monknow\">Monknow<\/a>.<\/p><figcaption>See the Pen <a href=\"https:\/\/codepen.io\/smashingmag\/pen\/VwOvLap\">Responsive Cards Using Container Queries [forked]<\/a> by <a href=\"https:\/\/codepen.io\/monknow\">Monknow<\/a>.<\/figcaption><\/figure>\n<p><strong>Style queries<\/strong> are a cousin to container queries in the sense that we can query the container\u2019s styles and conditionally apply style changes to its children, say changing a child element\u2019s <code>color<\/code> to white when the container\u2019s <code>background-color<\/code> is set to a dark color. We\u2019re still in the early days, and support for style queries and <a href=\"https:\/\/caniuse.com\/css-container-queries-style\">browser support is still evolving<\/a>.<\/p>\n<p>I hope this gives you a sense of how amazing it is that we have this <strong>context-aware way of establishing responsive layouts<\/strong>. Containers are a completely new idea in CSS (although we\u2019ve used the term synonymously with \u201cparent element\u201d for ages) that is novel and elegant.<\/p>\n<h2 id=\"so-are-media-queries-useless\">So, Are Media Queries Useless?<\/h2>\n<p><em>NO!<\/em> While media queries have been the go-to solution for responsive design, their limitations are glaringly obvious now that we have more robust tools in CSS that are designed to solve those limits.<\/p>\n<p>That doesn\u2019t make media queries obsolete \u2014 merely a different tool that\u2019s part of a larger toolset for building responsive interfaces. Besides, media queries still address vital accessibility concerns thanks to their ability to recognize a user\u2019s visual and motion preferences \u2014 among other settings \u2014 at the operating system level.<\/p>\n<p>So, yes, <em>keep using media queries!<\/em> But maybe reach for them sparingly since CSS has a lot more to offer us.<\/p>\n<div class=\"signature\">\n <img decoding=\"async\" src=\"data:image\/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==\" alt=\"Smashing Editorial\" width=\"35\" height=\"46\" loading=\"lazy\" class=\"lazyload\" data-src=\"https:\/\/www.smashingmagazine.com\/images\/logo\/logo--red.png\"><br \/>\n <span>(gg, yk)<\/span>\n<\/div>\n<\/article>\n","protected":false},"excerpt":{"rendered":"<p>Beyond CSS Media Queries Beyond CSS Media Queries Juan Diego Rodr\u00edguez 2024-05-16T15:00:00+00:00 2025-03-19T12:04:52+00:00 Media queries have been around almost as long as CSS itself \u2014 and with no flex, no grid, no responsive units, and no math functions, media queries were the most pragmatic choice available to make a somewhat responsive website. In the early 2010s, with the proliferation of mobile devices and the timely publication of Ethan Marcotte\u2019s classic…<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[11],"tags":[],"_links":{"self":[{"href":"https:\/\/kerrprogroup.com\/index.php\/wp-json\/wp\/v2\/posts\/382"}],"collection":[{"href":"https:\/\/kerrprogroup.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kerrprogroup.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kerrprogroup.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kerrprogroup.com\/index.php\/wp-json\/wp\/v2\/comments?post=382"}],"version-history":[{"count":1,"href":"https:\/\/kerrprogroup.com\/index.php\/wp-json\/wp\/v2\/posts\/382\/revisions"}],"predecessor-version":[{"id":383,"href":"https:\/\/kerrprogroup.com\/index.php\/wp-json\/wp\/v2\/posts\/382\/revisions\/383"}],"wp:attachment":[{"href":"https:\/\/kerrprogroup.com\/index.php\/wp-json\/wp\/v2\/media?parent=382"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kerrprogroup.com\/index.php\/wp-json\/wp\/v2\/categories?post=382"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kerrprogroup.com\/index.php\/wp-json\/wp\/v2\/tags?post=382"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}