Hover was the first Web Directions event devoted entirely to CSS. Along with the familiar faces of John and Rosemary, Hover was emceed by Hui Jin Chen. Hover was run online over two days, in three timezones.

Disclaimer & Credits

  • These notes were hammered out very quickly and paraphrase what speakers were saying. If you need an exact quote, use a definitive source such as a recording or slide deck.
  • Photo and other content credits as per the social media embeds.
  • Slide credits obviously to the speaker.

The talks

Day One (April 23)

What’s New In CSS 2021 – Adam Argyle

Adam is taking us through 31 features, rapid fire… from high risk, never-in-any-browser; to stable and available. A high-energy braindump to kick off the conference; full of callouts to the people who propsed these ideas, and to other speakers who will dive in deeper later. A great way to get Hover started!

Very Risky
  • Conditional Values – an unofficial draft by Lea Verou, adding inline if statements. unofficial draft - Lea Verou
  • Switch – proposal from Brian Kardell, adding switch statements to CSS along with available-inline-size which is a read-only value that works much like container queries proposalBrian Kardell
  • Relative units – (spec) adding units for line height, cap height, viewport width and height, rlh spec | demo
  • Houdini layout – one thing Houdini aims to do is replace heavy use of JavaScript for layout, moving the processing into the layout engine instead of blocking the main app thread. Examples of layout(masonry) and layout(packery) draft | browser support
  • Scope – a proposal by Miriam Suzanne to create non-global scope for CSS proposalMiriam Suzanne
Moderately risky
  • Container Queries – for real! You can try this now! You put a contain property on the outer element, then other rules can respond to dimensions of that nearest container instead of the whole viewport. unofficial draftMiriam Suzanne
  • Leading Trim – aims to solve the problem of element dimensions not matching typography dimensions. This effectively shrink wraps the element to the cap height, which is what people often really wanted. learn more | draftElika Etemad
  • Houdini paint – this lets you extend the engine to paint new backgrounds, the creative options are truly endless draft | learn more | browser support
  • Scroll timeline – aims to replace JS solutions for orchestrating relationships between elements based on scroll. Cool demo of a series of fractions, where the slash spins while scrolling between scroll snap points. There are polyfills if you can’t wait for this. draft | demo | browser support
  • Spelling and grammar – while the spellcheck and contenteditable attributes aren’t new, what is new is pseudo selectors ::spelling-error and ::grammar-error spec | browser support
  • :target-within spec
  • Nesting – a draft written by Tab Atkins quite a while ago, to add natively-supported nesting syntax popularised by LESS and SCSS. It works in some subtly different ways, by accessing the parent context and not just the parent selector draftTab Atkins
  • Cascade layers – allows multiple files/sources to build into a specific point in the cascade, even later in time. This is a huge change to the cascade 'rules’ but addresses a lot of concerns and criticisms specMiriam Suzanne
  • Foldables – for literally foldable devices, which have different quadrants in their display Explainer | polyfill
  • Color Level 5 – lets you work with colour in more advanced ways with color-mix (nifty threshold tricks), color-contrast (lets you specify a colour to contrast against – or provide some options for contrasting colours and CSS can 'pick’ one), color-adjust allows brightness changes, lch ('destructuring for colours’) draft
  • Masonry – extending the Grid spec to enable masonry layouts draft
  • Media Queries level 5 – some nice syntax updates like <=, @custom-media lets you use media queries as variables/custom props Spec | browser support
Low risk

Some of these may require polyfills, many don’t work in IE11. But for many people that’s no longer a big risk factor.

