Question

How to Transition Height from 0 to Auto in CSS

csscss-transitions

Question

I want to make a hidden section slide down using CSS transitions.

The element starts with height: 0 and overflow: hidden. On hover, I change it to height: auto, but instead of animating, it appears instantly.

If I start from a fixed height such as 40px and transition to height: auto, it first animates toward 0 and then suddenly jumps to the final size.

How can I create this expand/collapse effect using CSS only, without JavaScript?

#child0 {
  height: 0;
  overflow: hidden;
  background-color: #dedede;
  transition: height 1s ease;
}

#parent0:hover #child0 {
  height: auto;
}

#child40 {
  height: 40px;
  overflow: hidden;
  background-color: #dedede;
  transition: height 1s ease;
}

#parent40:hover #child40 {
  height: auto;
}

h1 {
  font-weight: bold;
}
<hr>
<div id="parent0">
  <h1>Hover me (height: 0)</h1>
  <div id="child0">
    Some content<br>
    Some content<br>
    Some content<br>
    Some content<br>
    Some content<br>
    Some content<br>
  </div>
</div>

<hr>
<div id="parent40">
  <h1>Hover me (height: 40)</h1>
  <div id="child40">
    Some content<br>
    Some content<br>
    Some content<br>
    Some content<br>
    Some content<br>
    Some content<br>
  </div>
</div>

Short Answer

By the end of this page, you will understand why height: auto does not animate in CSS, what kinds of values CSS transitions can animate, and the most common CSS-only workaround: animating max-height. You will also see alternatives like transform and learn when each approach is appropriate.

Concept

CSS transitions work best when the browser can calculate both a clear starting value and a clear ending value.

For example, this is easy to animate:

height: 0px;   /* start */
height: 200px; /* end */

The browser can generate the intermediate values: 20px, 40px, 60px, and so on.

But auto is different. It is not a fixed numeric value. It means: let the browser calculate the size based on the content and layout. Because of that, CSS cannot interpolate from 0px to auto during a transition.

That is why this does not animate:

height: 0;
transition: height 1s ease;
height: auto;

The browser jumps directly to the final layout instead of animating.

Why this matters

Expandable panels, dropdowns, accordions, menus, FAQ sections, and mobile navigation often need to grow and shrink based on content. Since content height is usually unknown ahead of time, developers often run into this exact limitation.

A common CSS-only workaround is to animate max-height instead of height:

  • keep height controlled by the content
  • set max-height: 0 when collapsed
  • animate to a large enough max-height when expanded

This works because max-height uses numeric values, which CSS can animate.

Mental Model

Think of CSS transitions like animating a car trip between two addresses with exact coordinates.

  • height: 0px is a known location.
  • height: 200px is another known location.
  • height: auto is like saying, "drive to wherever the content decides to be."

The browser cannot smoothly animate toward a destination that is not a fixed number.

Using max-height is like giving the browser a measurable limit instead:

  • collapsed: max-height: 0
  • expanded: max-height: 300px

Now the browser has two concrete numeric values and can animate between them.

Take Quiz

Syntax and Examples

The most common CSS-only solution is to animate max-height.

Basic pattern

.panel {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.4s ease;
}

.container:hover .panel {
  max-height: 300px;
}

Example

<div class="menu">
  <button>Hover me</button>
  <div class="panel">
    <p>Item 1</p>
    <p>Item 2</p>
    <p>Item 3</p>
  </div>
</div>
.menu .panel {
  max-height: 0;
  overflow: hidden;
  background: #dedede;
  transition: max-height 0.5s ease;
}

.menu:hover .panel {
  max-height: 200px;
}

Why it works

  • The real content height can still be determined naturally.
  • overflow: hidden prevents hidden content from showing.
  • max-height transitions from 0 to 200px smoothly.

Important note

The expanded max-height must be large enough to fit the content. If the content becomes taller than that value, it will be cut off.

Alternative: transform

If the visual effect is more important than the document layout, you can animate a scale effect:

.panel {
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 0.3s ease;
}

.container:hover .panel {
  transform: scaleY(1);
}

This looks like a slide/open effect, but it does not resize layout in the same way as height-based expansion.

Step by Step Execution

Consider this example:

<div class="box">
  <h2>Hover me</h2>
  <div class="content">Hello<br>Hello<br>Hello</div>
</div>
.content {
  max-height: 0;
  overflow: hidden;
  transition: max-height 1s ease;
}

.box:hover .content {
  max-height: 100px;
}

What happens step by step

  1. The page loads.
  2. .content has max-height: 0, so it is fully collapsed.
  3. overflow: hidden hides anything that does not fit inside that height.
  4. When the user hovers over .box, the rule .box:hover .content becomes active.
  5. max-height changes from 0 to 100px.
  6. Because both values are numeric, the browser animates the change.
  7. During the animation, the visible area grows until the content fully appears.

Why height: auto fails in the same scenario

If you wrote this instead:

.content {
  height: 0;
  transition: height 1s ease;
}

.box:hover .content {
  height: auto;
}

the browser would know the start value (0), but the end value (auto) is not a number it can animate through frame by frame. So it jumps.

Real World Use Cases

This pattern appears in many common UI elements.

Dropdown menus

A navigation menu may reveal links on hover or click.

Accordion sections

FAQ pages often expand and collapse answers of different lengths.

Mobile navigation

A menu panel may open to show a list of routes.

Notification details

A compact card may expand to show more information.

Filter panels

Search interfaces often hide advanced filters until needed.

