#233: CSS as a content API? No. But also sort of yes.

CSS as a content API

Okay, this is a neat idea but also probably highly foolish: using CSS as a content API. We’ll get to that. But first: in Custom Properties as State, Chris writes about Seasonal.css which “supplies a seasonal colour scheme based on the day of the year.”

You can import the CSS file…

<link rel="stylesheet" type="text/css" href="https://seasonal-css.incoherency.co.uk/seasonal.css">

And then use the variables within this CSS file to style your site. All of the variables in that file are then updated for every day of the year as they show on the example website:

Chris looks at all this and then writes:

This makes me think that a CDN-hosted CSS file like this could have other useful stuff, like today’s date for usage in pseudo content, or other special time-sensitive stuff. Maybe the phase of the moon? Sports scores?! Soup of the day?!

It’s almost like a data API that is tremendously easy to use. Pseudo content is even accessible content these days — but you can’t select the text of pseudo-elements, so don’t read this as an actual endorsement of using CSS as a content API.

Simon Willison took that idea and ran (caveating it all as a very weird idea) building an API for arbitrary database queries that return the results as… CSS custom properties. 🤯

Super interesting stuff here. I wrote not so long ago that CSS variables will soon be like the checkbox hack: they’re remarkable and extremely flexible. And I believe that this “CSS as content API” stuff proves me right. Just wait until we get Higher Level Custom Properties, things will get even weirder.

Maximally optimizing image loading for the web in 2021

Malte Ubl has written this fantastic piece that captures a whole bunch of knowledge about image loading best practices. There’s so much to learn here! Lazy rendering, the AVIF format, the picture element and the srcset attribute, caching, and blurry image placeholders.

Speaking of that last point on placeholders, Malte gives this example…

…where you can give an image a background before the image itself is loaded. This means users won’t have to wait until the full image has loaded, which is quite nice. Here’s how it’s done: with the background-image CSS property with a base64 SVG:

      background-size: cover;
        url('data:image/svg+xml;charset=utf-8,%3Csvg xmlns=\'http%3A//www.w3.org/2000/svg\'
        xmlns%3Axlink=\'http%3A//www.w3.org/1999/xlink\' viewBox=\'0 0 1280 853\'%3E%3Cfilter id=\'b\' color-interpolation-filters=\'sRGB\'%3E%3CfeGaussianBlur stdDeviation=\'.5\'%3E%3C/feGaussianBlur%3E%3CfeComponentTransfer%3E%3CfeFuncA type=\'discrete\' tableValues=\'1 1\'%3E%3C/feFuncA%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Cimage filter=\'url(%23b)\' x=\'0\' y=\'0\' height=\'100%25\' width=\'100%25\' 

aspect-ratio is coming soon

Breaking news: the aspect-ratio CSS property is coming soon! It’s now available in Safari Technical Preview 118 and Chrome and Firefox have it behind a flag.

But wait, why is it useful?

Well, Chris broke down the who, what, and why not so long ago but I’ll give you the elevator pitch: we’ve never been able to set the aspect ratio of an element in CSS before — only a few elements have it by default, like <img> and <video>. What if you wanted an element to be 100% of the browser window but you wanted the aspect ratio to be 16:9 (which is especially useful for video embeds)?

FitVids.js was the best solution to set the aspect ratio of an element for the longest time. But now we can do all of this without JavaScript and we can use it like this:

iframe[src*="vimeo.com"] {
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;

The nifty thing about this property to me is that if you set the width of an element with the aspect-ratio then the height will automatically be calculated and vice versa.

But wait! Not all videos are 16/9, right? You can set that ratio to whatever you like, but it might be smart to have a default, then take in a custom properties if set…

aspect-ratio: var(--aspect-ratio, 16 / 9);

So if you’ve set <iframe style="--aspect-ratio: 1/1;" ... > because it is a square video, then so it shall be, but it falls back to 16/9.

This makes me think about the typed attr() function. So many iframes (using that as a major use case of the property) have height and width attributes already on them (think YouTube embeds), so using them for the default aspect ratio (kinda like images do now) would be nice.

/* Not a supported thing yet, just an idea */
aspect-ratio: attr(width number) / attr(height number); /* if these are present, use them */

This is starting to feel like a soup of concepts though. It might be hard to pull all of them off together. As in…

  1. If the browser supports aspect-ratio
    1. Apply a default aspect-ratio
    2. Use the height and width attributes if you can for a better default
    3. Allow it all to be overridden with a custom property
  2. If the browser does not support aspect-ratio
    1. Use a padding hack
    2. Possibly automate the padding hack with FitVids.js
    3. Continue to use height and width attributes when you can because the future will need them

Will leave that alone for now.

Sticky CSS Grid Items

Melanie Richards investigates how to solve a particularly sticky (sorry) situation: sometimes, if trying to make a grid item stick to a point on the screen with position: sticky, it just…won’t. Sticky grid items can be a real pain like that.

The problem is with sizing algorithms in CSS. Melanie goes into why that is so I won’t spoil that but she points to the real solution: we need to add align-self or align-items to the grid wrapper below to make it sticky. In this example, Melanie adds align-items: baseline; to the article element to fix it.

Animated CSS Blob

Here’s a great post about creating an animated blob with nothing more than CSS. The smart thing with this design is that it uses three different blobs with an animation-delay and mix-blend-mode.

It’s just a nice and subtle technique that shows what border-radius is capable of doing. Wanna see another example of it in action? Check out this Pen.

Popper: a tooltip and popover positioning engine

Popper looks very neat and it seems like it’s been designed to capture all the edge cases that sometimes mess with a lot of other tooltip and popover techniques. I also just like the website, how it breaks down each problem and shows how this tiny little 3kb engine solves so much.

Whenever I see things like this — just like how FitVids.js was trying to solve the aspect ratio problem — I wonder how these custom solutions can be used to expand the scope of HTML and CSS. Tooltips and popovers are annoying and complex and to be honest I don’t want to have to import a third party dependency each time I want a really common pattern in a design system to work.

So: I feel like this is an interesting link to share because it ought be our goal to make things like Popper obsolete in the long run. Bootstrap and Material Design use Popper — and if that’s not a sign that our default tools in HTML are sort of half-baked and need a bunch of improvements, then I’m not sure what is.

Learn how to partner with design to ship products faster

As teams scale, maintaining alignment becomes more difficult. Checkout InVision’s new Leading Influential, Collaborative Engineering Teams guide and learn how to align teams as they scale, foster a growth mindset, and much more!


Connect your repository. Add your build settings. Deploy your website. Netlify is the fastest way to get a site live and supports any type of site with a Jamstack architecture. With static global CDN hosting, it is the fastest possible way to host.

Have you seen Amelia Wattenberger’s latest blog post? “Use the d3 force” is an amazing interactive experience (of a blog post) like so much of what Amelia does. Don’t miss the Yoda headlines.