увеличения - анимирование высоты css




Как переместить высоту: 0; высота: авто; используя CSS? (20)

Я пытаюсь сделать слайд <ul> с помощью переходов CSS.

<ul> начинается с height: 0; , При зависании высота устанавливается на height:auto; , Однако это заставляет его просто появляться, а не переход,

Если я делаю это с height: 40px; height: auto; , то он будет скользить до height: 0; , а затем внезапно перепрыгните на правильную высоту.

Как еще я могу это сделать без использования JavaScript?

#child0 {
  height: 0;
  overflow: hidden;
  background-color: #dedede;
  -moz-transition: height 1s ease;
  -webkit-transition: height 1s ease;
  -o-transition: height 1s ease;
  transition: height 1s ease;
}
#parent0:hover #child0 {
  height: auto;
}
#child40 {
  height: 40px;
  overflow: hidden;
  background-color: #dedede;
  -moz-transition: height 1s ease;
  -webkit-transition: height 1s ease;
  -o-transition: height 1s ease;
  transition: height 1s ease;
}
#parent40:hover #child40 {
  height: auto;
}
h1 {
  font-weight: bold;
}
The only difference between the two snippets of CSS is one has height: 0, the other height: 40.
<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>


Визуальное обходное решение для анимации высоты с использованием переходов CSS3 - это оживить дополнение.

Вы не совсем получаете полный эффект протирания, но игра со значениями продолжительности перехода и заполнения должна быть достаточно близко. Если вы не хотите явно устанавливать высоту / максимальную высоту, это должно быть то, что вы ищете.

div {
    height: 0;
    overflow: hidden;
    padding: 0 18px;
    -webkit-transition: all .5s ease;
       -moz-transition: all .5s ease;
            transition: all .5s ease;
}
div.animated {
    height: auto;
    padding: 24px 18px;
}

http://jsfiddle.net/catharsis/n5XfG/17/ (риффед с stefband выше jsFiddle)


Вместо этого вы должны использовать scaleY.

HTML:

<p>Here (scaleY(1))</p>
<ul>
  <li>Coffee</li>
  <li>Tea</li>
  <li>Milk</li>
</ul>

CSS:

ul {
    background-color: #eee;
    transform: scaleY(0);    
    transform-origin: top;
    transition: transform 0.26s ease;
}

p:hover ~ ul {
    transform: scaleY(1);
}

Я сделал версию префикса вышеприведенного кода на jsfiddle, http://jsfiddle.net/dotnetCarpenter/PhyQc/9/ и изменил ваш jsfiddle, чтобы использовать scaleY вместо высоты, http://jsfiddle.net/dotnetCarpenter/7cnfc/206/ .


Вы не можете в настоящее время анимации по высоте, когда одна из задействованных высот auto , вы должны установить две явные высоты.


Используйте max-height в преобразовании, а не в height . И установите значение на max-height на нечто большее, чем ваша коробка когда-либо появится.

См. Демонстрацию JSFiddle, предоставленную Крисом Джорданом в другом answer здесь.

#menu #list {
    max-height: 0;
    transition: max-height 0.15s ease-out;
    overflow: hidden;
    background: #d5d5d5;
}

#menu:hover #list {
    max-height: 500px;
    transition: max-height 0.25s ease-in;
}
<div id="menu">
    <a>hover me</a>
    <ul id="list">
        <!-- Create a bunch, or not a bunch, of li's to see the timing. -->
        <li>item</li>
        <li>item</li>
        <li>item</li>
        <li>item</li>
        <li>item</li>
    </ul>
</div>


Решение, которое я всегда использовал, должно было сначала исчезнуть, а затем уменьшить font-size , padding и значения margin . Он не выглядит так же, как вытирание, но он работает без статической height или max-height .

Рабочий пример:

/* final display */
#menu #list {
    margin: .5em 1em;
    padding: 1em;
}

/* hide */
#menu:not(:hover) #list {
    font-size: 0;
    margin: 0;
    opacity: 0;
    padding: 0;
    /* fade out, then shrink */
    transition: opacity .25s,
                font-size .5s .25s,
                margin .5s .25s,
                padding .5s .25s;
}

/* reveal */
#menu:hover #list {
    /* unshrink, then fade in */
    transition: font-size .25s,
                margin .25s,
                padding .25s,
                opacity .5s .25s;
}
<div id="menu">
    <b>hover me</b>
    <ul id="list">
        <li>item</li>
        <li>item</li>
        <li>item</li>
        <li>item</li>
        <li>item</li>
    </ul>
</div>

<p>Another paragraph...</p>