In all of these cases, the final height depends on content, which is why developers often use max-height or JavaScript-assisted measurement.

Take Quiz

Real Codebase Usage

In real projects, developers usually choose one of these patterns:

1. max-height for simple CSS-only UI

Good for:

  • small dropdowns
  • FAQ sections with predictable size
  • simple hover interactions

Pattern:

.section {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.3s ease;
}

.section.is-open {
  max-height: 500px;
}

2. JavaScript-measured height for precise animations

When content size is unknown or dynamic, developers often measure the element's scrollHeight and animate to that pixel value.

This avoids guessing a max-height.

3. transform for performance-focused effects

Developers sometimes animate transform because it is often smoother and cheaper for the browser to render. However, this is mainly a visual effect and may not affect surrounding layout as expected.

4. Class-based state changes

In real codebases, hover is often replaced by classes such as .is-open, especially for click-driven interfaces:

.panel {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.3s ease;
}

.panel.is-open {
  max-height: 300px;
}

This makes the code easier to manage and reuse.

Common supporting patterns

  • overflow: hidden to clip content during animation
  • guard values like max-height: 999px when content size varies
  • early state classes like .is-open and .is-collapsed
  • reduced-motion support for accessibility

Common Mistakes

1. Trying to transition to auto

Broken example:

.panel {
  height: 0;
  transition: height 0.4s ease;
}

.panel:hover {
  height: auto;
}

Why it fails:

  • auto is not an animatable numeric endpoint for height.

Use this instead:

.panel {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.4s ease;
}

.panel:hover {
  max-height: 200px;
}

2. Forgetting overflow: hidden

Broken example:

.panel {
  max-height: 0;
  transition: max-height 0.4s ease;
}

Problem:

  • The content may still be visible even though the container is collapsed.

Fix:

.panel {
  max-height: 0;
  overflow: hidden;
}

3. Choosing a max-height that is too small

If the content is taller than the expanded value, part of it will be cut off.

.panel.open {
  max-height: 100px; /* too small for content */
}

Choose a safe value:

.panel.open {
  max-height: 500px;
}

4. Using hover for important interactions on touch devices

Hover works poorly or differently on mobile devices.

Prefer click-based toggles for production interfaces.

5. Animating the wrong property

Sometimes beginners animate display:

.panel {
  display: none;
  transition: display 0.3s ease;
}

This does not work because display is not animatable.

Use animatable properties like:

  • max-height
  • opacity
  • transform

Comparisons

ApproachCan animate smoothly?Affects layout?Best forLimitation
height: 0 to height: autoNoYesNot recommendedauto is not animatable
max-height: 0 to max-height: 300pxYesYesSimple CSS-only expand/collapseMust guess a large enough max value
transform: scaleY(0) to scaleY(1)YesUsually no real layout resizingPure visual open/close effectsCan look squashed; layout behavior differs
opacity: 0 to opacity: 1YesNoFade effectsDoes not create slide/height expansion
JavaScript with measured heightYesYesDynamic content with exact sizingRequires scripting

height vs max-height

PropertyGood for animation?Notes
heightYes, if both values are fixed lengthsExample: 0px to 200px
height: autoNoBrowser cannot interpolate auto
max-heightYesCommon workaround for unknown content height
Take Quiz

Cheat Sheet

/* CSS-only expand/collapse pattern */
.panel {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.3s ease;
}

.panel.is-open {
  max-height: 300px;
}

Key rules

  • height: auto does not transition.
  • height can transition only between numeric values like 0px and 200px.
  • max-height is the usual CSS-only workaround.
  • Add overflow: hidden to hide collapsed content.
  • Pick a max-height large enough for the content.

Useful alternatives

/* Visual-only open effect */
.panel {
  transform: scaleY(0);
  transform-origin: top;
  transition: transform 0.3s ease;
}

.panel.is-open {
  transform: scaleY(1);
}

Not animatable for this use case

  • height: auto
  • display: none to display: block

Quick decision guide

  • Need CSS-only and simple? Use max-height.
  • Need exact dynamic height? Use JavaScript.
  • Need a visual effect only? Use transform.

FAQ

Why can't CSS transition height: auto?

Because auto is not a fixed numeric value. The browser cannot calculate intermediate values between 0px and auto.

What is the best CSS-only replacement for height: auto animation?

Usually max-height with overflow: hidden.

Is max-height a perfect solution?

No. You must choose an upper limit, and if the content grows beyond it, the content may be clipped.

Can I use display: none and transition it?

No. display is not animatable.

Should I use hover for dropdowns?

For simple desktop effects, yes. For important navigation or mobile-friendly UI, click-based interactions are usually better.

Is transform: scaleY() better than max-height?

It depends. transform can be smoother visually, but it does not behave like true layout expansion.

When should I use JavaScript instead?

Use JavaScript when the content height is unknown, changes dynamically, or must animate precisely to its actual size.

Take Quiz

Mini Project

Description

Build a simple FAQ item that expands and collapses using only CSS. This demonstrates the common max-height technique for creating a slide-down effect when the content height is not known in advance.

Goal

Create a CSS-only expandable answer panel that smoothly opens and closes without using height: auto in the transition.

Requirements

  • Create a question-and-answer block with a visible title.
  • Keep the answer hidden by default.
  • Reveal the answer with a smooth animation using CSS only.
  • Prevent hidden content from overflowing while collapsed.
  • Use a technique that works around the height: auto limitation.
Take Quiz

Keep learning

Related questions

View more