{"id":3108,"date":"2024-08-02T11:49:11","date_gmt":"2024-08-02T16:49:11","guid":{"rendered":"https:\/\/frontendmasters.com\/blog\/?p=3108"},"modified":"2024-08-02T11:49:12","modified_gmt":"2024-08-02T16:49:12","slug":"what-if-you-used-container-units-for-everything","status":"publish","type":"post","link":"https:\/\/frontendmasters.com\/blog\/what-if-you-used-container-units-for-everything\/","title":{"rendered":"What if you used Container Units for&#8230; everything?"},"content":{"rendered":"\n<p>I said to myself I said <em>what if I used <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/CSS_containment\/Container_queries#container_query_length_units\">container units<\/a> for every single unit in a design? <\/em>I was wondering, partially because I thought the answer might be <em>well, everything will probably scale really nicely then. <\/em>Container units, in case you haven&#8217;t heard of them, are unit (like <code>px<\/code> or <code>rem<\/code>, but more closely related to viewport units like <code>vw<\/code> or <code>vi<\/code>) that are sized relatively <em>to the container that they are in<\/em>.<\/p>\n\n\n\n<p>Turns out, surprise surprise, that it&#8217;s not that easy. There are plenty of things that container queries are awkward at or just not the right unit for.<\/p>\n\n\n\n<p>I had a play with a <em>pretty simple<\/em> grid of cards of various sizes. Don&#8217;t consider this demo in good shape, it&#8217;s just what I used to have a plan.<\/p>\n\n\n\n<div class=\"wp-block-cp-codepen-gutenberg-embed-block cp_embed_wrapper\"><iframe id=\"cp_embed_OJYKLXz\" src=\"\/\/codepen.io\/anon\/embed\/OJYKLXz?height=450&amp;theme-id=47434&amp;slug-hash=OJYKLXz&amp;default-tab=result\" height=\"450\" scrolling=\"no\" frameborder=\"0\" allowfullscreen allowpaymentrequest name=\"CodePen Embed OJYKLXz\" title=\"CodePen Embed OJYKLXz\" class=\"cp_embed_iframe\" style=\"width:100%;overflow:hidden\">CodePen Embed Fallback<\/iframe><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Potential Problem: You Can&#8217;t Style The Element You Query<\/h2>\n\n\n\n<p>This is a fairly known thing with container queries, but the weirdness with it compounds a bit with container units, as the desire to <em>use<\/em> those units right away on a container is strong. To be clear, the container units will &#8220;work&#8221;, they&#8217;ll just be based on the next-higher-up container, which if there isn&#8217;t a declared one will be the document.<\/p>\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\">.card-wrap<\/span> {\n  <span class=\"hljs-attribute\">container<\/span>: cardWrap \/ inline-size;\n\n  <span class=\"hljs-attribute\">padding<\/span>: <span class=\"hljs-number\">2<\/span>cqi;\n  <span class=\"hljs-attribute\">border-radius<\/span>: <span class=\"hljs-number\">4<\/span>cqi;\n\n  .card {\n    <span class=\"hljs-attribute\">border-radius<\/span>: <span class=\"hljs-number\">4<\/span>cqi;\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>Above, the <code>border-radius<\/code> will be different despite looking like it will be the same, because the container the units reference are different. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"342\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/08\/CleanShot-2024-08-02-at-08.42.03%402x.png?resize=1024%2C342&#038;ssl=1\" alt=\"\" class=\"wp-image-3331\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/08\/CleanShot-2024-08-02-at-08.42.03%402x.png?resize=1024%2C342&amp;ssl=1 1024w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/08\/CleanShot-2024-08-02-at-08.42.03%402x.png?resize=300%2C100&amp;ssl=1 300w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/08\/CleanShot-2024-08-02-at-08.42.03%402x.png?resize=768%2C257&amp;ssl=1 768w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/08\/CleanShot-2024-08-02-at-08.42.03%402x.png?w=1388&amp;ssl=1 1388w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><figcaption class=\"wp-element-caption\">See how the outer border radius&#8217; match, but the inner card are different and look off on the larger card.<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Potential Solution: Style Nothing on the Container<\/h3>\n\n\n\n<p>Be vigilant! It will save headaches if you are hardfast when you set a <code>container<\/code> you do no other size-based styling. If that means adding an extra otherwise meaningless <code>&lt;div&gt;<\/code> wrapper, well, that&#8217;s not ultra ideal as DOM weight does matter, but it&#8217;s probably fine.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Potential Problem: Too Small &amp; Too Big<\/h2>\n\n\n\n<p>If you <em>only<\/em> use container units for something like <code>font-size<\/code>, it&#8217;s pretty easy to get into a situation where text, and text-based elements, end up either <em>too big<\/em> or <em>too small.<\/em> <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"455\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/08\/Screenshot-2024-08-02-at-8.49.16%E2%80%AFAM.png?resize=1024%2C455&#038;ssl=1\" alt=\"\" class=\"wp-image-3332\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/08\/Screenshot-2024-08-02-at-8.49.16%E2%80%AFAM.png?resize=1024%2C455&amp;ssl=1 1024w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/08\/Screenshot-2024-08-02-at-8.49.16%E2%80%AFAM.png?resize=300%2C133&amp;ssl=1 300w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/08\/Screenshot-2024-08-02-at-8.49.16%E2%80%AFAM.png?resize=768%2C341&amp;ssl=1 768w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/08\/Screenshot-2024-08-02-at-8.49.16%E2%80%AFAM.png?resize=1536%2C682&amp;ssl=1 1536w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/08\/Screenshot-2024-08-02-at-8.49.16%E2%80%AFAM.png?w=1810&amp;ssl=1 1810w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><figcaption class=\"wp-element-caption\">Here the text on the larger card feels a bit too big but the tags are OK. The text on the smaller card feels OK, but those tags are too small. <\/figcaption><\/figure>\n\n\n\n<p>Either is annoying, but too small is also an accessibility failure. <\/p>\n\n\n\n<p>Using container units (or viewport units) alone is a bad practice for text sizing. It&#8217;s fixable though.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Potential Solution: Clamp<\/h3>\n\n\n\n<p>Making sure text doesn&#8217;t get too small or too big is solved with a CSS <code>clamp()<\/code> function. And while we&#8217;re at it, we can sprinkle in a relative unit to make sure that users font sizing preferences are honored. <\/p>\n\n\n\n<p>You can still use container units, but set those limits and use a bit of relative mixed in.<\/p>\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\">.tag<\/span> {\n  <span class=\"hljs-comment\">\/* Don't *\/<\/span>\n  <span class=\"hljs-attribute\">font-size<\/span>: <span class=\"hljs-number\">4<\/span>cqi;\n\n  <span class=\"hljs-comment\">\/* Do *\/<\/span>\n  <span class=\"hljs-attribute\">font-size<\/span>: <span class=\"hljs-built_in\">clamp<\/span>(<span class=\"hljs-number\">16px<\/span>, <span class=\"hljs-number\">4<\/span>cqi + <span class=\"hljs-number\">0.5rem<\/span>, <span class=\"hljs-number\">24px<\/span>);\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<h2 class=\"wp-block-heading\">Potential Problem: Rows vs Columns<\/h2>\n\n\n\n<p>One strong use case for a container query is shifting layout at container based breakpoints. If that container goes from wide-and-short to narrow-and-tall, then the <em>width-based<\/em> (probably the most common) container units will be super different. <\/p>\n\n\n\n<p>Say the container here is the card itself, and you size some icons to work with that context when they are horizontal. But then if you shift the layout to a narrow column for the icons, as the card gets bigger, the sizing doesn&#8217;t work in that context now.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"654\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/08\/Screenshot-2024-08-02-at-9.25.58%E2%80%AFAM.png?resize=1024%2C654&#038;ssl=1\" alt=\"\" class=\"wp-image-3335\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/08\/Screenshot-2024-08-02-at-9.25.58%E2%80%AFAM.png?resize=1024%2C654&amp;ssl=1 1024w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/08\/Screenshot-2024-08-02-at-9.25.58%E2%80%AFAM.png?resize=300%2C192&amp;ssl=1 300w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/08\/Screenshot-2024-08-02-at-9.25.58%E2%80%AFAM.png?resize=768%2C491&amp;ssl=1 768w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/08\/Screenshot-2024-08-02-at-9.25.58%E2%80%AFAM.png?w=1362&amp;ssl=1 1362w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><figcaption class=\"wp-element-caption\">Bonus problem: you can&#8217;t use container units to set the <code>grid-template-columns<\/code> as they can never be based on an element that is reliably the same width as the grid.<\/figcaption><\/figure>\n\n\n\n<p>Instead, if we make the element around the icons the container, and thus it changes width when the layout changes, the change in our icon size can be too dramatic. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"628\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/08\/Screenshot-2024-08-02-at-9.27.26%E2%80%AFAM.png?resize=1024%2C628&#038;ssl=1\" alt=\"\" class=\"wp-image-3336\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/08\/Screenshot-2024-08-02-at-9.27.26%E2%80%AFAM.png?resize=1024%2C628&amp;ssl=1 1024w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/08\/Screenshot-2024-08-02-at-9.27.26%E2%80%AFAM.png?resize=300%2C184&amp;ssl=1 300w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/08\/Screenshot-2024-08-02-at-9.27.26%E2%80%AFAM.png?resize=768%2C471&amp;ssl=1 768w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/08\/Screenshot-2024-08-02-at-9.27.26%E2%80%AFAM.png?w=1240&amp;ssl=1 1240w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Potential Solution: Use a Different Unit<\/h3>\n\n\n\n<p>And here&#8217;s the rub. You just don&#8217;t have to use container units for everything. I doubt anyone ever intended for them to be used that way. It&#8217;s just a fun exercise, especially as strong scalability is a great effect. <\/p>\n\n\n\n<p>In this case <em>maybe<\/em> something like <code>cqmax<\/code> units would be workable, so the unit is based on the containers longest edge.<\/p>\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-class\">.actions<\/span> {\n  <span class=\"hljs-attribute\">container<\/span>: actions \/ inline-size;\n\n  svg {\n    <span class=\"hljs-attribute\">display<\/span>: block;\n    <span class=\"hljs-attribute\">width<\/span>: <span class=\"hljs-number\">4<\/span>cqmax;\n    <span class=\"hljs-attribute\">min-width<\/span>: <span class=\"hljs-number\">24px<\/span>;\n    <span class=\"hljs-attribute\">max-width<\/span>: <span class=\"hljs-number\">100%<\/span>;\n    <span class=\"hljs-attribute\">aspect-ratio<\/span>: <span class=\"hljs-number\">1<\/span>;\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>But&#8230; nah. It&#8217;s too weird. I&#8217;d say just use relative units or pixels or something here.<\/p>\n\n\n\n<p>In the end, if container units are helpful for a scaling effect based on the size of an element you want to achieve, go for it! <a href=\"https:\/\/caniuse.com\/css-container-queries\">The support is good.<\/a> But don&#8217;t force it. <\/p>\n\n\n\n<p>If you&#8217;re up for a challenge, have a play with it. Try something like converting every unit in <a href=\"https:\/\/codepen.io\/ecemgo\/pen\/YzBZjjb\">a more complex layout like this<\/a> into containers with container units. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>I said to myself I said what if I used container units for every single unit in a design? I was wondering, partially because I thought the answer might be well, everything will probably scale really nicely then. Container units, in case you haven&#8217;t heard of them, are unit (like px or rem, but more [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3340,"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":[48,7],"class_list":["post-3108","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog-post","tag-container-units","tag-css"],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/08\/smaller-containers.jpg?fit=1200%2C800&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/3108","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=3108"}],"version-history":[{"count":8,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/3108\/revisions"}],"predecessor-version":[{"id":3339,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/3108\/revisions\/3339"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media\/3340"}],"wp:attachment":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media?parent=3108"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/categories?post=3108"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/tags?post=3108"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}