{"id":4888,"date":"2025-01-14T16:42:28","date_gmt":"2025-01-14T21:42:28","guid":{"rendered":"https:\/\/frontendmasters.com\/blog\/?p=4888"},"modified":"2025-01-16T14:42:47","modified_gmt":"2025-01-16T19:42:47","slug":"css-wishlist-for-2025","status":"publish","type":"post","link":"https:\/\/frontendmasters.com\/blog\/css-wishlist-for-2025\/","title":{"rendered":"CSS Wishlist for 2025"},"content":{"rendered":"\n<p>The new year is bringing out plenty of folks blogging about their CSS wishlists. It&#8217;s fun! I love thinking about the future of CSS capability, particularly now when CSS seems to be moving so fast. I&#8217;m going to make my own list by listing some of my own wishes, then linking up other people&#8217;s ideas who I agree with (from any year). <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Stuff That Doesn&#8217;t Exist Yet<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><a href=\"https:\/\/nerdy.dev\/css-wishlist-2025#pick-where-to-stick\">Adam Argyle<\/a>: Pick Where to Stick<\/h3>\n\n\n\n<p>Layout with <code>position: sticky;<\/code> doesn&#8217;t let you be as specific as you might want to be with what parent element it&#8217;s going to stick<em> against.<\/em> Aside from other issues where it&#8217;s weirdly easy to <em>break<\/em> the stickiness, I agree it would be nice to just say where you want it to stick:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>For that all too common moment when you want to pick which element position sticky will respect. What if we could use&nbsp;<code>container-name<\/code>&nbsp;<a href=\"https:\/\/github.com\/w3c\/csswg-drafts\/issues\/9868\">or something<\/a>&nbsp;and reference it from position sticky by making it a function?<\/p>\n<\/blockquote>\n\n\n\n<p>Personally, I&#8217;d want the same thing for <code>position: fixed;<\/code>. I think it&#8217;s a bit annoying that you can only use it relative to the viewport and not a specific parent container.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><a href=\"https:\/\/css-tricks.com\/the-2013-css-wishlist\/#aa-3-id-like-multiple-pseudo-elements\">Me<\/a>: Unlimited Pseudo Elements with More Placement Options<\/h3>\n\n\n\n<p>Why do we only get <code>::before<\/code> and <code>::after<\/code>? I&#8217;m sure there are historical discussions you could dig up, but whatever happened, that&#8217;s how it was specced out. Feels a little arbitrary to me, like if someone decided functions in JavaScript could only have two arguments. What if it matched the great API that is <code>insertAdjacentHTML<\/code> and we had <code>::beforebegin<\/code>, <code>::afterbegin<\/code>, <code>::beforeend<\/code>, and <code>::afterend<\/code>? That would be nice. Even better, no particular limit to them, like <code>::afterbegin(n)<\/code> which would allow us to add as many of these as we like. After all, they help us keep non-content elements out of HTML, which is typically A Good Thing\u2122.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><a href=\"https:\/\/css-tricks.com\/a-css-wishlist-for-2025\/#aa-6-promoting-elements-to-the-top-layer-without-popover\">Ryan Trimble<\/a>: Promoting Elements to the Top Layout <em>without<\/em> Popover<\/h3>\n\n\n\n<p>A massive reason to use the <code>popover<\/code> attribute to create native popovers is that you don&#8217;t have to fiddle with <code>z-index<\/code> and stacking contexts and such. If it&#8217;s open, users will be able to see it, because it&#8217;s promoted to what&#8217;s called the &#8220;top layer&#8221;. This is an amazing feature! I can imagine how careful the specs need to be to prevent it from being just another thing that&#8217;s easy for authors to screw up, but I can also imagine opening up this superpower to more than the handful of things that happen to use it today.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Me: An <code>extend()<\/code> Function<\/h3>\n\n\n\n<p>The concept of &#8220;extend&#8221; (in my mind) <a href=\"https:\/\/sass-lang.com\/documentation\/at-rules\/extend\/\">comes from Sass<\/a>. It means: make this selector have the same styles as this other selector. Maybe it could remain an at-rule in CSS that looks like a function?<\/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-comment\">\/* somewhere in any loaded CSS *\/<\/span>\n<span class=\"hljs-selector-class\">.special-title-style<\/span> {\n  <span class=\"hljs-attribute\">paint-order<\/span>: stroke fill;\n  <span class=\"hljs-attribute\">-webkit-text-stroke<\/span>: <span class=\"hljs-number\">6px<\/span> <span class=\"hljs-number\">#b39ddb<\/span>;\n  <span class=\"hljs-attribute\">text-shadow<\/span>: -<span class=\"hljs-number\">1px<\/span> -<span class=\"hljs-number\">1px<\/span> <span class=\"hljs-number\">0<\/span> white;\n}\n\n<span class=\"hljs-comment\">\/* somewhere else in CSS *\/<\/span>\n<span class=\"hljs-selector-id\">#matching<\/span> <span class=\"hljs-selector-class\">.what<\/span> <span class=\"hljs-selector-class\">.the<\/span> <span class=\"hljs-selector-class\">.CMS<\/span> <span class=\"hljs-selector-attr\">&#91;gave-me]<\/span> {\n  @extend(.special-title-style); <span class=\"hljs-comment\">\/* <span class=\"hljs-doctag\">NOTE:<\/span> not real yet *\/<\/span>\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>This would be helpful when you have less control over the HTML. Like you <em>both<\/em> don&#8217;t want to wrestle control over what the CMS is outputting (because that&#8217;s technical debt) <em>and<\/em> you don&#8217;t want to bend your CSS system to the whims of the CMS either. <\/p>\n\n\n\n<p>Sass has <code>@extend()<\/code> and it&#8217;s sometimes called an anti-pattern, but that&#8217;s largely because it can produce ultra-verbose CSS that you might not even be aware of, which would not be a problem in native CSS. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><a href=\"https:\/\/rachelandrew.co.uk\/archives\/2024\/12\/20\/a-progress-update-on-reading-flow\/\">Rachel Andrew<\/a>: Regions &amp; Reading Flow<\/h3>\n\n\n\n<p>With grid and flexbox we were given the power to easily reflow and <a href=\"https:\/\/css-tricks.com\/almanac\/properties\/o\/order\/\">reorder<\/a> elements in ways that very much do not match whatever the current languages natural flow is (e.g. left to right and top to bottom). This can be an accessibility issue where the source order, and thus typically the tabbing order, doesn&#8217;t match the visual order, which can confuse people and\/or lead to awkward screen-jumping.<\/p>\n\n\n\n<p>There is a draft for <code>reading-flow<\/code> that <a href=\"https:\/\/rachelandrew.co.uk\/archives\/2024\/12\/20\/a-progress-update-on-reading-flow\/\">Rachel explains<\/a>:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>The property aims to solve the issue where the source (and therefore tab) order of a page gets disconnected from layout when using CSS grid layout or flexbox. This is a problem I\u2019ve been&nbsp;<a href=\"https:\/\/rachelandrew.co.uk\/archives\/2019\/06\/04\/grid-content-re-ordering-and-accessibility\/\">talking and writing about for a long time<\/a>. As soon as I realized this problem existed when using grid, I felt as if we were giving people potential with one hand but then removing it with the other. I\u2019m very happy that we\u2019re now fixing that problem.<\/p>\n<\/blockquote>\n\n\n\n<p>Yes please. <\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1020\" height=\"270\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/01\/Screenshot-2025-01-13-at-11.17.28%E2%80%AFAM.png?resize=1020%2C270&#038;ssl=1\" alt=\"\" class=\"wp-image-4959\" style=\"width:348px;height:auto\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/01\/Screenshot-2025-01-13-at-11.17.28%E2%80%AFAM.png?w=1020&amp;ssl=1 1020w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/01\/Screenshot-2025-01-13-at-11.17.28%E2%80%AFAM.png?resize=300%2C79&amp;ssl=1 300w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/01\/Screenshot-2025-01-13-at-11.17.28%E2%80%AFAM.png?resize=768%2C203&amp;ssl=1 768w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/figure>\n<\/div>\n\n\n<p>The rule <code>reading-flow: grid-rows<\/code> <a href=\"https:\/\/chrome.dev\/reading-flow-examples\/grid-placement-row.html\">in this demo<\/a> would make assistive tech read how it <em>looks<\/em> (4, 2, 3, 1) rather than what the source is (1, 2, 3, 4).<\/p>\n\n\n\n<p>At the risk of sounding lazy, I&#8217;d want to do <code>html { reading-flow: make-it-all-correct; }<\/code> \u2014 that is \u2014 just not worry about moving around the order of things, make a browser heuristic in charge of making the tab ordering logical. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Me: <code>image-set()<\/code> with Container Size Breakpoints<\/h3>\n\n\n\n<p>I just ran across this the other day so I figured I&#8217;d put it on my list. I had a container where I wanted to swap out the <code>background-image<\/code> at different container widths. Container queries can do this by writing a container queries that override the <code>background-image<\/code>, but it occurs to me that we could do it in a more concise <code><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/image\/image-set\">image-set()<\/a><\/code> declaration if that were to be allowed.<\/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\">.card<\/span> {\n  <span class=\"hljs-attribute\">container<\/span>: card \/ inline-size;\n\n  .card-banner {\n    <span class=\"hljs-attribute\">background-image<\/span>: <span class=\"hljs-built_in\">image-set<\/span>(\n      \/* Not real... yet *\/\n      <span class=\"hljs-string\">\"small.jpg\"<\/span> container(width &lt; <span class=\"hljs-number\">500px<\/span>)\n      <span class=\"hljs-string\">\"large.jpg\"<\/span> <span class=\"hljs-built_in\">container<\/span>(width &gt;= <span class=\"hljs-number\">500px<\/span>)\n    );\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<h3 class=\"wp-block-heading\"><a href=\"https:\/\/www.sarahgebauer.com\/post\/css-wishlist-2024\/\">Sarah Gebauer<\/a>: <code>:local-link<\/code><\/h3>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>The pseudo-class&nbsp;<strong>:local-link<\/strong>&nbsp;is a selector which targets links that point to the same web site. At the moment it&#8217;s not supported by any browser.<\/p>\n<\/blockquote>\n\n\n\n<p>That would be cool. I wonder if people had easier access to <em>style<\/em> same-website links differently easily, they would be less <a href=\"https:\/\/css-tricks.com\/use-target_blank\/\">quick to <code>target=\"_blank\"<\/code><\/a>, which I&#8217;m of the opinion you should only do in rare and specific circumstances.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><a href=\"https:\/\/kizu.dev\/shrinkwrap-problem\/\">Roman Komarov<\/a>: Shrinkwrapping<\/h3>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>There is&nbsp;one old, yet unsolved, CSS problem: shrinking containers to&nbsp;fit the content when it&nbsp;automatically wraps.<\/p>\n<\/blockquote>\n\n\n\n<p>When an element wraps, the width becomes as wide as the container. But that feels\/looks silly sometimes when the new now-wrapped content doesn&#8217;t occupy all that space. <\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"764\" height=\"800\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/01\/CleanShot-2025-01-14-at-10.49.41.gif?resize=764%2C800&#038;ssl=1\" alt=\"\" class=\"wp-image-4966\" style=\"width:392px;height:auto\"\/><\/figure>\n<\/div>\n\n\n<h3 class=\"wp-block-heading\"><a href=\"https:\/\/chriscoyier.net\/2022\/12\/21\/things-css-could-still-use-heading-into-2023\/\">Me<\/a>: Be able to style the handle on resizeable elements<\/h3>\n\n\n\n<p>See those little line nuggets in the bottom right? I think they are ugly and I want to style them. <\/p>\n\n\n\n\t\t<figure class=\"wp-block-jetpack-videopress jetpack-videopress-player aligncenter wp-block-jetpack-videopress--has-max-width\" style=\"max-width: 464.945px;\" >\n\t\t\t<div class=\"jetpack-videopress-player__wrapper\"> <iframe title=\"VideoPress Video Player\" aria-label='VideoPress Video Player' width='500' height='176' src='https:\/\/videopress.com\/embed\/oYMsnsmQ?cover=1&amp;autoPlay=0&amp;controls=1&amp;loop=0&amp;muted=0&amp;persistVolume=1&amp;playsinline=0&amp;preloadContent=metadata&amp;useAverageColor=1&amp;hd=0' frameborder='0' allowfullscreen data-resize-to-parent=\"true\" allow='clipboard-write'><\/iframe><script src='https:\/\/v0.wordpress.com\/js\/next\/videopress-iframe.js?m=1725245713'><\/script><\/div>\n\t\t\t\n\t\t\t\n\t\t<\/figure>\n\t\t\n\n\n<p>Not to mention I might want to move or resize them, potentially bettering the UX. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><a href=\"https:\/\/css-tricks.com\/a-css-wishlist-for-2025\/#aa-2-css-mixins\">Geoff Graham<\/a>: Mixins<\/h3>\n\n\n\n<p>A mixin is like a function, only the returned value is always style rules. <\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>The deal is that we can use utility classes almost as little CSS snippets to build out other style rules and maintain a clearer separation between markup and styles.<\/p>\n<\/blockquote>\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-keyword\">@mixin<\/span> --sr-text {\n  <span class=\"hljs-selector-tag\">position<\/span>: <span class=\"hljs-selector-tag\">absolute<\/span>;\n  <span class=\"hljs-selector-tag\">left<\/span>: <span class=\"hljs-selector-tag\">-10000px<\/span>;\n  <span class=\"hljs-selector-tag\">top<\/span>: <span class=\"hljs-selector-tag\">auto<\/span>;\n  <span class=\"hljs-selector-tag\">width<\/span>: 1<span class=\"hljs-selector-tag\">px<\/span>;\n  <span class=\"hljs-selector-tag\">height<\/span>: 1<span class=\"hljs-selector-tag\">px<\/span>;\n  <span class=\"hljs-selector-tag\">overflow<\/span>: <span class=\"hljs-selector-tag\">hidden<\/span>;\n}\n\n<span class=\"hljs-selector-tag\">header<\/span> <span class=\"hljs-selector-tag\">a<\/span><span class=\"hljs-selector-pseudo\">:first-child<\/span> {\n  @apply --sr-text;\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>I&#8217;ll note that <a href=\"https:\/\/frontendmasters.com\/blog\/css-does-need-mixins\/\">style queries are really close to mixins<\/a> in my mind, which actually have some support already.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Me: Trim Text from the Middle<\/h3>\n\n\n\n<p>Let&#8217;s say you want output:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\/styles\/setup\/colors.scss<\/pre>\n\n\n\n<p>But you only have ~15 characters to do it in. We have <code>text-overflow<\/code> (&#8216;n&#8217; friends) now to truncate it to something like:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\/styles\/setup...<\/pre>\n\n\n\n<p>But that could be awful as the entire file name is being truncated away. There is <a href=\"https:\/\/codepen.io\/jakob-e\/pen\/JoPpYqW\">a wild CSS trick<\/a> to truncate it from the other side, but I&#8217;d prefer something less hacky. And even better, we should be able to do that truncation<em> from the middle<\/em> instead of an edge. I think it would be nice to get something like:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">\/styl...lors.scss<\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Styling Grid Gaps and Cells<\/h3>\n\n\n\n<p>It&#8217;s to hard to style the gaps <em>between<\/em> grid columns and rows. Just want a 1px line between all the columns? There are ways, but nothing just easy and side-effect-free. For that matter, it could be argued it shouldn&#8217;t be necessary to put an HTML element into a grid cell in order to style it. That would be nice to do in CSS alone.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The &#8220;Want Better Support&#8221; List<\/h2>\n\n\n\n<div class=\"wp-block-group\"><div class=\"wp-block-group__inner-container is-layout-constrained wp-block-group-is-layout-constrained\">\n<h3 class=\"wp-block-heading\">A <code>random()<\/code> Function<\/h3>\n\n\n\n<p><a href=\"https:\/\/drafts.csswg.org\/css-values-5\/#randomness\">There is a working draft for this already done.<\/a> So I suppose this is more of a waiting game.<\/p>\n\n\n\n<p>There are plenty of design choices that benefit from a degree of randomness. Random dots on a grid, random movements, random timings&#8230;<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"457\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/01\/CleanShot-2025-01-14-at-10.55.57.gif?resize=800%2C457&#038;ssl=1\" alt=\"\" class=\"wp-image-4967\" style=\"width:471px;height:auto\"\/><figcaption class=\"wp-element-caption\">Which of these animations runs first? What if you didn&#8217;t have to decide, you could just randomize it each run? Would it benefit from randomized delays, durations, or easings?<\/figcaption><\/figure>\n<\/div>\n\n\n<p>If we try generate the random number, with, say, <a href=\"https:\/\/codepen.io\/chriscoyier\/pen\/nKZdBo\">a CSS processor<\/a>, that randomness is only calculated once and won&#8217;t feel particularly random across users and page loads.<\/p>\n\n\n\n<p>What&#8217;s less clear to me about this runtime version of randomness is how often it will be calculated. Like if you did <code>div { height: random(100px, 200px); }<\/code>, and that selector matched 50 <code>&lt;div&gt;<\/code>s, would each of them have a random height or would all 50 of them have the same height, even if that height is randomly calculated. Or if you used <code>random()<\/code> within a <code>@keyframe<\/code> animation that infinitely animates, would the value be re-calculated each iteration? I suspect it&#8217;s stuff like that which makes it something browsers don&#8217;t want to jump on implementing until they have very clear answers. <\/p>\n<\/div><\/div>\n\n\n\n<h3 class=\"wp-block-heading\"><a href=\"https:\/\/meyerweb.com\/eric\/thoughts\/2025\/01\/08\/css-wish-list-2025\/\">Eric Meyer<\/a>: <code>margin-trim<\/code><\/h3>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p>Trim off the leading block margin on the first child in an element, or the trailing block margin of the last child, so they don\u2019t stick out of the element and mess with margin collapsing.&nbsp; Same thing with block margins on the first and last line boxes in an element.&nbsp; And then, be able to do similar things with the inline margins of elements and line boxes!&nbsp; All these things could be ours.<\/p>\n<\/blockquote>\n\n\n\n<p>I really want this as it seems to come up for me <em>a lot<\/em>. That is, this kind of thing&#8230;<\/p>\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-selector-class\">.card<\/span> {\n  <span class=\"hljs-attribute\">padding<\/span>: <span class=\"hljs-number\">1rem<\/span>;\n  \n  :first-child {\n    <span class=\"hljs-attribute\">margin-block-start<\/span>: <span class=\"hljs-number\">0<\/span>;\n  }\n  <span class=\"hljs-selector-pseudo\">:last-child<\/span> {\n    <span class=\"hljs-attribute\">margin-block-end<\/span>: <span class=\"hljs-number\">0<\/span>;\n  }\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>Those extra selectors are easy to forgot and feel a bit fragile to me. I&#8217;d rather write:<\/p>\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-selector-class\">.card<\/span> {\n  <span class=\"hljs-attribute\">padding<\/span>: <span class=\"hljs-number\">1rem<\/span>;\n  <span class=\"hljs-attribute\">margin-trim<\/span>: block;\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>The <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/CSS\/margin-trim#browser_compatibility\"><code>margin-trim<\/code> property is already in Safari<\/a> so let&#8217;s go. My thinking on this boils down to <strong>if you set padding in a direction on an element, <code>margin-trim<\/code> in that same direction. <\/strong><\/p>\n\n\n\n<p>While we&#8217;re talking about trimming, Jason Bradberry&#8217;s <a href=\"https:\/\/piccalil.li\/\/blog\/why-im-excited-about-text-box-trim-as-a-designer\/\">Why I\u2019m excited about text-box-trim as a designer<\/a> deserves a shout-out on this list. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">The &#8220;ui&#8221; font families everywhere<\/h3>\n\n\n\n<p>The most popular and well-supported of these is <code>system-ui<\/code> and I see plenty of that on the web already.  It amounts to being able to use the San Francisco on modern Macs, Segoe on Windows, Roboto on Android, and the list goes on&#8230; generally matching what font the operating running the browser uses. I think that rules. But it doesn&#8217;t have to be the only one \u2014 and isn&#8217;t \u2014 <a href=\"https:\/\/drafts.csswg.org\/css-fonts-4\/#generic-family-name-syntax\">in the spec<\/a>. There are more like:<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">ui-serif<br>ui-sans-serif<br>ui-monospace<br>ui-rounded<\/pre>\n\n\n\n<p>Those don&#8217;t <em>have<\/em> to map to anything, but it&#8217;s sure nice if they do. They do in Safari on Mac and I kinda love it.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img data-recalc-dims=\"1\" loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"605\" src=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/12\/Screenshot-2024-12-27-at-11.08.28%E2%80%AFAM.png?resize=1024%2C605&#038;ssl=1\" alt=\"\" class=\"wp-image-4889\" srcset=\"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/12\/Screenshot-2024-12-27-at-11.08.28%E2%80%AFAM.png?resize=1024%2C605&amp;ssl=1 1024w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/12\/Screenshot-2024-12-27-at-11.08.28%E2%80%AFAM.png?resize=300%2C177&amp;ssl=1 300w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/12\/Screenshot-2024-12-27-at-11.08.28%E2%80%AFAM.png?resize=768%2C454&amp;ssl=1 768w, https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2024\/12\/Screenshot-2024-12-27-at-11.08.28%E2%80%AFAM.png?w=1524&amp;ssl=1 1524w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><figcaption class=\"wp-element-caption\">Safari (<a href=\"https:\/\/codepen.io\/chriscoyier\/pen\/GgKvOvL\">Demo<\/a>)<\/figcaption><\/figure>\n\n\n\n<p>This is a big wish as it&#8217;s not something that browser makers can just <em>do. <\/em> It requires, like, computer makers to agree and ship appropriate fonts that then map to these. I guess that&#8217;s why we call it a wishlist.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><a href=\"https:\/\/meyerweb.com\/eric\/thoughts\/2025\/01\/08\/css-wish-list-2025\/\">Eric Meyer<\/a>: Expanded <code>attr()<\/code> Support<\/h3>\n\n\n\n<p>Example from Eric:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-tag\">td<\/span> {\n  <span class=\"hljs-attribute\">width<\/span>: <span class=\"hljs-built_in\">attr<\/span>(data-size em, <span class=\"hljs-number\">1px<\/span>)\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><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<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">td<\/span> <span class=\"hljs-attr\">data-size<\/span>=<span class=\"hljs-string\">\"5\"<\/span>&gt;<\/span>\u2026<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">td<\/span>&gt;<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Yep. Love that. Part of what I like is that it moves <em>some<\/em> design information over to the HTML in a way that doesn&#8217;t need to be entirely prescribed right there. For example, setting <code>data-color=\"red\"<\/code> gives you a lot more CSS opportunity to fiddle with than <code>style=\"color: red;\"<\/code> does. Not to mention an easier way to back out of the support for it in the future which inline styles do not offer. <\/p>\n\n\n\n<p>To be clear, <code>attr()<\/code> &#8220;works&#8221; now, the values you get out are just strings, not &#8220;typed&#8221;, so you can&#8217;t use them to set things like colors and sizes like you might expect you can.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><a href=\"https:\/\/ishadeed.com\/article\/css-wishlist-2023\/#detect-when-sticky-is-active\">Ahmad Shadeed<\/a>: State Queries<\/h3>\n\n\n\n<p>Ahmad has made good points over the years about being able to style things when in certain states. Like applying styles when a flexbox container has elements that are wrapping (vs when it&#8217;s not). <\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-class\">.section-header<\/span> {\n  <span class=\"hljs-attribute\">container-type<\/span>: style flex-wrap;\n  <span class=\"hljs-attribute\">display<\/span>: flex;\n  <span class=\"hljs-attribute\">flex-wrap<\/span>: wrap;\n}\n\n<span class=\"hljs-keyword\">@container<\/span> style(wrap) {\n  <span class=\"hljs-comment\">\/* do the things you should do when the flex items are wrapped. *\/<\/span>\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><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><a href=\"https:\/\/ishadeed.com\/article\/css-state-queries\/\">Similarly<\/a>, and this is a big one I&#8217;ve heard a million times, styling a sticky element <em>only when it is stuck.<\/em> I put this one in the &#8220;better support&#8221; section as there is <a href=\"https:\/\/groups.google.com\/a\/chromium.org\/g\/blink-dev\/c\/C1D321h3OnA?pli=1\">actual movement on this<\/a>.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-class\">.page<\/span> {\n  <span class=\"hljs-attribute\">container-name<\/span>: sticky-header;\n  <span class=\"hljs-attribute\">container-type<\/span>: sticky;\n}\n\n<span class=\"hljs-selector-class\">.site-header<\/span> {\n  <span class=\"hljs-attribute\">position<\/span>: sticky;\n  <span class=\"hljs-attribute\">top<\/span>: <span class=\"hljs-number\">0<\/span>;\n}\n\n<span class=\"hljs-keyword\">@container<\/span> state(<span class=\"hljs-attribute\">stuck:<\/span> top) {\n  <span class=\"hljs-selector-class\">.site-header__bottom<\/span> {\n    <span class=\"hljs-attribute\">display<\/span>: none;\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><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<h3 class=\"wp-block-heading\">Custom Media Queries<\/h3>\n\n\n\n<p>There is <a href=\"https:\/\/drafts.csswg.org\/mediaqueries-5\/#custom-mq\">a draft with this in it<\/a>, but it&#8217;s never seem to come to be.<\/p>\n\n\n\n<p>This doesn&#8217;t work:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-selector-pseudo\">:root<\/span> { <span class=\"hljs-attribute\">--mobile<\/span>: <span class=\"hljs-number\">35em<\/span>; }\n\n<span class=\"hljs-keyword\">@media<\/span> (<span class=\"hljs-attribute\">min-width:<\/span> var(--mobile)) {\n  <span class=\"hljs-comment\">\/* non-mobile styles go here *\/<\/span>\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><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>The draft syntax was like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-keyword\">@custom-media<\/span> --narrow-window (<span class=\"hljs-attribute\">max-width:<\/span> <span class=\"hljs-number\">30em<\/span>);\n\n<span class=\"hljs-keyword\">@media<\/span> (--narrow-window) {\n  <span class=\"hljs-comment\">\/* narrow window styles *\/<\/span>\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><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 alas, nothing but <a href=\"https:\/\/www.stefanjudis.com\/notes\/the-death-of-custom-media-queries\/\">this hack<\/a>. <\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Style Queries that Support More Than Custom Properties<\/h3>\n\n\n\n<p>We actually have some support for style queries already, but all they can do is test custom properties. Example <a href=\"https:\/\/developer.chrome.com\/docs\/css-ui\/style-queries\">from Una<\/a>:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-keyword\">@container<\/span> style(<span class=\"hljs-attribute\">--theme:<\/span> warm) {\n  <span class=\"hljs-selector-class\">.card<\/span> {\n    <span class=\"hljs-attribute\">background-color<\/span>: wheat;\n    <span class=\"hljs-attribute\">border-color<\/span>: brown; \n    ...\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><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, if <code>--theme<\/code> matches the value <code>warm<\/code> (anywhere), then the nested styles will get applied to the relevant container. But we <em>don&#8217;t<\/em> have access to styling information generally to query against. Like this:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-keyword\">@container<\/span> style(<span class=\"hljs-attribute\">background:<\/span> black) {\n  <span class=\"hljs-selector-tag\">a<\/span> {\n    <span class=\"hljs-attribute\">color<\/span>: white;\n  }\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><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>Perhaps that&#8217;s not an amazing example, but being able to write styles that apply themselves based on arbitrary other styles on a container would be powerful. <\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>What&#8217;s on <em>your<\/em> CSS wishlist? <\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey we might as well spill out all these wishes as the CSS feature train has been rolling and we oughta get while the getting is good.<\/p>\n","protected":false},"author":1,"featured_media":4980,"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":[7],"class_list":["post-4888","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog-post","tag-css"],"acf":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/frontendmasters.com\/blog\/wp-content\/uploads\/2025\/01\/pexels-photo-54300.jpeg?fit=1880%2C1253&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/4888","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=4888"}],"version-history":[{"count":21,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/4888\/revisions"}],"predecessor-version":[{"id":4987,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/posts\/4888\/revisions\/4987"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media\/4980"}],"wp:attachment":[{"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/media?parent=4888"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/categories?post=4888"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/frontendmasters.com\/blog\/wp-json\/wp\/v2\/tags?post=4888"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}