Transition css height 100

31.08.2023 · ≈ 11 мин чтения

How To Do CSS Transitions With Height: Auto

Creating a smooth expand/collapse animation seems easy. Surely you can set a transition on height: auto , and it’ll just work?

Sadly, the CSS gods aren’t so kind.

Instead of the smooth open and close you wanted, your element flashes to its new height. No smooth animation.

As it turns out, animating on CSS auto values doesn’t work, and it’s honestly a real shame. We need to use specific values, and that’s not a luxury we always have.

Fortunately, there are several approaches we can take to animating auto dimensions in CSS.

Method 1: Use transform

Despite its rampant use, you should avoid CSS transitions on the height or width properties (among some others).

These properties affect the page layout. To see how other elements on the page are being affected during your animation, the browser completely recalculates your page’s layout.

This is where the CSS transform property comes in. transform causes your element to be animated like an image, and skip the layout recalculations. If you can use this approach, you should.

Unfortunately, there are two deal-breakers in using transform to collapse your content:

Method 2: Animate max-height / max-width

A different approach to collapsing height is to collapse max-height in its place.

The upside of this approach is that it’s straightforward. It also manages to avoid the weird warping effect of transform: scale .

There are some downsides, though:

  • We’re animating on height , with all its layout-thrashing goodness
  • You need a non-auto value for max-height
  • Your transition-timing applies to the max-height range, not height . This makes it nearly impossible to get a specific visual effect from your transitions.

Method 3: Calculate height with JavaScript

A lengthier (but more precise) approach is to use JavaScript to calculate the animation start and end using the element’s rendered height .

Once we determine the element’s actual height, we can inject it as inline CSS so the browser has something to transition between.

In terms of effect, this is probably the one you were going for, but with tradeoffs.

  • We’re still animating on height
  • We’ve introduced a fair chunk of code to address a very narrow problem
  • There’s tight coupling between your JavaScript and CSS

Method 4: Nuke from orbit with FLIP + Inverse Scaling

Remember Method 1 and all the problems that using transform caused?

Well, it turns out you can fix them.

Content warping can be fixed by applying counter-scaling on your content. The FLIP technique also lets us move surrounding content in a performant way.

This looks much better than our initial transform attempt, and solves the problems we were having. However:

  • This solution is big and complex. We’ve introduced a lot of code now, and it’s still a very narrow problem.
  • Several moving parts need to stay synchronised
  • We need a custom easing function. I’ve used linear for simplicity, but anything else gets gnarly.
  • Even more coupling than the height example.
Читайте также:  Html css font style example

Источник

CSS3 transition height auto to 100%

I have a little thumbnail that shows the title of an image. When you hover over it, the overlay spreads over the entire image and the button «learn more» will show as well. This is a fiddle of what I have so far: http://jsfiddle.net/razLnbvL/ My HTML:

 
Golf Courses Learn more
Land Owners Learn more
Landscape Contractors Learn more
#industries article < float: left; width: 33.33333%; position: relative; >#industries article img < max-width: 100%; >#industries article .caption < position: absolute; box-sizing: border-box; width: 100%; background-color: rgba(24, 66, 113, 0.65); color: #fff; text-align: center; font-weight: bold; text-transform: uppercase; padding: 9px 14px; bottom: 0; height: auto; transition: height 0.25s ease-out; >#industries article .caption span < display: block; >#industries article .caption .button < background-color: #b50937; border-color: #b50937; display: none; color: #fff; padding: 10px 30px; text-transform: uppercase; text-align: center; cursor: pointer; >#industries article:hover .caption < height: 100%; padding-top: 40px; transition: height 0.25s ease-in; >#industries article:hover .caption span < margin-bottom: 25px; >#industries article:hover .caption .button

However, I have tried min-height and max-height , but obviously the max-height won’t work since the text doesn’t even take up the entire space initially so it’s only going to go to the height of the text. And when I set the height attribute to 100% it just jolts up without the transition again. Any help would be appreciated! I want the overlay to slowly slide up and the learn more button to fade in (but I can do that later once I get the slide to work).

Источник

CSS-переход свойства height от 0px до auto

Хочу поделиться ещё одним способом создания css-перехода ( transition ) свойства height от 0px до auto .

Столкнулся с данной проблемой при разработке веб-компонентов TreeView и DataGrid. В TreeView решил сделать плавное развёртывание/свёртывание узлов, а в DataGrid — строки с дополнительным контентом. Почитав интернет, нашёл несколько способов реализации, основные — через свойство max-height и на javascript. Реализация на javascript была исключена — есть же css с поддержкой переходов и анимаций. Остался max-height , тем более в примерах с выпадающими меню всё работает.

В TreeView каждый узел имеет неограниченную вложенность, поэтому сразу не получится определить максимальную высоту его содержимого, да и если max-height задать очень большим, будут проблемы с анимацией перехода. Также, если развернуть дочерние узлы, высота родительского увеличится и может перекрыть max-height . Как ни крути, max-height не подходит. С DataGrid та же проблема — дополнительный контент в строке может быть любой. Нужен height:auto !

Итак, приступим к реализации перехода по свойству height от 0px до auto . Рассмотрим простой пример.

  • elBlock: HTMLDivElement — блок, который нужно развёртывать/свёртывать;
  • elToggle: HTMLButtonElement — кнопка-переключатель состояния.
Читайте также:  margin-bottom

Опишем обработчик события onClick для elToggle :

elToggle.addEventListener("click", () => < if (elBlock.style.height === "0px") < elBlock.style.height = `$< elBlock.scrollHeight >px` > else < elBlock.style.height = `$< elBlock.scrollHeight >px`; window.getComputedStyle(elBlock, null).getPropertyValue("height"); elBlock.style.height = "0"; > >);