Я знаю, что это тридцать-точный ответ на этот вопрос, но я думаю, что это того стоит, так и здесь. Это решение только для CSS со следующими свойствами:

  • Вначале нет задержек, и переход не прекращается рано. В обоих направлениях (расширяя и сворачивая), если вы укажете длительность перехода в 300 мс в своем CSS, то переход займет 300 мс, период.
  • Он transform: scaleY(0) фактическую высоту (в отличие от transform: scaleY(0) ), поэтому он делает все правильно, если есть содержимое после сбрасываемого элемента.
  • Хотя (как и в других решениях) есть магические числа (например, «выберите длину, которая выше, чем ваша коробка когда-либо будет»), это не фатально, если ваше предположение окажется неправильным. В этом случае переход может выглядеть не удивительно, но до и после перехода это не проблема: в расширенном ( height: auto ) состоянии весь контент всегда имеет правильную высоту (в отличие от, например, если вы выбираете max-height которая оказывается слишком низкой). И в сложенном состоянии высота равна нулю.

демонстрация

Вот демо с тремя разборными элементами, все разные высоты, которые используют один и тот же CSS. Вы можете нажать «полная страница» после нажатия «выполнить сниппет». Обратите внимание, что JavaScript только переключает collapsed класс CSS, нет никакого измерения. (Вы можете сделать эту точную демонстрацию без какого-либо JavaScript вообще, используя флажок или :target ). Также обратите внимание, что часть CSS, ответственная за переход, довольно короткая, и для HTML требуется только один дополнительный элемент оболочки.

$(function () {
  $(".toggler").click(function () {
    $(this).next().toggleClass("collapsed");
    $(this).toggleClass("toggled"); // this just rotates the expander arrow
  });
});
.collapsible-wrapper {
  display: flex;
  overflow: hidden;
}
.collapsible-wrapper:after {
  content: '';
  height: 50px;
  transition: height 0.3s linear, max-height 0s 0.3s linear;
  max-height: 0px;
}
.collapsible {
  transition: margin-bottom 0.3s cubic-bezier(0, 0, 0, 1);
  margin-bottom: 0;
  max-height: 1000000px;
}
.collapsible-wrapper.collapsed > .collapsible {
  margin-bottom: -2000px;
  transition: margin-bottom 0.3s cubic-bezier(1, 0, 1, 1),
              visibility 0s 0.3s, max-height 0s 0.3s;
  visibility: hidden;
  max-height: 0;
}
.collapsible-wrapper.collapsed:after
{
  height: 0;
  transition: height 0.3s linear;
  max-height: 50px;
}

/* END of the collapsible implementation; the stuff below
   is just styling for this demo */

#container {
  display: flex;
  align-items: flex-start;
  max-width: 1000px;
  margin: 0 auto;
}  


.menu {
  border: 1px solid #ccc;
  box-shadow: 0 1px 3px rgba(0,0,0,0.5);
  margin: 20px;

  
}

