{"id":7153,"date":"2025-09-12T11:05:34","date_gmt":"2025-09-12T16:05:34","guid":{"rendered":"https:\/\/frontendmasters.com\/blog\/?p=7153"},"modified":"2025-09-13T09:58:15","modified_gmt":"2025-09-13T14:58:15","slug":"breakpoint-columns-five-ways-which-do-you-like","status":"publish","type":"post","link":"https:\/\/frontendmasters.com\/blog\/breakpoint-columns-five-ways-which-do-you-like\/","title":{"rendered":"Breakpoint Columns, Five Ways. Which Do You Like?"},"content":{"rendered":"\n<p>You&#8217;ve got a three-column grid, but when the browser window is less than 500px wide, you break to a one-column grid. Let us review some of the ways.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1) Top-Level Media Query<\/h2>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-class\">.grid<\/span> {\n  <span class=\"hljs-attribute\">display<\/span>: grid;\n  <span class=\"hljs-attribute\">grid-template-columns<\/span>: <span class=\"hljs-number\">1<\/span>fr <span class=\"hljs-number\">1<\/span>fr <span class=\"hljs-number\">1<\/span>fr;\n}\n\n<span class=\"hljs-keyword\">@media<\/span> (width &lt; <span class=\"hljs-number\">500px<\/span>) {\n  <span class=\"hljs-selector-class\">.grid<\/span> {\n    <span class=\"hljs-attribute\">grid-template-columns<\/span>: <span class=\"hljs-number\">1<\/span>fr;\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Aside from the slightly-newish media query syntax there, this has deep browser support and is a classic way of achieving our goal. <\/p>\n\n\n\n<p>Advantages?<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The single top-level media query could contain other selectors so you can do more work under the logic of a single media query.<\/li>\n<\/ul>\n\n\n\n<p>Disadvantages?<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>You need to repeat the <code>.grid<\/code> selector (more code, error prone).<\/li>\n\n\n\n<li>You need to repeat the <code>grid-template-columns<\/code> property (more code, error prone).<\/li>\n\n\n\n<li>The property you are changing isn&#8217;t particularly close to the original.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">2) Nested Media Query<\/h2>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-class\">.grid<\/span> {\n  <span class=\"hljs-attribute\">display<\/span>: grid;\n  <span class=\"hljs-attribute\">grid-template-columns<\/span>: <span class=\"hljs-number\">1<\/span>fr <span class=\"hljs-number\">1<\/span>fr <span class=\"hljs-number\">1<\/span>fr;\n  @media (width &lt; 500px) {\n    <span class=\"hljs-attribute\">grid-template-columns<\/span>: <span class=\"hljs-number\">1<\/span>fr;\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Advantages?<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The nesting puts the property you are changing nearby the original, helping understanding at a glance what changes. <\/li>\n\n\n\n<li>You don&#8217;t have to repeat the <code>.grid<\/code> selector.<\/li>\n<\/ul>\n\n\n\n<p>Disadvantages?<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The 500px breakpoint might be a common one where you make other changes to the design. Nesting might have you sprinkling\/repeating them throughout the code rather than consolidating the changes together.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">3) Variablizing the Columns<\/h2>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">html<\/span> {\n  <span class=\"hljs-attribute\">--cols<\/span>: <span class=\"hljs-number\">1<\/span>fr <span class=\"hljs-number\">1<\/span>fr <span class=\"hljs-number\">1<\/span>fr;\n}\n\n<span class=\"hljs-selector-class\">.grid<\/span> {\n  <span class=\"hljs-attribute\">display<\/span>: grid;\n  <span class=\"hljs-attribute\">grid-template-columns<\/span>: <span class=\"hljs-built_in\">var<\/span>(--cols);\n  @media (width &lt; 500px) {\n    <span class=\"hljs-attribute\">--cols<\/span>: <span class=\"hljs-number\">1<\/span>fr;\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>We&#8217;re continuing the nesting here, but using a custom property to store and apply the <code>grid-template-columns<\/code> value. <\/p>\n\n\n\n<p>Advantages?<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>As a custom property set at a high level, this value could be re-used in other places.<\/li>\n\n\n\n<li>Don&#8217;t have to repeat the <code>grid-template-columns<\/code> property.<\/li>\n<\/ul>\n\n\n\n<p>Disadvantages?<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Naming things is hard.<\/li>\n\n\n\n<li>Sometimes custom property usage causes abstraction that is more confusing than helpful.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">4) Using a Custom Function<\/h2>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-keyword\">@function<\/span> --cols() {\n  <span class=\"hljs-selector-tag\">result<\/span>: 1<span class=\"hljs-selector-tag\">fr<\/span> 1<span class=\"hljs-selector-tag\">fr<\/span> 1<span class=\"hljs-selector-tag\">fr<\/span>;\n  <span class=\"hljs-keyword\">@media<\/span> (width &lt; <span class=\"hljs-number\">500px<\/span>) {\n    <span class=\"hljs-selector-tag\">result<\/span>: 1<span class=\"hljs-selector-tag\">fr<\/span>;\n  }\n}\n\n<span class=\"hljs-selector-class\">.grid<\/span> {\n  <span class=\"hljs-attribute\">display<\/span>: grid;\n  <span class=\"hljs-attribute\">grid-template-columns<\/span>: <span class=\"hljs-built_in\">--cols<\/span>();\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Newfangled CSS! Custom value functions return a single value, and thus can be used to abstract away logic. <\/p>\n\n\n\n<p>Advantages?<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Abstracted away logic can make the more declarative design block easier to read.<\/li>\n\n\n\n<li>Like a custom property, the function can be re-used.<\/li>\n<\/ul>\n\n\n\n<p>Disadvantages?<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Very low browser support so far.<\/li>\n\n\n\n<li>Abstraction doesn&#8217;t always mean more understandable code.<\/li>\n\n\n\n<li>Unfortunate you can&#8217;t pass an argument for the media query size.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">5) Custom Function + if()<\/h2>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-keyword\">@function<\/span> --cols() {\n  <span class=\"hljs-selector-tag\">result<\/span>: <span class=\"hljs-selector-tag\">if<\/span>(\n    <span class=\"hljs-selector-tag\">media<\/span>(<span class=\"hljs-selector-tag\">width<\/span> &lt; 500<span class=\"hljs-selector-tag\">px<\/span>): 1<span class=\"hljs-selector-tag\">fr<\/span>;\n    <span class=\"hljs-selector-tag\">else<\/span>: 1<span class=\"hljs-selector-tag\">fr<\/span> 1<span class=\"hljs-selector-tag\">fr<\/span> 1<span class=\"hljs-selector-tag\">fr<\/span>;\n  )\n}\n\n<span class=\"hljs-selector-class\">.grid<\/span> {\n  <span class=\"hljs-attribute\">display<\/span>: grid;\n  <span class=\"hljs-attribute\">grid-template-columns<\/span>: <span class=\"hljs-built_in\">--cols<\/span>();\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Even more newfangled CSS! (Also, you could imagine using <code>if()<\/code> alone for <code>grid-template-columns<\/code> without the custom function I&#8217;m sure.)<\/p>\n\n\n\n<p>Advantages?<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The custom function doesn&#8217;t need two <code>result<\/code> properties which could be a smidge confusing.<\/li>\n\n\n\n<li>The more conditions there are, they more terse and nice feeling the <code>if()<\/code> syntax looks.<\/li>\n<\/ul>\n\n\n\n<p>Disadvantages?<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Very low browser support, especially combining two brand new features.<\/li>\n\n\n\n<li>So friggin fancy it nearly breaks my old eyes.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>So?!<\/p>\n\n\n\n<p>What do you think? What is your favorite here? Or do you have an alternate entry? <\/p>\n","protected":false},"excerpt":{"rendered":"<p>There are usually multiple ways to do the same thing on the web. Sometimes&#8230; a lot of ways. Which is &#8220;better&#8221; can be a matter of taste or which abstraction buys the most value. Check out this CSS example and see which you prefer.<\/p>\n","protected":false},"author":1,"featured_media":7156,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"sig_custom_text":"","sig_image_type":"featured-image","sig_custom_image":0,"sig_is_disabled":false,"inline_featured_image":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[395,7,123,396,45],"class_list":["post-7153","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog-post","tag-function","tag-css","tag-grid","tag-if","tag-media-query"],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/09\/cols.png?fit=2000%2C1200&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/7153","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/comments?post=7153"}],"version-history":[{"count":5,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/7153\/revisions"}],"predecessor-version":[{"id":7169,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/7153\/revisions\/7169"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media\/7156"}],"wp:attachment":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media?parent=7153"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/categories?post=7153"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/tags?post=7153"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}