Осталось добавить возврат height:auto после перехода:

elBlock.addEventListener("transitionend", () => < if (elBlock.style.height !== "0px") < elBlock.style.height = "auto" >>);

Ну вот и всё, теперь развёртывание/свёртывание блока работает как надо и не зависит от размера контента.

Рисунок 1 — Пример развёртывания/свёртывания узлов в TreeView

Стоит отметить минусы данного подхода:

  • использование javascript, хотелось бы только css;
  • во время перехода может измениться контент (его высота, scrollHeight ) и после его завершения, в случае возврата auto , высота блока резко поменяется в ту или иную сторону. Для избежания данного эффекта, необходимо отслеживать изменение scrollHeight и менять height . Как показывает практика, обычно переходы развёртывания/свёртывания занимают по 0.5 с, а за это время пользователь вряд ли успеет изменить что-то внутри, например, в случае TreeView, развернуть дочерний узел.

Источник

Transitioning to Height Auto (Two Ways)

Update 3 May 2023: It looks like the origin of this trick in grid traces back to this post from Nelson Menezes in 2021.

One of my longstanding annoyances with CSS has been the inability to transition to height auto. It’s an incredibly common use-case that’s needed for dropdowns and accordions and all sorts of other UI patterns. Unfortunately, this just doesn’t work:

/* Doesn't work */ .dropdown  height: 0; transition: height 0.5s ease-out; > .dropdown.is-open  height: auto; > 

It’ll open and close just fine, but it won’t animate. The normal course of action here has been to pull out JavaScript and set the height explicitly based on the element’s scrollHeight .

However, I have come across a two different ways to solve the problem without the help of JavaScript. One approach transitions an element inside a flex item; the other approach transitions an element as a grid item. Each requires adding one or two extra elements to the page to pull it off, but in many cases, that’s still better than the alternative.

With flexbox¶

I found this solution from Joakim Chiem in a comment buried in the W3C GitHub issue. (The comment is two and a half years old. I am so sorry for not writing about it before now!)

For this approach, wrap the element you want to transition in two divs: the outer will be a flexbox and the inner one will be a flex item. With these in place, you can transition max-height from 0 to 100% . This leverages a quirk of how height/max-height work inside flexbox.

.wrapper  display: flex; > .inner  max-height: 0; overflow: hidden; transition: max-height 0.5s ease-out; > .wrapper.is-open .inner  max-height: 100%; > 

Just be sure there’s an extra div between the wrapper and the inner element:

div class="wrapper"> div> div class="inner">Expandable content> > > 

And here’s what it looks like in action:

This demo won’t show the transition because you have reduced motion settings enabled.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent mi enim, venenatis non facilisis sed, finibus in enim. Sed auctor enim nisl, sit amet feugiat risus blandit vitae.

Integer dapibus tortor lorem, quis interdum erat maximus eu. Nam varius, nisl ac pharetra convallis, neque ex blandit quam, sit amet condimentum lectus elit vel ligula. Donec commodo porta elit quis facilisis. Sed non purus a massa convallis ultricies. Donec malesuada sollicitudin dui, vel lobortis arcu rutrum ut. Curabitur lobortis ac tellus non tempor. Donec nisl risus, cursus vel odio quis, convallis euismod ante.

Nulla lectus diam, sagittis id urna in, tincidunt facilisis sapien. Sed ante turpis, porttitor a diam at, auctor lobortis sapien. Cras ornare dolor sed arcu laoreet volutpat ut tristique ipsum.

The downside to this approach is that, while the inner element animates smoothly, its container does not; that just snaps into place instantly. But that might be prefereable in some situations, since the browser doesn’t need to constantly reflow all the contents of the page beneath it.

With grid¶

I first saw mention of this technique from Chris Coyier, but he kinda buried the lede amid a longer wish-list of CSS features.

This one is a bit simpler, and probably a little more understandable. Make a CSS grid with a single grid item. All you have to do is transition grid-template-rows from 0fr to 1fr , so the grid item transitions to its auto height:

.wrapper  display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.5s ease-out; > .wrapper.is-open  grid-template-rows: 1fr; > .inner  overflow: hidden; > 

This does not require the extra div. Just a grid container and its one grid item:

div class="wrapper"> div class="inner">Expandable content> > 

Surprisingly, it’s that simple:

This demo won’t show the transition because you have reduced motion settings enabled.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent mi enim, venenatis non facilisis sed, finibus in enim. Sed auctor enim nisl, sit amet feugiat risus blandit vitae.

Integer dapibus tortor lorem, quis interdum erat maximus eu. Nam varius, nisl ac pharetra convallis, neque ex blandit quam, sit amet condimentum lectus elit vel ligula. Donec commodo porta elit quis facilisis. Sed non purus a massa convallis ultricies. Donec malesuada sollicitudin dui, vel lobortis arcu rutrum ut. Curabitur lobortis ac tellus non tempor. Donec nisl risus, cursus vel odio quis, convallis euismod ante.

Nulla lectus diam, sagittis id urna in, tincidunt facilisis sapien. Sed ante turpis, porttitor a diam at, auctor lobortis sapien. Cras ornare dolor sed arcu laoreet volutpat ut tristique ipsum.

This approach feels a lot cleaner. Only two DOM nodes needed, and all the page content beneath moves fluidly like you probably expect.

The one caveat to both of these is you can’t add any padding to the inner element. If you need padding, you have to add one more extra element inside the collapsed element and put the padding on that.

Источник