.menu-item {
  display: block;
  background: linear-gradient(to bottom, #fff 0%,#eee 100%);
  margin: 0;
  padding: 1em;
  line-height: 1.3;
}
.collapsible .menu-item {
  border-left: 2px solid #888;
  border-right: 2px solid #888;
  background: linear-gradient(to bottom, #eee 0%,#ddd 100%);
}
.menu-item.toggler {
  background: linear-gradient(to bottom, #aaa 0%,#888 100%);
  color: white;
  cursor: pointer;
}
.menu-item.toggler:before {
  content: '';
  display: block;
  border-left: 8px solid white;
  border-top: 8px solid transparent;
  border-bottom: 8px solid transparent;
  width: 0;
  height: 0;
  float: right;
  transition: transform 0.3s ease-out;
}
.menu-item.toggler.toggled:before {
  transform: rotate(90deg);
}

body { font-family: sans-serif; font-size: 14px; }

*, *:after {
  box-sizing: border-box;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div id="container">
  <div class="menu">
    <div class="menu-item">Something involving a holodeck</div>
    <div class="menu-item">Send an away team</div>
    <div class="menu-item toggler">Advanced solutions</div>
    <div class="collapsible-wrapper collapsed">
      <div class="collapsible">
        <div class="menu-item">Separate saucer</div>
        <div class="menu-item">Send an away team that includes the captain (despite Riker's protest)</div>
        <div class="menu-item">Ask Worf</div>
        <div class="menu-item">Something involving Wesley, the 19th century, and a holodeck</div>
        <div class="menu-item">Ask Q for help</div>
      </div>
    </div>
    <div class="menu-item">Sweet-talk the alien aggressor</div>
    <div class="menu-item">Re-route power from auxiliary systems</div>
  </div>

  <div class="menu">
    <div class="menu-item">Something involving a holodeck</div>
    <div class="menu-item">Send an away team</div>
    <div class="menu-item toggler">Advanced solutions</div>
    <div class="collapsible-wrapper collapsed">
      <div class="collapsible">
        <div class="menu-item">Separate saucer</div>
        <div class="menu-item">Send an away team that includes the captain (despite Riker's protest)</div>
      </div>
    </div>
    <div class="menu-item">Sweet-talk the alien aggressor</div>
    <div class="menu-item">Re-route power from auxiliary systems</div>
  </div>

  <div class="menu">
    <div class="menu-item">Something involving a holodeck</div>
    <div class="menu-item">Send an away team</div>
    <div class="menu-item toggler">Advanced solutions</div>
    <div class="collapsible-wrapper collapsed">
      <div class="collapsible">
        <div class="menu-item">Separate saucer</div>
        <div class="menu-item">Send an away team that includes the captain (despite Riker's protest)</div>
        <div class="menu-item">Ask Worf</div>
        <div class="menu-item">Something involving Wesley, the 19th century, and a holodeck</div>
        <div class="menu-item">Ask Q for help</div>
        <div class="menu-item">Separate saucer</div>
        <div class="menu-item">Send an away team that includes the captain (despite Riker's protest)</div>
        <div class="menu-item">Ask Worf</div>
        <div class="menu-item">Something involving Wesley, the 19th century, and a holodeck</div>
        <div class="menu-item">Ask Q for help</div>
      </div>
    </div>
    <div class="menu-item">Sweet-talk the alien aggressor</div>
    <div class="menu-item">Re-route power from auxiliary systems</div>
  </div>

</div>

Как это работает?

На самом деле в этом есть два перехода. Один из них -2000px margin-bottom от 0px (в расширенном состоянии) до -2000px в сложенном состоянии (аналогично этому ответу ). 2000 здесь - первое магическое число, оно основано на предположении, что ваш ящик не будет выше этого (2000 пикселей кажутся разумным выбором).

Одновременно с использованием перехода на посадку по отдельности возникают две проблемы:

  • Если у вас на самом деле есть ящик размером более 2000 пикселей, то margin-bottom: -2000px не скроет всего - в margin-bottom: -2000px появятся видимые вещи. Это небольшое исправление, которое мы сделаем позже.
  • Если фактическое поле, скажем, 1000 пикселей в высоту, и ваш переход длится 300 мс, то видимый переход уже завершен примерно через 150 мс (или, в противоположном направлении, начинается с опоздания на 150 мс).

Исправление этой второй проблемы - это переход к второму переходу, и этот переход концептуально нацелен на минимальную высоту оболочки («концептуально», потому что мы фактически не используем свойство min-height для этого, более подробно об этом позже).

Вот анимация, которая показывает, как объединение перехода нижнего края с минимальным переходом высоты, равным продолжительности, дает нам комбинированный переход от полной высоты к нулевой высоте, который имеет одинаковую продолжительность.

Левая панель показывает, как отрицательное нижнее поле подталкивает снизу вверх, уменьшая видимую высоту. Средняя полоса показывает, как минимальная высота гарантирует, что в свертывающемся случае переход не заканчивается на ранней стадии, а в расширяющемся случае переход не задерживается. Правая полоса показывает, как комбинация этих двух причин позволяет коробке перейти от полной высоты к нулевой высоте за правильное время.

Для моей демонстрации я установил 50px как верхнее минимальное значение высоты. Это второе магическое число, и оно должно быть ниже, чем высота окна. 50px также кажется разумным; кажется маловероятным, что вы очень часто захотите сделать элемент разборчивым, который не имеет даже 50 пикселей в высоту.

Как вы можете видеть в анимации, результирующий переход непрерывный, но он не дифференцируемый - в тот момент, когда минимальная высота равна полной высоте, скорректированной по нижнему краю, происходит внезапное изменение скорости. Это очень заметно в анимации, потому что он использует функцию линейного синхронизма для обоих переходов и потому, что весь переход происходит очень медленно. В фактическом случае (моя демонстрация сверху) переход занимает всего 300 мс, а переход нижнего края не является линейным. Я играл с множеством различных функций синхронизации для обоих переходов, и те, в которых я оказался, чувствовали, что они лучше всего подходят для самых разных дел.

Остаются две проблемы:

  1. точка сверху, где ящики с высотой более 2000 пикселей не полностью скрыты в сложенном состоянии,
  2. и обратная проблема, где в не скрытом случае коробки с высотой менее 50 пикселей слишком высоки, даже когда переход не выполняется, поскольку минимальная высота поддерживает их в 50 пикселей.

Мы решаем первую задачу, предоставляя элементу контейнера max-height: 0 в 0s 0.3s случае с переходом 0s 0.3s . Это означает, что на самом деле это не переход, но max-height применяется с задержкой; он применяется только после завершения перехода. Чтобы это правильно работало, нам также нужно выбрать числовую max-height для противоположного, не сложенного состояния. Но в отличие от случая 2000px, когда выбор слишком большого числа влияет на качество перехода, в этом случае это действительно не имеет значения. Поэтому мы можем просто выбрать число, которое настолько велико, что мы знаем, что высота никогда не приблизится к этому. Я выбрал миллион пикселей. Если вы чувствуете, что вам может потребоваться поддержка контента высотой более миллиона пикселей, тогда 1) извините, а 2) просто добавьте пару нулей.

Вторая проблема - причина, по которой мы фактически не используем min-height для минимального перехода высоты. Вместо этого в контейнере есть ::after псевдоэлемента с height которая переходит от 50px к нулю. Это имеет тот же эффект, что и min-height : он не позволит контейнеру сжиматься ниже любой высоты, которую имеет псевдоэлемент. Но поскольку мы используем height , а не min-height , теперь мы можем использовать max-height (снова применяемую с задержкой), чтобы установить фактическую высоту псевдоэлемента в ноль после завершения перехода, гарантируя, что по крайней мере за пределами переход, даже небольшие элементы имеют правильную высоту. Поскольку min-height stronger max-height , это не сработает, если мы используем min-height контейнера вместо height . Как и max-height в предыдущем абзаце, эта max-height также требует значения для противоположного конца перехода. Но в этом случае мы можем просто выбрать 50px.

Протестировано в Chrome (Win, Mac, Android, iOS), Firefox (Win, Mac, Android), Edge, IE11 (за исключением проблемы с макетом Flexbox с моей демонстрацией, которую я не беспокоил отладкой) и Safari (Mac, iOS ). Говоря о flexbox, можно сделать эту работу без использования flexbox; на самом деле, я думаю, вы могли бы заставить почти все работать в IE7 - за исключением того, что у вас не будет переходов CSS, что делает его довольно бессмысленным.


Я думаю, что я придумал действительно солидное решение

ХОРОШО!Я знаю, что эта проблема так же стара, как и Интернет, но я думаю, что у меня есть решение, которое я превратил в плагин под названием мутантный переход . Мое решение устанавливает style=""атрибуты для отслеживаемых элементов всякий раз, когда происходит изменение в DOM. конечным результатом является то, что вы можете использовать хороший ole CSS для своих переходов и не использовать хакерские исправления или специальный javascript. Единственное, что вам нужно сделать, это установить, что вы хотите отслеживать на рассматриваемом элементе data-mutant-attributes="X".

<div data-mutant-attributes="height">                                                                      
        This is an example with mutant-transition                                                                                                          
    </div>

Это оно! Это решение использует MutationObserver для отслеживания изменений в DOM. Из-за этого вам действительно не нужно ничего устанавливать или использовать javascript для ручной анимации вещей. Изменения отслеживаются автоматически. Однако, поскольку он использует MutationObserver, это будет только переход в IE11 +.

Скрипки!


Вы можете перейти с высоты: от 0 до высоты: автоматически, при условии, что вы также обеспечиваете минимальную высоту и максимальную высоту.

div.stretchy{
    transition: 1s linear;
}

div.stretchy.hidden{
    height: 0;
}

div.stretchy.visible{
    height: auto;
    min-height:40px;
    max-height:400px;
}

Ответ Джейка на оживление макс-высоты велик, но я нашел задержку, вызванную установкой большой макс-высоты, раздражающей.

Можно перемещать содержимое с возможностью разворачивания во внутренний div и вычислять максимальную высоту, получая высоту внутреннего div (через JQuery это будет внешнийHeight ()).

$('button').bind('click', function(e) { 
  e.preventDefault();
  w = $('#outer');
  if (w.hasClass('collapsed')) {
    w.css({ "max-height": $('#inner').outerHeight() + 'px' });
  } else {
    w.css({ "max-height": "0px" });
  }
  w.toggleClass('collapsed');
});

Вот ссылка jsfiddle: http://jsfiddle.net/pbatey/duZpT

Вот jsfiddle с абсолютным минимальным количеством требуемого кода: http://jsfiddle.net/8ncjjxh8/


Развернувшись на ответе @ jake, переход будет полностью соответствовать максимальному значению высоты, что приведет к чрезвычайно быстрой анимации - если вы установите переходы для обоих: hover и off, вы можете немного контролировать сумасшедшую скорость.

Таким образом, li: hover - это когда мышь входит в состояние, а переход на не-зависание будет оставить мышь.

Надеюсь, это поможет.

например:

.sidemenu li ul {
   max-height: 0px;
   -webkit-transition: all .3s ease;
   -moz-transition: all .3s ease;
   -o-transition: all .3s ease;
   -ms-transition: all .3s ease;
   transition: all .3s ease;
}
.sidemenu li:hover ul {
    max-height: 500px;
    -webkit-transition: all 1s ease;
   -moz-transition: all 1s ease;
   -o-transition: all 1s ease;
   -ms-transition: all 1s ease;
   transition: all 1s ease;
}
/* Adjust speeds to the possible height of the list */

Вот скрипка: http://jsfiddle.net/BukwJ/


Это регулярная проблема, которую я решил так

http://jsfiddle.net/ipeshev/d1dfr0jz/

Попробуйте установить задержку закрытого состояния на некоторое отрицательное число и немного сыграйте со значением. Вы увидите разницу. Его можно заставить почти лежать человеческим глазом;).

Он работает в крупных браузерах, но достаточно хорош для меня. Это странно, но дать некоторые результаты.

.expandable {
    max-height: 0px;
    overflow: hidden;
    transition: all 1s linear -0.8s;
}

button:hover ~ .expandable {
    max-height: 9000px;
    transition: all 1s ease-in-out;
}

Я не читал все подробно, но у меня была эта проблема в последнее время, и я сделал следующее:

div.class{
   min-height:1%;
   max-height:200px;
   -webkit-transition: all 0.5s ease;
   -moz-transition: all 0.5s ease;
   -o-transition: all 0.5s ease;
   -webkit-transition: all 0.5s ease;
   transition: all 0.5s ease;
   overflow:hidden;
}

div.class:hover{
   min-height:100%;
   max-height:3000px;
}

Это позволяет вам иметь div, который вначале показывает содержание до высоты 200 пикселей и при наведении его размер становится как минимум таким же высоким, как и весь контент div. Div не становится 3000px, но 3000px является пределом, который я навязываю. Убедитесь, что у вас есть переход на не-зависание, иначе вы можете получить какой-то странный рендеринг. Таким образом: hover наследуется от не-зависания.

Переход не работает в формате px на% или в auto. Вы должны использовать ту же меру измерения. Это отлично работает для меня. Использование HTML5 делает его идеальным ....

Помните, что всегда есть работа вокруг ...; )

Надеюсь, кто-то найдет это полезным


EDIT: прокрутите вниз, чтобы обновить ответ.
Я делал раскрывающийся список и видел этот пост ... много разных ответов, но я решил поделиться своим выпадающим списком тоже ... Это не идеально, но по крайней мере он будет использовать только css для падать! Я использовал transform: translateY (y), чтобы преобразовать список в представление ...
Вы можете увидеть больше в тесте
http://jsfiddle.net/BVEpc/4/
Я поместил div за каждым ли, потому что мой выпадающий список идет вверх и чтобы показать их должным образом, это было необходимо, мой код div:

#menu div {
    transition: 0.5s 1s;
    z-index:-1;
    -webkit-transform:translateY(-100%);
    -webkit-transform-origin: top;
}

и наведение:

#menu > li:hover div {
    transition: 0.5s;
    -webkit-transform:translateY(0);
}

и потому, что высота ul установлена ​​на контент, который он может получить над вашим содержимым тела, поэтому я сделал это для ul:

 #menu ul {
    transition: 0s 1.5s;
    visibility:hidden;
    overflow:hidden;
}

и наведите указатель мыши:

#menu > li:hover ul {
     transition:none;
     visibility:visible;
}