(Example of the colour spaces now open to CSS – brighter colours! Bright as the display can manage, not bright as the language would let you specify…)

  • Colour Level 4 – hex with alpha, functional notation (much cleaner syntax), ability to use relative colours via lch and lab colours. This actually gives access to more-vibrant colours that screens can manage but hex didn’t give you access to use. spec | browser support
  • HD Color – high dynamic range colour comes to the web spec | Demo
  • Typed Custom Properties – you can make custom properties but they take anything… @property lets you set a type for the property and whether it inherits. This is a huge boost for reliability and code quality! spec | browser support
  • Content Visibility – note this has some accessibility issues to work out – lets you 'hide’ off screen content with placeholder dimensions. Be really careful to test this if you do use it, but so long as you do there’s no reason not to use it!
  • Aspect Ratio – define one width or height plus an aspect-ratio and the browser just works it out for you. spec | browser support
  • ::marker lets you tweak the design of list item markers. Nice, stable and often requested by designers. spec | browser support
  • Conic Gradients – allows for some really nice new design effects (https://www.conic.style/ for inspiration) spec | browser support | inspiration
  • Containment – stops elements from creating cyclical errors that were blocking a lot of container query ideas. You can specify properties to 'contain’ to the element. spec | browser support
  • :focus-visible – fixes the problem of getting keyboard-oriented focus styles while using the mouse. This is so widely desired that browsers are shipping it on by default. spec | browser support
  • :focus-within – style a parent element while a child element has user focus. This is very useful, very powerful!
  • Logical Properties – a way to move away from assumptions like “left” and “right”, or the position of an “underline” which isn’t always under the text. The logical properties move to contextual, relative values like max-inline-size instead of max-width; padding-inline instead of padding-left and padding-right; and using block as a keyword. This will seriously help or change how we think about internationalisation and layout. spec | browser support
  • :is() and :where() – allows some neat syntax, although you have to get your head around the specificity differences, so you don’t add higher specificity just because you needed to target a lot of selectors. Very neat. spec | browser support
  • prefers-reduced-data media query – lets you reduce heavy resources like fonts and images when the user needs to save data. This is a really big deal for vast numbers of people coming to the web on in countries where expensive mobile plans are still the norm. draft | browser support
  • ::cue() draft | browser support

CSS is cruising!


Container Queries & The Future of CSS – Miriam Suzanne

(I had some connection issues so this is an incomplete writeup)

To understand where we’re going with CSS, we have to understand where it has come from. The web was always For Everyone, on any device.

Web for all. Web for everything. – W3C Mission

So we should send hints and boundaries to browsers and let them work it out. CSS is built to be tolerant to the many challenges users face; while giving authors some escape hatches to boost the importance of certain rules.

CSS also aims to make our styles re-usable; while still resolving conflicts when we send multiple instructions for a single element. So we can establish defaults, set the broad strokes, then adjust all the way down to styles for a single element for one element (with ID selectors).

But this gets complicated. There are a lot of situations where the most general rules, with the lightest selectors, are the most important to always 'win’. So we have a lot of complexity in the way we set our layers of intent… plus !important grenades.

Cascade Layers are the first big feature in this space. It gives authors a way to define layers like resets, themes and components; and also define the relative importance of those layers (implicitly – the order follows the first definition of layers). It means far less need for hacks and selector warfare.

Slide illustrates the layers of global and local scope

Scoped Styles – @scope – gives a form of encapsulation to CSS. The spec is still being debated a lot so it’s a great time to be giving feedback.

So this brings us to the real reason we’re all here…

Container Queries! What devs have been asking for all these years, CQs allow you to style according to the dimensions of containing elements and not the entire viewport. The container element is set in CSS, then other rules can query that element.

/* Establish containers */
.container {
contain: size layout;
.sidebar, main, .grid-item {
/* contain: size layout; */
contain: inline-size layout;
/* Query containers */
@container (min-width: 40em) {
.card { /* ... */ }
h2 { /* ... */ }

You can preview the current state of CQs by enabling them in canary builds of Chrome.

As Jen Simmons put it we are moving to intrinsic web design. Our platform is growing and changing, it is still going through radical changes!


The State of CSS-in-JS – Mark Dalgleish

The TL:DR for CSS-in-JS is that it has heaps of options but is dominated by Styled Components and Emotion.

  • A big callout for component developers is the ability for SC to set style according to the props being passed in.
  • Emotion gives syntax much closer to what you’d write in CSS directly.
  • Both of these libraries get millions of downloads every week so they are very popular.

So is CSS-in-JS a solved problem? Not really – there are a lot of tradeoffs to juggle…

  • bundle size
  • performance
  • flexibility
  • abstractions
  • static extraction

There’s also a bit of “not invented here” factor where people don’t want to make big bets on an area that’s changing relatively rapidly.

So there are new projects appearing that have different takes on the various concerns.

  • Goober – big focus on bundle size and perf
  • Stitches – digging into higher level abstractions and ways to handle variants; and also to add better support for CSS variables. They have the foundations set to look for planned static extraction later.

Mark has been working on Vanilla Extract, to go all in on static extraction. The goal is zero-runtime CSS-in-Typescript. The idea is to write styles with the benefits of typescript, but extract vanilla CSS and ship that to users (SCSS-in-JS!).

Another project looking at static extraction is Compiled, by Atlassian. It takes more of an inline/in-JSX approach to writing styles. It uses a bable plugin so it does require the code to be statically analysable. They’re aiming for the holy grail of being as expressive as you want with JS, but enjoy the optimisation of CSS.

So what should you pick if you’re starting a project today? Styled Components and Emotion are stable options that are relatively 'safe’ in this space. But there are lots of new options appearing which are worth checking out.


CSS Aspect Ratio – Anton Ball

Why do we need CSS aspect ratio? The solutions we currently use aren’t so great and it’s a cleaner, better solution.

Quick recap of aspect ratios – they are a relative size ratio:

  • 1:1 is a square
  • 4:3 is a common monitor ratio
  • 16:9 is a really common video ratio

We haven’t had a native solution for this in CSS. There are some hacks and some JS libraries that have papered over the gap. CSS has lots of good approaches to handling images, but they don’t work with video.

Users are often victims of cumulative layout shift – eg. when responsive images load, pushing content around. Ever clicked on the wrong thing because the page jumped? That’s CLS.

So what are the current solutions? The most common are probably the Padding Top Hack or libraries like fitvids.js.

But now we are getting a native CSS solution: aspect-ratio (not to be confused with the aspect ratio media query).

aspect-ratio: auto|ratio

eg: width: 100%; aspect-ratio: 16/9;

The syntax echoes grid syntax, as consistency helps a lot.

Intrinsic Aspect Ratio (aka natural aspect ratio) is useful for elements that are replaced with other things (iframe, video, embed, img). This is where browsers take the width and height and calculate the ratio for you.

We need to understand that aspect ratio is not the only thing affecting width; and in the heirarchy of CSS it can be thought of as the 'weakest’. If both width and height are set, that combination will override the aspect-ratio property.

Another gotcha is overflowing content – oversized content will extend the element, unless you specifically set the min-height to zero… at which point it will spill out. Whatever works best in your scenario.

Browser support is good although not universal yet – Safari is notably yet to ship support. It is however part of Web Compat 2021 as it’s such a common use case.


CSS Variables for Real Life – Matt Colman

Currently CSS variables aren’t used that much. They need to come down the CSS pyramid, from the tip to the base.

Slide: the healthy CSS pyrmamid, riffing on the healthy food pyramid

Matt’s process for new tech is to look into things when they pop up in a few different places; and a quick google showed “CSS vars in five quick examples”... which has the example of changing a background colour. Ok, cool, but we’ve always been able to do that… and basically none of the examples were compelling. Not even “css vars are awesome for dark mode”.

This trend ran through a lot of the top results on the topic. Cool example, but where can I really use it?

That’s the problem, Kent!

Matt finally found a great use case in the JIRA deployments view. They had a tricky rendering case where they needed a border to match a background… but the background varied a lot; and they had to sync hover state as well.

At first they tried to use currentColor but it wasn’t the colour, it was the background. But it triggered the realisation that it was the first CSS variable.

So they…

  • set the colour as a shared var between the container and the element, making it easy to synchronise the row background and the child element’s border
  • set fallback variables to make it more reliable
  • set different colours per row, because CSS variables are locally scoped

Another real-world example was a CSS var based font size system.

CSS variables also make it much easier to co-name design tokens and code, in a way that’s revealed in dev tools.


Typography superpower with variable fonts and CSS – Ananya Neogi

Currently static fonts dominate the web – for each font variation, we have to send a font file. So different weights and styles all add weight, meaning we have to restrict the type choices we make.

Variable fonts change this equation, by sending one file that supports multiple weights and styles. One file, multiple fonts. You can use CSS to access all the fonts in the file.

Variable fonts have the concept of 'axes’:

  • Registered axes – wdth, wght, ital, slnt, opsz
  • Custom axes – allows extras from the font designer

We use font-variation-settings in CSS to work with these axes.

h1 { font-variation-settings: "wght" var(--text-wght); }

  • Weight controls how heavy the text looks (sort-of-but-not-exactly translates to how thick the stroke is)
  • Width controls character width
  • Italic is a boolean, the text is either italicised or not
  • Slant is similar to italics, but offers more control over the degree of slant
  • Optical Size changes the apparent size of the type different, so things remain legible at smaller sizes

So how do you know what your font can do?

  • Drop it on WakamaiFondue.com
  • Check in Firefox dev tools – there’s a 'font’ tab that gives you access to adjust the axes

Where do you find variable fonts?

Slide: exaggerated Hello World of various variable font effects

So what are the practical uses and benefits?

  • There are big performance benefits
  • The perf benefits in turn give much more freedom to designers, who have more options with typography
  • Custom axes can effectively provide totally different typefaces out of one file (eg. the Movement font)

To really make use of all this, combine custom properties, calc(), media queries… (code demo with quite a bit of maths going on)

Reference: https://blog.typekit.com/2016/08/17/flexible-typography-with-css-locks/

(Demo of the fundamental techniques)

The deeper customisation of variable fonts have accessibility potential, eg. to improve reading experience with optical sizing on small screens:

p {
--text-opsz: 20;
font-variation-settings: "opsz" var(--text-opsz);
@media screen and (min-width: 25em) {
  --text-opsz: 16;

You can also use the GRAD axis in some fonts, which is hard to see in a presentation but it makes text much clearer when adjusted for different colour combinations. This is a common issue with dark modes, where text becomes less legible.

The more control we have over the way we can design on the web, the better experience we can

Ananya’s slides and code samples


Understanding display – Rachel Andrew

(This is a good one to revise, there is a heck of a lot in this. One of those presentations that everyone from beginner to veteran will learn something.)

CSS1 became a recommendation in December 1996, and it’s a tiny document. But it contains the fundamentals of the language we still use today.

Rachel can’t count the number of times she’s drawn the box model while teaching people CSS... and similarly everyone encounters the concepts of inline and block elements.

Browsers have a user agent stylesheet that applies the very basics of formatting to HTML, even if you don’t. These elements have key intrinsic features; and this can be seen in the way that spacing on those elements is applied.

Block, inline and box model has been the foundation of understanding CSS layout for 20 years. But in recent times, Rachel has found it’s time we have to change that approach. It makes people think Flexbox and Grid are completely separate and not part of the general model of the web.

It all starts with display. This is the key to understanding everything else. It’s a CSS3 specification, based on concepts in CSS2. These levels of CSS aren’t separate, they build on each other.

Going back to block and inline, what does that mean?

  • Block expands to fill available space (which dimension depends on reading direction)
  • Inline does not expand

This makes up the normal flow of the document. This is what your layout will always return to, so working with it is easier

Rachel jokes she travels the world talking about little boxes – and it’s easy to think of block and inline as boxes.

CSS specs have a lot of odd words, because of the demands of spec writing – if you don’t know what it means there should always be a link to be able to learn it.

Flexbox creates a new formatting context, in which normal flow does not apply. You now need to pay attention to the flexbox spec. Flex is block, inline-flex is inline. Same for Grid – it sets up a block that abides by the Grid spec.

So display now does a lot of things… and there is some refactoring happening. There is now display: block flex; and display: block grid etc. These mappings are only implemented in firefox at this point. But they are useful to understand:

Old Value New Value(s)
block block flow
flow-root block flow-root
inline inline flow
inline-block inline flow-root
flex block flex
inline-flex inline flex
grid block grid
inline-grid inline grid

Slide illustrating content overflow handling. Plus one of Rachel's cats.

CSS has some new properties, including flow-root which solves a classic overflow problem of content breaking out. The overflow:auto hack worked because it created a new block formatting context… flow-root addresses this.

Creating a new context with flow-root will also solve problems with collapsing margins. Flexbox and Grid also retain margins.

...back to boxes…

Any element gets a box; and this creates a box tree as things are nested. But some things aren’t elements that get a box… anonymous boxes, like text nodes.

<p>Some <span>text</span> nodes.</p>

If you set that paragraph to display:flex, spacing can collapse and you can’t target the anonymous nodes with CSS.

There’s also display:table-cell… this has some interesting behaviours as it creates anonymous boxes to emulate the HTML structure of table.

Then there’s float and position that take elements out of normal flow. This puts the onus on the author to manage most things that flow was handling for them. This is specified as “out of flow” and defines what should happen.

Out of flow elements can still be effected by changes to parent elements, which may create new contexts that take over. (demo of floated vs grid cards) In essence, floated items won’t be floating any more inside a grid. You can still absolutely-position elements inside a grid layout; but relative to its content area. Display table-cell won’t create anonymous boxes.

This is all defined in the spec, so browsers can handle it consistently.

There are two values of display that don’t generate boxes:

  • display:none – box and children all removed, it’s like the box was never there
  • display:contents – removes the box but not its children, they are promoted in the tree

There are some browser bugs to be resolved around this. Test thoroughly if you are using display:contents at the moment.

Some new terminology: priciple box and marker box. This is demonstrated with with lists – the marker goes around the bullet, the principle goes around the content. CSS lists spec is adding ::marker so we can target these directly. This opens up some neat things like the ability to add generated content to markers.

All of this stuff is values of display! Having separate specs for grid and flexbox is more about working group process than anything else.

Very important to understand – values of display do not inherit.

So what about subgrid? Doesn’t that inherit? Sort of… it allows you to use the track definitions in the subgrid, but values of display are not inherited.

Understanding Display: slides, links/resources, code demos and examples


Day Two (April 30)

Neurodiversity (and why you hate CSS) – Facundo Corradini

The term “neurodiverse” was coined to refer to the unlimited variation of the human mind, without negative connotations of other terms.

(Participatory exercises in visualisation and internal monologue – some people can see pictures or hear their internal monologue, others can’t.)

We all have a primary way of thinking, but nobody’s experience of this is exactly the same. Does that mean some are smarter than others? Well, “intelligence” is traditionally defined as the ability to learn a new task very quickly. Which doesn’t seem to really fit here.

Slide listing examples from the Multiple Intelligneces theory by Howard Gardner - Visual-spatial linguistic-verbal logical-mathematical bodily-kinesthetic musical intrapersonal extrapersonal

Howard Gardner – Multiple intelligences theory – proposed that there is a range of common styles of intelligence (or perhaps modes of learning). Mainstream psychology recognises the general idea but doesn’t like the terminology/definitions so much.

Designers are commongly Visual-Spatial; programmers are commonly Logical-Mathematical… but CSS sits between.

It is a design task? Is it a coding task? It’s both!

Is CSS a programming language? Yes – it’s a declarative, domain-specific programming language. But many people strongly reject the idea because they prefer a narrower definition of programming language.

CSS is highly contextual, which makes it a lot like most spoken languages. Take the example of the word “lead” in English… it has dozens of possible meanings. In CSS flex:1 can mean many different things depending on the other properties being applied.

CSS has a grammar and you have to follow it to understand what’s going on. Max Stoiber’s red/blue twitter poll shows many people still have trouble following the many contexts of CSS.

CSS is really contextual! Containing blocks, Formatting context, Stacking context, writing-mode, @rules, Inheritance Cascade, Specificity, Origin…

CSS has idioms. Clearfix CSS is a good example – you’re not trying to create a table or show content, those properties are being used to manipulate space.

CSS is a living language that continues to evolve as the need for new words arise.

So back to the question – is CSS design or programming? CSS relies heavily on Verbal-Linguistic intelligence… which is why both designers AND devs can struggle with it.

It can be good to think of CSS the way you’d think of learning a second language. So what approach do you take? How deeply do you need to learn it?

UI libraries are like taking a crash course in a language, just enough to get through a holiday. Most bootcamps are focused on JavaScript and use the crash course approach for CSS. But it means you would struggle to live there…

Some people try to learn CSS by learning lists of properties. But nobody really learns a new language by studying nothing but the dictionary…

For CSS, if you don’t learn more deeply you will always struggle. Instead of fighting margin collapses and float clearing, learn the deeper concept of formatting context… and understand the cascade!

Don’t just use tutorials and libraries, dive into the specs to understand what’s going on. You’ll learn more in an hour reading specs than a month of googling tutorials.

So there are lots of ways to handle the situation.

  • Do a crash course
  • Learn the language deeply
  • Hire an interpreter – hire people who are experts

There’s no harm in allowing people to shine in their role. Include diverse people and play to their strengths.

Celebrate diversity!


The New CSS Logical Properties – Elad Shechter

The internet was not created for the types of websites you use today! Think of CSS flexbox… it only started being implemented in 2012!

If you have been shipping internationalised websites, you’ll have experienced problems in the past where it was easier to ship two different stylesheets than it was to create one that handled both RTL and LTR. Going from left-to-right languages to top-to-bottom is like rotating everything 90degrees… but the

Enter the new CSS Logical Properties… but first a quick refresher

Block Axis defines the overall flow of the page:

  • writing-mode: horizontal-tb (horizontal top to bottom)
  • vertical-rl (vertical right-to-left)
  • vertical-lr (vertical left-to-right)

Inline Axis defines the text direction in the page

  • direction property (LTR/RTL)

To get away from directional naming, flexbox uses names like block-start and block-end. So when the direction of the page changes, the naming doesn’t become weird.

CSS Logical Properties continue this important conceptual shift.

Slide illustrating the new logical properties. Block axis or website flow shown vertically, with block-start at the top and block-end at the bottom. Inline axis or content flow shown horizontally, with inline-start on the left and inline-end on the right.

Top isn’t Top any more!

Top and bottom are the Block Axis

  • top = block-start
  • bottom = block-end

Left and right are the Inline Axis

  • left = inline-start
  • right = inline-end


  • margin-top = margin-block-start
  • margin-bottom = margin-block-end
  • margin-left = margin-inline-start
  • margin-right = margin-inline-end

Width and height turn into min and max inline and block sizes.

So the new CSS box model is renamed, and in the next few years we will stop talking about directions assuming LTR+TB.

But this means we have to relearn all the positional names as well

  • top = inset-block-start
  • left = inset-inline-start
  • bottom = inset-block-end
  • right = inset-inline-end

There are also new shorthands. There was no shorthand for top/bottom/left/right properties… but with logical props, we have prefixes that can be used as shorthands. Eg. for all the inset- properties:

  • inset: 0 0 0 0;
  • inset: 0 0;
  • inset: 0;


  • text-align: left = text-align: start
  • text-align: right = text-align: end

(lots of code examples along these lines, view the slides if you want a full list – these just give the flavour)

Live example: https://codepen.io/elad2412/pen/oQJmYQ

So can you use it yet? If you don’t need to support IE11, yes https://caniuse.com/css-logical-props – most of the core values are supported, there are some exceptions.

...and there are still some problems such as having to write out all margin properties longhand; and media queries don’t support them yet; things like that.

They are considering a new keyword 'logical’ to convert things like margin into logical flow; there is also a suggestion to have a flow-mode property you can set on html {} (you can upvote Elad’s suggestion at https://github.com/w3c/csswg-drafts/issues/1282#issuecomment-443253091)

More reading:


Beyond responsive design: new and future media queries – Kilian Valkhof

Responsive design is about websites adapting to things like the user’s device and surroundings. So the more we can do to understand what the user prefers, the better. There is a lot of new stuff coming, this talk will pick out some of the key things.

New media queries that are likely to be available soon:

  • contrast
  • reduced-data
  • custom-media
  • reduced-transparency
  • light-level
  • dynamic-range

Starting with everyone’s favourite… dark mode! prefers-color-scheme currently has just two values, light and dark; but the format keeps it open for future options.

prefers-reduced-motion – reduce the amount of swooshing going on. You should put your animations behind this check, so users who don’t want them don’t have to put up with them. There is also a hack where you can remove animations via a * selectors in CSS.

(Aside: see the linked guide for more examples than the few I’ve cherry picked here)

reduced-data is something you can add in today, serving lighter resources to browsers that do support it.

prefers-contrast: more|less|no-preference – there are lots of reasons to need different levels of contrast, many devices now include night modes that people are using to remove blue light. So there is a lot of interest in this space.

forced-colours: none|active – hard override of your colours, gives users a high level of control. Not a lot of adjustment required; and there are some ways to force your own colours, eg. if you have a colour picker.

prefers-reduced-transparency – helps reduce problems like layering images and text.

light-level: dim|normal|washed – this handles the issues caused by ambient lighting varying from very-bright to very-dark.

@custom-media is a big deal for all this as it enables variables in media queries, which helps manage these things in a rational way.



CSS Comparison Functions – Ahmad Shadeed

An example to illustrate what CSS Comparison Functions are…

To change the text size at different sizes we’d usually reach for a media query:

.title {
font-size: 1rem;
@media (min-width: 600px) {
.title {
    font-size: 2rem;

But you can do it this way instead with clamp:

.title {
font-size: clamp(1rem, (2vw + 1rem), 2rem)

So CSS Comparison Functions give us much shorter, neater syntax.

  • min() – you set a range of values and it will display the smallest
  • max() – you set a range of values and it will display the largest
  • eg. min(50%, 500px) and max(50%, 500px)

Clamp allows a preferred value as well as min/max:

.element {
  width: clamp(200px, 50%, 1000px);
  • The width will never go below 200px
  • The preferred value is 50% and will only work if the viewport width is greater than 200px and less than 1000px.
  • The width won’t go above 1000px

Things get even more powerful as clamp supports Math Expressions – you don’t even need to use calc().

Now vs The Future. How we design now, shown as a range of breakpoints xsmall, small, medium, large. The future, shown as a range from minimum, to recommended, to maximum.

Currently we design specifically for a set of different sizes; in the future we will set min/max/preferred and let the browser rendering inside those limits.

Accessibility note: avoid using min() for font-size, it’s very risky… easy to accidentally set microtext on portrait-mode mobile screens.

Example use cases for CSSCFs:

  • adding max() into linear-gradient(), so effects cna be adjusted at different screen sizes
  • using clamp() to adjust the padding above and below page sections; or the margins around headings

To support IE11 you can set a fallback property first, then add the CSSCF property; or use at-supports.



Move over TypeScript, here comes TypedCSS! – Rhiana Heath

Typed CSS really just means adding some type safety to CSS.

Why even have types?

  • better errors
  • code the documents itself
  • faster performance

So what types does CSS have now? While we see things in terms of properties, values, unitless values, etc… in terms of readable types they’re all just strings.

Slide: Woody and Buzz meme - strings! strings everywhere!

If you’ve worked with CSS values in JS you’ll have hit the issue – eg. where 500px is a string, which you need to split into the value and the unit to work on it.

If you typo a value like 500pxs you get a generic Invalid property value error. It’s technically accurate but it’s not helpful – it can be caused by such a broad range of problems.

So what is Typed CSS?

It’s an API under the CSS Houdini umbrella – Typed Object Model (OM) sits alongside the more-discussed APIs like Layout.

What types are we looking at in the CSS Typed OM? CSS-specific things like…

  • keyword
  • position
  • unit – a good example: in “500px”, “px” is the unit and 500 is the value
  • image

A couple of disclaimers:

  • Houdini is still fairly experimental and doesn’t have production-ready support yet… ishoudinireadyyet.com
  • Houdini is JS+CSS, not pure CSS


  • foo.css('width') current state – returns value as a string 500px
  • foo.attributeStyleMap('width') typed css – returns unit and value in a CSSUnitValue object { value: 500, unit: 'px' }

You can also set attributes this way. foo.attributeStyleMap.set('width', CSS.percent(50))

Once you can reliably get values and units separately, you can work with them much more easily; and it enables things like unit conversion. In a practical sense this means you can do calculations with mixed units, like a percentage added to a pixel value.

You can also add in error handling, eg. try/catch using CSSStyleValue.parse() to check if you have a valid value.



How To Draw, With CSS – Michal Porag

Have you ever wondered how people create incredible art with CSS?

Dribbble is a great place to find inspiration for this. Of course if you copy anything, ask the artist for permission first. Or make something that is clearly a copy of a famous work, with no deception.

Great example of randomly generated Mondrian squares – this is actually easier in code than it is in paint! We can also improve artwork with CSS thanks to animation.

But how do you start? Start simple – play with border-radius on all corners of an element. You can make a range of curved shapes.

Example with Pikachu – draw two lines across the face and you can see how the curves add up to make the shape, just by adjusting the border radius. Remember that when the corners don’t meet or add up, you can get straight lines as well.

Use relative units for this, to open up more opportunities and work on more devices.

Once you master tricks of creating basic shapes, use z-index to layer them.

The next trick is to bend gradients. Remember there are linear, radial and conic gradients in CSS and they will all give you different creative options. Conic gradients can make sharp cornered shapes too.

The next trick – box-shadow doesn’t just add shadows, you can create more shapes by adding more shadows.

Screenshot of the final product, of the CSS-drawn kite on a cloudy background

Walkthrough of drawing a single-div kite

  • Conic gradients with solid colours create triangles; these are combined to make the kite body
  • Elongate the shape with transform (scaleY) to make it look like kite sails
  • The tail is created on a pseudo element with a black border
  • Border radius curves the tail
  • Then crazy box-shadow tricks to create the kite tail bows
  • Then animate rotation to give it movement

Michal’s Codepens


A special Webbed Briefs – Heydon Pickering

(This writeup does not in any way approach the experience of watching this, you should just watch it. I have created a writeup mostly for my own amusement.)

There are lots of ways to draw a line onto a computer screen with CSS...

#1 The Horizontal Rule

<hr /> is a semantic element indicating a break in the content. It renders with a “shadow” set with an inset border. To remove that you can add a noshade attribute will draw a line without a shadow… although it is deprecated, so you should really just do it with a CSS border. You could also style an empty <div> but that has accessibility issues – it’s not a semantic element.

Screenshot from video. Heading is 'SVG' and Red Dwarf's Kryten appears saying 'sverg'.

#2 Scalable Vector Graphics

SVG has a few ways to draw a line. You can use a no-height rect or a line or a polyline… but the most versatile way to draw a line is path. Combine curves with fills and you can you draw just about everything, like skulls, because your calendar’s memento mori stopped working.

#3 UTF-8 encoded SVG background images

You can send a 1×1 SVG as a data url; then use repeating backgrounds to draw lines. Or stripes. Or sweary monks. If you use this technique with enough complexity you might achieve the galaxy-brained heights of CSS-in-SVG-in-CSS-in-JS.

#4 Repeating linear-gradients

SVG backgrounds are neat but you can’t rotate them. Linear gradients can rotate things, so if you want diagonal things you could use them for that. Hashtag diagonal hashtag stripes hashtag hashtag hashtag number.

#5 Houdini paint worklets

Paint worklets let you draw a line by writing a bunch of JavaScript. It has access to JS Math so you can do nifty random things. It looks a lot like canvas and needs JS. But it’s totally CSS. You might be a parsnip if you do this.

#6 WebGL

Arguably the pinnacle of over engineering for drawing a line… in simulated 3D space. But you can’t tell because you’re looking at it side on.

In summary

You can make browsers draw lines lots of ways. You should choose the simplest and most efficient way for your specific use case.

Some lines are decorative, but some are meaningful and should be audible.

Finally, remember that the leading cause of death in the UK is choking on an unchewed melon. The second most common cause of death is spontaneous combustion triggered by telling someone CSS Is A Programming Language.