Jasmine Web Starter Logo

Jasmine Web Starter

Sproutius the magician making a rabbit appear from his hat

Going from display:none to height:auto in CSS seconds!

Published:

August 2024 has seen some exciting new CSS features become available in all major browsers making them Baseline Newly Available @starting-style and transition-behavior: allow-discrete, now allow us to transition elements with discrete properties such as display: none more smoothly with less code and without the need for added JavaScript.

Though not quite Baseline adopted yet but equally as exciting (if like us CSS floats your boat!) is the news we can now animate to and from height: auto using just CSS with the help of interpolate-size and calc-size.

What's the fuss?

Ok, so why should we be getting excited about transitioning display: and height: properties we hear you ask?

Well having the ability to better control how an element is or is not displayed should firstly help your initial page load speed, if an item needs to be hidden from sight when the page is first rendered.

Or when we have a expanding element on a page which may have a variable height due to changing contents, so we need to be able to set its height to auto.

Also being able to control how the element transitions into place when necessary with entry animation effects, instead of its natural state of instantly being there like an on/off switch.

Though currently the baseline only includes animations on entry not exit. That's not to say it isn't possible to animate on exiting too, as there is a work around for this, but at the time of writing the browser support for it is low, so it would have to be included as a progressive enhancement feature. Which isn't an issue and won't break anything, it just means some users will see a smooth transitioned exit and for others like magic it will simply disappear as it did before this was possible. (If you want to find out more we'll include links to some other awesome articles on this at the end.)

The magical properties of allow-discrete

By default properties that animate discretely do not trigger transition events, so we needed a way to make this happen. This is where the allow-discrete transition mode comes in.

/* Keyword values */
transition-behavior: allow-discrete;
transition-behavior: normal;

Usually discrete-animated properties will switch between two values, halfway (50%) through animating between them. That is unless we are trying to animate from display: none or content-visibility: hidden where the transitioned content will switch immediately (0%) and be visible through the entire animation duration. And vice versa when transitioning back the content will switch at (100%).

By using the allow-discrete value we can now animate these discrete properties too, but only when used along with other transition properties such as transition-property and transition-duration, or when it is added to the transition: shorthand.

.sprout_advert {
    transition-property: height, display;
    transition-duration: 0.5s;
    transition-timing-function: ease-in-out;
    transition-behavior: allow-discrete;
}

/* transition shorthand  */
.sprout_advert {    
    transition: all 0.7s ease-in-out allow-discrete;
}

Please note when using transition-behavior: allow-discrete or adding allow-discrete to the transition: shorthand it should always be added after the transitions, otherwise it will be ignored and the transitions then not applied by the browsers.

Its all in the timing with @starting-style

So we've enabled our discrete-animated properties to transition, but how do we control when that transition is triggered? You can use the @starting-style at-rule to enable transitions when an element is first added to the page, or when the display value changes from none.

.sprout_advert {    
    display: none; 
    transition: all 0.7s ease-in-out;
    transition-behavior: allow-discrete;
}

When we have an element that starts with a value of display: none you'd be forgiven for thinking that its height would be 0. But unless a height is specified an element will actually have a computed value of auto, which doesn't effect that it isn't yet visible, but does mean the browser will include it in the initial page load calculations. So if we don't want the element included in the first rendering of the page, we have to declare it to have a height: 0 which we can do by using the @starting-style at-rule, thus controlling when we want the element to be added to the page.

.sprout_advert {    
    display: none;
    transition: all 0.7s ease-in-out;
    transition-behavior: allow-discrete;
    
    @starting-style {
        height: 0;
    }
}

Sizing up the height: auto problem

Hasn't animating and transitioning elements been around for a while? Yes it has, but until now it wasn't possible to do it with elements that we didn't give a fixed height to, as it wouldn't work with keywords values such as the go to magic failsafe of : auto, many a designer/developer's favourite keyword!

But now our calculation headaches are (almost) over with the help of interpolate-size: allow-keywords and calc-size.

Interpolate-size

When we add this amazing one liner interpolate-size: allow-keywords to our code it enables us to animate to the intrinsic (natural) size of the element.

.sprout_advert_sneakpeek {    
    height: 1.5lh;
    transition: height 0.7s ease-in-out;
    interpolate-size: allow-keywords;
}

.sprout_advert_sneakpeek:hover {
    height: auto;
}

As well as adding it to one particular element we can also add it to the :root or html of our CSS, and because this is an inherited value, it allows all transition and animation keyword values to be used across your whole website.

:root {
interpolate-size: allow-keywords;
}

/* alternatively  */

html {
    interpolate-size: allow-keywords;
}

A powerful little line of code which is ideal to add to new projects or to your CSS reset/starter files for future website creations. Though if you are thinking of adding it to an older project, we'd strongly advise that you test and double check that it doesn't break or cause any strange effects you weren't expecting.

Its not just useful for height: auto it also animates these keywords too

  • content
  • min-content
  • max-content
  • fit-content

But unfortunately it won't as yet allow you to transition and animate between two different keyword values, but who knows what the future may bring!

Work it out with calc-size

What if you want more control over the size your element changes to, rather than the intrinsic sizing you get with interpolate-size:.

You'd really need the calc: function for that, but unfortunately it doesn't allow calculations based on keyword values. Luckily for us the new calc-size: function does!

There are some syntax differences to using calc-size: from what you may be used to with calc:. As here we need to pass two values, firstly the intrinsic size e.g. auto or max-content, then we write the calculation that we want to do to the size e.g. + 16px or * 2 separating the values with a comma.

.sprout_advert {
  block-size: calc-size(auto, size + 16px)
}
/* height example - takes the natural size of 
the element and adds 16px to its height */

.sprout_advert {
  inline-size: calc-size(max-content, size * 2);
}
/* width example - takes the max-content size 
and multiples it by 2 */

.sprout_advert {
  inline-size: calc-size(max-content, size * .5);
}
/* width example - takes the max-content size and
multiples it by .5 making it half its original size */

If you're already familiar with using calc: functions it shouldn't take you long to get to grips with calc-size: too.

Progressive Enhancement

We do need to point out that both interpolate-size: allow-keywords and calc-size are not currently Baseline Newly Available at the time of writing this article. So should only be used as a progressive enhancement for the moment, with fall backs for those browsers still not supporting these features. Though if you would like to check their current status you can either look them up on caniuse.com or go directly to the Web.dev Baseline Newly Available page and see what the latest feature releases are.

Why we're excited!

We can't wait till all these features are fully Baseline available as they will be a great addition to our starter templates and help make reusable modular components such as product cards and adverts so much easier to build and use.

Sproutius cooking book advert
Our advert with link to expandable info panel

Just like Sproutius has added here to his book advert, with a expanding info panel when you click/hover on the sneak-peek link. Which in a live scenario could be opened from display: none and animated with transitions to expand and close in a smooth gradual motion.

Sproutius cooking book advert with sneak peek receipe
Our advert with info panel open

This is just one of many ways we are looking forward to implementing these new features.

Further Resources

If you want to know more about the features we've covered here, plus, see some live demos or watch a video on how to use them, we recommend you check out these links below:

Now in Baseline: animating entry effects web.dev article by Una Kravets

Transition to `height: auto` & `display: none` Using Pure CSS CSS Weekly article by Zoran Jambor

Transitioning to Auto Height CSS Tricks article by Geoff Graham

Animate and do math on things like height: auto with interpolate-size and calc-size() YouTube video by Kevin Powell

Coming 2025

You've been asking and we have listened... so in 2025 we plan to start introducing a beginners guide to CSS with the help of our new friend Cam Chameleon!

Cam the CSS Chameleon
Cam CSS Chameleon

So if you would like to know more on the features in this article or have some suggestions for other CSS topics you'd like us to write about contact us today.