второй раз после перехода - это задержка, и он будет скрыт после того, как мой раскрывающийся список будет закрыт ...
Надеюсь, позже кто-то получит выгоду от этого.

EDIT: Я просто не могу поверить, что ppl использует этот прототип! это выпадающее меню доступно только для одного подменю, и все! Я обновил лучшую версию, которая может иметь два подменю для направления ltr и rtl с поддержкой IE 8.
Fiddle для LTR
Fiddle для RTL,
надеюсь, кто-то найдет это полезным в будущем.


Вот решение, которое я использовал только в сочетании с jQuery. Это работает для следующей структуры HTML:

<nav id="main-nav">
    <ul>
        <li>
            <a class="main-link" href="yourlink.html">Link</a>
            <ul>
                <li><a href="yourlink.html">Sub Link</a></li>
            </ul>
        </li>
    </ul>
</nav>

и функция:

    $('#main-nav li ul').each(function(){
        $me = $(this);

        //Count the number of li elements in this UL
        var liCount = $me.find('li').size(),
        //Multiply the liCount by the height + the margin on each li
            ulHeight = liCount * 28;

        //Store height in the data-height attribute in the UL
        $me.attr("data-height", ulHeight);
    });

Затем вы можете использовать функцию щелчка, чтобы установить и удалить высоту, используя css()

$('#main-nav li a.main-link').click(function(){
    //Collapse all submenus back to 0
    $('#main-nav li ul').removeAttr('style');

    $(this).parent().addClass('current');

    //Set height on current submenu to it's height
    var $currentUl = $('li.current ul'),
        currentUlHeight = $currentUl.attr('data-height');
})

CSS:

#main-nav li ul { 
    height: 0;
    position: relative;
    overflow: hidden;
    opacity: 0; 
    filter: alpha(opacity=0); 
    -ms-filter: "alpha(opacity=0)";
    -khtml-opacity: 0; 
    -moz-opacity: 0;
    -webkit-transition: all .6s ease-in-out;
    -moz-transition: all .6s ease-in-out;
    -o-transition: all .6s ease-in-out;
    -ms-transition: all .6s ease-in-out;
    transition: all .6s ease-in-out;
}

#main-nav li.current ul {
    opacity: 1.0; 
    filter: alpha(opacity=100); 
    -ms-filter: "alpha(opacity=100)";
    -khtml-opacity: 1.0; 
    -moz-opacity: 1.0;
}

.ie #main-nav li.current ul { height: auto !important }

#main-nav li { height: 25px; display: block; margin-bottom: 3px }

Используйте max-heightс различными переходами и задержкой перехода для каждого состояния.

HTML:

<a href="#" id="trigger">Hover</a>
<ul id="toggled">
    <li>One</li>
    <li>Two</li>
    <li>Three</li>
<ul>

CSS:

#toggled{
    max-height: 0px;
    transition: max-height .8s cubic-bezier(0, 1, 0, 1) -.1s;
}

#trigger:hover + #toggled{
    max-height: 9999px;
    transition-timing-function: cubic-bezier(0.5, 0, 1, 0); 
    transition-delay: 0s;
}

Пример: http://jsfiddle.net/0hnjehjc/1/


Ниже приведен способ перехода от любой начальной высоты, включая 0, к авто (полный размер и гибкость), не требуя жесткого кода на основе каждого узла или любого пользовательского кода для инициализации: https://github.com/csuwildcat/transition-auto . Я считаю, что это в основном святой Грааль, который, по вашему мнению, -> http://codepen.io/csuwldcat/pen/kwsdF . Просто удалите следующий JS-файл на свою страницу, и все, что вам нужно сделать, это добавить / удалить один логический атрибут reveal=""- из узлов, которые вы хотите развернуть и сжать.

Вот вам все, что вам нужно сделать в качестве пользователя, как только вы включите блок кода, найденный ниже кода примера:

/*** Nothing out of the ordinary in your styles ***/
<style>
    div {
        height: 0;
        overflow: hidden;
        transition: height 1s;
    }
</style>

/*** Just add and remove one attribute and transition to/from auto! ***/

<div>
    I have tons of content and I am 0px in height you can't see me...
</div>

<div reveal>
     I have tons of content and I am 0px in height you can't see me...
     but now that you added the 'reveal' attribute, 
     I magically transitioned to full height!...
</div>

Вот блок кода, который будет включен в вашу страницу, после этого все это соус:

Отбросьте этот JS-файл на своей странице - все это Just Works ™

/ * Код для высоты: авто; переход * /

(function(doc){

/* feature detection for browsers that report different values for scrollHeight when an element's overflow is hidden vs visible (Firefox, IE) */
var test = doc.documentElement.appendChild(doc.createElement('x-reveal-test'));
    test.innerHTML = '-';
    test.style.cssText = 'display: block !important; height: 0px !important; padding: 0px !important; font-size: 0px !important; border-width: 0px !important; line-height: 1px !important; overflow: hidden !important;';
var scroll = test.scrollHeight || 2;
doc.documentElement.removeChild(test);

var loading = true,
    numReg = /^([0-9]*\.?[0-9]*)(.*)/,
    skipFrame = function(fn){
      requestAnimationFrame(function(){
        requestAnimationFrame(fn);
      });
    },
    /* 2 out of 3 uses of this function are purely to work around Chrome's catastrophically busted implementation of auto value CSS transitioning */
    revealFrame = function(el, state, height){
        el.setAttribute('reveal-transition', 'frame');
        el.style.height = height;
        skipFrame(function(){
            el.setAttribute('reveal-transition', state);
            el.style.height = '';
        });
    },
    transitionend = function(e){
      var node = e.target;
      if (node.hasAttribute('reveal')) {
        if (node.getAttribute('reveal-transition') == 'running') revealFrame(node, 'complete', '');
      } 
      else {
        node.removeAttribute('reveal-transition');
        node.style.height = '';
      }
    },
    animationstart = function(e){
      var node = e.target,
          name = e.animationName;   
      if (name == 'reveal' || name == 'unreveal') {

        if (loading) return revealFrame(node, 'complete', 'auto');

        var style = getComputedStyle(node),
            offset = (Number(style.paddingTop.match(numReg)[1])) +
                     (Number(style.paddingBottom.match(numReg)[1])) +
                     (Number(style.borderTopWidth.match(numReg)[1])) +
                     (Number(style.borderBottomWidth.match(numReg)[1]));

        if (name == 'reveal'){
          node.setAttribute('reveal-transition', 'running');
          node.style.height = node.scrollHeight - (offset / scroll) + 'px';
        }
        else {
            if (node.getAttribute('reveal-transition') == 'running') node.style.height = '';
            else revealFrame(node, 'running', node.scrollHeight - offset + 'px');
        }
      }
    };

doc.addEventListener('animationstart', animationstart, false);
doc.addEventListener('MSAnimationStart', animationstart, false);
doc.addEventListener('webkitAnimationStart', animationstart, false);
doc.addEventListener('transitionend', transitionend, false);
doc.addEventListener('MSTransitionEnd', transitionend, false);
doc.addEventListener('webkitTransitionEnd', transitionend, false);

/*
    Batshit readyState/DOMContentLoaded code to dance around Webkit/Chrome animation auto-run weirdness on initial page load.
    If they fixed their code, you could just check for if(doc.readyState != 'complete') in animationstart's if(loading) check
*/
if (document.readyState == 'complete') {
    skipFrame(function(){
        loading = false;
    });
}
else document.addEventListener('DOMContentLoaded', function(e){
    skipFrame(function(){
        loading = false;
    });
}, false);

/* Styles that allow for 'reveal' attribute triggers */
var styles = doc.createElement('style'),
    t = 'transition: none; ',
    au = 'animation: reveal 0.001s; ',
    ar = 'animation: unreveal 0.001s; ',
    clip = ' { from { opacity: 0; } to { opacity: 1; } }',
    r = 'keyframes reveal' + clip,
    u = 'keyframes unreveal' + clip;

styles.textContent = '[reveal] { -ms-'+ au + '-webkit-'+ au +'-moz-'+ au + au +'}' +
    '[reveal-transition="frame"] { -ms-' + t + '-webkit-' + t + '-moz-' + t + t + 'height: auto; }' +
    '[reveal-transition="complete"] { height: auto; }' +
    '[reveal-transition]:not([reveal]) { -webkit-'+ ar +'-moz-'+ ar + ar +'}' +
    '@-ms-' + r + '@-webkit-' + r + '@-moz-' + r + r +
    '@-ms-' + u +'@-webkit-' + u + '@-moz-' + u + u;

doc.querySelector('head').appendChild(styles);

})(document);

/ * Код для DEMO * /

    document.addEventListener('click', function(e){
      if (e.target.nodeName == 'BUTTON') {
        var next = e.target.nextElementSibling;
        next.hasAttribute('reveal') ? next.removeAttribute('reveal') : next.setAttribute('reveal', '');
      }
    }, false);

Принятый ответ работает в большинстве случаев, но он не работает хорошо, когда ваш divможет сильно различаться по высоте - скорость анимации не зависит от фактической высоты содержимого, и она может выглядеть нестабильной.

Вы все равно можете выполнить фактическую анимацию с помощью CSS, но вам нужно использовать JavaScript для вычисления высоты элементов вместо того, чтобы пытаться использовать auto. Нет jQuery, хотя вам, возможно, придется немного изменить это, если вы хотите совместимости (работает в последней версии Chrome :)).

window.toggleExpand = function(element) {
    if (!element.style.height || element.style.height == '0px') { 
        element.style.height = Array.prototype.reduce.call(element.childNodes, function(p, c) {return p + (c.offsetHeight || 0);}, 0) + 'px';
    } else {
        element.style.height = '0px';
    }
}
#menu #list {
    height: 0px;
    transition: height 0.3s ease;
    background: #d5d5d5;
    overflow: hidden;
}
<div id="menu">
    <input value="Toggle list" type="button" onclick="toggleExpand(document.getElementById('list'));">
    <ul id="list">
        <!-- Works well with dynamically-sized content. -->
        <li>item</li>
        <li><div style="height: 100px; width: 100px; background: red;"></div></li>
        <li>item</li>
        <li>item</li>
        <li>item</li>
    </ul>
</div>


Решение Max-height от Jake работает хорошо, если поставляемое жестко закодированное значение максимальной высоты не намного больше реальной высоты (поскольку в противном случае возникают нежелательные задержки и проблемы времени). С другой стороны, если жестко закодированное значение случайно не превышает реальную высоту, элемент не будет полностью раскрываться.

Следующее решение только для CSS также требует жестко кодированного размера, который должен быть больше, чем большинство реальных размеров. Однако это решение также работает, если реальный размер в некоторых ситуациях превышает размер жесткого кодирования. В этом случае переход может немного перескочить, но он никогда не покинет частично видимый элемент. Таким образом, это решение может также использоваться для неизвестного контента, например, из базы данных, где вы просто знаете, что контент обычно не больше, чем x пикселей, но есть исключения.

Идея состоит в том, чтобы использовать отрицательное значение для margin-bottom (или margin-top для слегка отличной анимации) и поместить элемент контента в средний элемент с переполнением: hidden. Отрицательный край элемента контента уменьшает высоту среднего элемента.

В следующем коде используется переход на основе margin-bottom от -150px до 0px. Это само по себе прекрасно работает, пока элемент содержимого не превышает 150 пикселей. Кроме того, он использует переход на максимальную высоту для среднего элемента от 0px до 100%. Это, наконец, скрывает средний элемент, если элемент контента превышает 150 пикселей. Для max-height переход просто используется для задержки его применения на секунду при закрытии, а не для гласного визуального эффекта (и поэтому он может работать от 0px до 100%).

CSS:

.content {
  transition: margin-bottom 1s ease-in;
  margin-bottom: -150px;
}
.outer:hover .middle .content {
  transition: margin-bottom 1s ease-out;
  margin-bottom: 0px
}
.middle {
  overflow: hidden;
  transition: max-height .1s ease 1s;
  max-height: 0px
}
.outer:hover .middle {
  transition: max-height .1s ease 0s;
  max-height: 100%
}

HTML:

<div class="outer">
  <div class="middle">
    <div class="content">
      Sample Text
      <br> Sample Text
      <br> Sample Text
      <div style="height:150px">Sample Test of height 150px</div>
      Sample Text
    </div>
  </div>
  Hover Here
</div>

Значение нижней границы поля должно быть отрицательным и максимально приближенным к реальной высоте элемента контента. Если это (абсурдное значение) больше, существуют аналогичные проблемы с задержкой и временем, как с решениями максимальной высоты, которые, однако, могут быть ограничены, если размер жесткого кодирования не намного больше, чем реальный. Если абсолютное значение для нижней границы поля меньше реальной высоты, танец перепрыгивает бит. В любом случае после перехода элемент контента либо полностью отображается, либо полностью удаляется.

Более подробную информацию см. В моем сообщении в блоге http://www.taccgl.org/blog/css_transition_display.html#combined_height


Это не совсем «решение» проблемы, но более обходное решение. Он работает только как написанный с текстом, но может быть изменен для работы с другими элементами по мере необходимости. Я уверен.

.originalContent {
    font-size:0px;
    transition:font-size .2s ease-in-out;
}
.show { /* class to add to content */
    font-size:14px;
}

Вот пример: http://codepen.io/overthemike/pen/wzjRKa

По сути, вы устанавливаете размер шрифта на 0 и переходите к высоте, а не по высоте или max-height или scaleY () и т. Д. Достаточно быстро, чтобы получить высоту, чтобы преобразовать ее в нужную вам. Чтобы преобразовать фактическую высоту с помощью CSS в auto, в настоящее время невозможно, но преобразование содержимого внутри - это, следовательно, переход по размеру шрифта.

  • Примечание. В кодедере есть javascript, но цель состоит в том, чтобы добавлять / удалять классы css при нажатии на аккордеон. Это можно сделать с помощью скрытых переключателей, но я не был сосредоточен на этом, просто преобразование высоты.

Я недавно переходил max-heightна liэлементы, а не на упаковку ul.

Причиной является то, что задержка для малых max-heightsзначительно менее заметна (если вообще) по сравнению с большими max-heights, и я также могу установить max-heightзначение, отличное font-sizeот числа, liа не какого-либо произвольного огромного числа, используя emsили rems.

Если мой размер шрифта 1rem, я установлю свое max-heightна что-то вроде 3rem(для размещения завернутого текста). Здесь вы можете увидеть пример:

http://codepen.io/mindfullsilence/pen/DtzjE





css-transitions