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




анимирование высоты css (24)

Я пытаюсь сделать слайд <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>


Установите высоту в auto и перейдите на максимальную высоту.

Протестировано на Chrome v17

div {
  position: absolute;
  width:100%;
  bottom:0px;
  left:0px;

  background:#333;
  color: #FFF;

  max-height:100%; /**/
  height:auto; /**/

  -webkit-transition: all 0.2s ease-in-out;
  -moz-transition: all 0.2s ease-in-out;
  -o-transition: all 0.2s ease-in-out;
  -ms-transition: all 0.2s ease-in-out;
  transition: all 0.2s ease-in-out;
}

.close {
  max-height:0%; /**/
}

Визуальное обходное решение для анимации высоты с использованием переходов 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)


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

ХОРОШО!Я знаю, что эта проблема так же стара, как и Интернет, но я думаю, что у меня есть решение, которое я превратил в плагин под названием мутантный переход . Мое решение устанавливает 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 +.

Скрипки!


Вместо этого вы должны использовать 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/ .


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

Можно перемещать содержимое с возможностью разворачивания во внутренний 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/


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


Я знаю, что это тридцать-точный ответ на этот вопрос, но я думаю, что это того стоит, так и здесь. Это решение только для 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, что делает его довольно бессмысленным.


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

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;
}

Нет жестко закодированных значений.

Нет JavaScript.

Нет приближений.

Фокус в том, чтобы использовать скрытый и дублированный, divчтобы заставить браузер понять, что означает 100%.

Этот метод подходит, когда вы можете дублировать DOM элемента, который хотите оживить.

.outer {
  border: dashed red 1px;
  position: relative;
}

.dummy {
  visibility: hidden;
}

.real {
  position: absolute;
  background: yellow;
  height: 0;
  transition: height 0.5s;
  overflow: hidden;
}

.outer:hover>.real {
  height: 100%;
}
Hover over the box below:
<div class="outer">
  <!-- The actual element that you'd like to animate -->
  <div class="real">
unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable
content unpredictable content unpredictable content unpredictable content
  </div>
  <!-- An exact copy of the element you'd like to animate. -->
  <div class="dummy" aria-hidden="true">
unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable content unpredictable
content unpredictable content unpredictable content unpredictable content
  </div>
</div>


Используйте 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>


Вы можете, с немного не-семантического jiggery-pokery. Мой обычный подход состоит в том, чтобы анимировать высоту внешнего DIV, у которого есть единственный ребенок, который является стилем без DIV, используемым только для измерения высоты содержимого.

function growDiv() {
  var growDiv = document.getElementById('grow');
  if (growDiv.clientHeight) {
    growDiv.style.height = 0;
  } else {
    var wrapper = document.querySelector('.measuringWrapper');
    growDiv.style.height = wrapper.clientHeight + "px";
  }
}
#grow {
  -moz-transition: height .5s;
  -ms-transition: height .5s;
  -o-transition: height .5s;
  -webkit-transition: height .5s;
  transition: height .5s;
  height: 0;
  overflow: hidden;
  outline: 1px solid red;
}
<input type="button" onclick="growDiv()" value="grow">
<div id='grow'>
  <div class='measuringWrapper'>
    <div>
      The contents of my div.
    </div>
    <div>
      The contents of my div.
    </div>
    <div>
      The contents of my div.
    </div>
    <div>
      The contents of my div.
    </div>
    <div>
      The contents of my div.
    </div>
    <div>
      The contents of my div.
    </div>
  </div>
</div>

Хотелось бы просто обойтись без использования .measuringWrapper и просто установить высоту DIV в auto и создать анимацию, но это не работает (высота устанавливается, но анимации не происходит).

function growDiv() {
  var growDiv = document.getElementById('grow');
  if (growDiv.clientHeight) {
    growDiv.style.height = 0;
  } else {
    growDiv.style.height = 'auto';
  }
}
#grow {
  -moz-transition: height .5s;
  -ms-transition: height .5s;
  -o-transition: height .5s;
  -webkit-transition: height .5s;
  transition: height .5s;
  height: 0;
  overflow: hidden;
  outline: 1px solid red;
}
<input type="button" onclick="growDiv()" value="grow">
<div id='grow'>
  <div>
    The contents of my div.
  </div>
  <div>
    The contents of my div.
  </div>
  <div>
    The contents of my div.
  </div>
  <div>
    The contents of my div.
  </div>
  <div>
    The contents of my div.
  </div>
  <div>
    The contents of my div.
  </div>
</div>

Моя интерпретация заключается в том, что для запуска анимации требуется явная высота. Вы не можете получить анимацию на высоте, если высота (начальная или конечная высота) является auto .


Решение, которое я всегда использовал, должно было сначала исчезнуть, а затем уменьшить 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>


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

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,
надеюсь, кто-то найдет это полезным в будущем.


Используйте 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 до высоты: автоматически, при условии, что вы также обеспечиваете минимальную высоту и максимальную высоту.

div.stretchy{
    transition: 1s linear;
}

div.stretchy.hidden{
    height: 0;
}

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

Я смог это сделать. У меня есть .child& .parentdiv. Детский div идеально вписывается в ширину / высоту родителя с absoluteпозиционированием. Затем я анимирую translateсвойство, чтобы подтолкнуть его Yзначение вниз 100%. Его очень гладкая анимация, никаких сбоев или нисходящих сторон, как любое другое решение здесь.

Что-то вроде этого, псевдокод

.parent{ position:relative; overflow:hidden; } 
/** shown state */
.child {
  position:absolute;top:0;:left:0;right:0;bottom:0;
  height: 100%;
  transition: transform @overlay-animation-duration ease-in-out;
  .translate(0, 0);
}

/** Animate to hidden by sliding down: */
.child.slidedown {
  .translate(0, 100%); /** Translate the element "out" the bottom of it's .scene container "mask" so its hidden */
}

Вы бы указать heightна .parent, в px, %или оставить как auto. Затем этот div маскирует .childdiv, когда он скользит вниз.


Моим обходным путем является переход max-height в точную высоту контента для приятной гладкой анимации, а затем использовать обратный вызов transitionEnd для установки max-height до 9999px, чтобы контент мог свободно изменять размер.

var content = $('#content');
content.inner = $('#content .inner'); // inner div needed to get size of content when closed

// css transition callback
content.on('transitionEnd webkitTransitionEnd transitionend oTransitionEnd msTransitionEnd', function(e){
    if(content.hasClass('open')){
        content.css('max-height', 9999); // try setting this to 'none'... I dare you!
    }
});

$('#toggle').on('click', function(e){
    content.toggleClass('open closed');
    content.contentHeight = content.outerHeight();
    
    if(content.hasClass('closed')){
        
        // disable transitions & set max-height to content height
        content.removeClass('transitions').css('max-height', content.contentHeight);
        setTimeout(function(){
            
            // enable & start transition
            content.addClass('transitions').css({
                'max-height': 0,
                'opacity': 0
            });
            
        }, 10); // 10ms timeout is the secret ingredient for disabling/enabling transitions
        // chrome only needs 1ms but FF needs ~10ms or it chokes on the first animation for some reason
        
    }else if(content.hasClass('open')){  
        
        content.contentHeight += content.inner.outerHeight(); // if closed, add inner height to content height
        content.css({
            'max-height': content.contentHeight,
            'opacity': 1
        });
        
    }
});
.transitions {
    transition: all 0.5s ease-in-out;
    -webkit-transition: all 0.5s ease-in-out;
    -moz-transition: all 0.5s ease-in-out;
}

body {
    font-family:Arial;
    line-height: 3ex;
}
code {
    display: inline-block;
    background: #fafafa;
    padding: 0 1ex;
}
#toggle {
    display:block;
    padding:10px;
    margin:10px auto;
    text-align:center;
    width:30ex;
}
#content {
    overflow:hidden;
    margin:10px;
    border:1px solid #666;
    background:#efefef;
    opacity:1;
}
#content .inner {
    padding:10px;
    overflow:auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<div id="content" class="open">
    <div class="inner">
        <h3>Smooth CSS Transitions Between <code>height: 0</code> and <code>height: auto</code></h3>
        <p>A clever workaround is to use <code>max-height</code> instead of <code>height</code>, and set it to something bigger than your content. Problem is the browser uses this value to calculate transition duration. So if you set it to <code>max-height: 1000px</code> but the content is only 100px high, the animation will be 10x too fast.</p>
        <p>Another option is to measure the content height with JS and transition to that fixed value, but then you have to keep track of the content and manually resize it if it changes.</p>
        <p>This solution is a hybrid of the two - transition to the measured content height, then set it to <code>max-height: 9999px</code> after the transition for fluid content sizing.</p>
    </div>
</div>

<br />

<button id="toggle">Challenge Accepted!</button>


Принятый ответ работает в большинстве случаев, но он не работает хорошо, когда ваш 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>


Я понимаю, что эта ветка стареет, но она высоко ценится в некоторых поисковых системах Google, поэтому я считаю, что ее стоит обновить.

Вы также просто получаете / устанавливаете собственную высоту элемента:

var load_height = document.getElementById('target_box').clientHeight;
document.getElementById('target_box').style.height = load_height + 'px';

Вы должны сбросить этот Javascript сразу после закрывающего тега target_box во встроенном теге скрипта.


Поскольку я публикую это, есть уже более 30 ответов, но я чувствую, что мой ответ улучшается по уже принятому ответу Джейком.

Я не был доволен проблемой, которая возникает из-за простого использования max-heightи переходов CSS3, поскольку, как отмечали многие комментаторы, вы должны установить свою max-heightценность очень близко к фактической высоте или вы получите задержку. См. Этот JSFiddle для примера этой проблемы.

Чтобы обойти это (пока не используете JavaScript), я добавил еще один элемент HTML, который transform: translateYпереводит значение CSS.

Это означает, что оба max-heightи translateYиспользуются: max-heightпозволяет элементу выталкивать элементы под ним, а также translateYдает «мгновенный» эффект, который мы хотим. Проблема max-heightвсе еще существует, но ее эффект уменьшается. Это означает, что вы можете установить гораздо большую высоту для своей max-heightценности и меньше беспокоиться об этом.

Общая выгода заключается в том, что при переходе назад (коллапсе) пользователь сразу видит translateYанимацию, поэтому на самом деле не имеет значения, сколько времени max-heightзанимает.

Решение как скрипка

body {
  font-family: sans-serif;
}

.toggle {
  position: relative;
  border: 2px solid #333;
  border-radius: 3px;
  margin: 5px;
  width: 200px;
}

.toggle-header {
  margin: 0;
  padding: 10px;
  background-color: #333;
  color: white;
  text-align: center;
  cursor: pointer;
}

.toggle-height {
  background-color: tomato;
  overflow: hidden;
  transition: max-height .6s ease;
  max-height: 0;
}

.toggle:hover .toggle-height {
  max-height: 1000px;
}

.toggle-transform {
  padding: 5px;
  color: white;
  transition: transform .4s ease;
  transform: translateY(-100%);
}

.toggle:hover .toggle-transform {
  transform: translateY(0);
}
<div class="toggle">
  <div class="toggle-header">
    Toggle!
  </div>
  <div class="toggle-height">
    <div class="toggle-transform">
      <p>Content!</p>
      <p>Content!</p>
      <p>Content!</p>
      <p>Content!</p>
    </div>
  </div>
</div>

<div class="toggle">
  <div class="toggle-header">
    Toggle!
  </div>
  <div class="toggle-height">
    <div class="toggle-transform">
      <p>Content!</p>
      <p>Content!</p>
      <p>Content!</p>
      <p>Content!</p>
    </div>
  </div>
</div>


Здесь мало упоминалось Element.scrollHeightсвойство, которое может быть полезно здесь и все еще может использоваться с чистым переходом CSS. Свойство всегда содержит «полную» высоту элемента, независимо от того, как и как его содержимое переполняется в результате свернутой высоты (например, height: 0).

Таким образом, для height: 0(фактически полностью свернутого) элемента его «нормальная» или «полная» высота по-прежнему доступна через его scrollHeightзначение (неизменно длина пикселя ).

Для такого элемента, предполагая, что он уже имеет переход, подобный, например, (используя ulв соответствии с исходным вопросом):

ul {
    height: 0;
    transition: height 1s; /* An example transition. */
}

Мы можем вызвать желаемое анимированное «расширение» высоты, используя только CSS, с чем-то вроде следующего (здесь предполагается, что ulпеременная относится к списку):

ul.style.height = ul.scrollHeight + "px";

Вот и все. Если вам нужно свернуть список, сделайте одно из двух следующих утверждений:

ul.style.height = "0";
ul.style.removeProperty("height");

Мой конкретный случай использования вращался вокруг анимации списков неизвестных и часто значительных длин, поэтому мне было неудобно устанавливать произвольное «достаточно большое» heightили max-heightспецификацию и рисковать срезанным контентом или контентом, который вам внезапно нужно прокрутить (если overflow: auto, например) , Кроме того, ослабление и синхронизация нарушаются с помощью max-heightрешений на основе, потому что используемая высота может достигать своего максимального значения намного раньше, чем требуется для max-heightдостижения 9999px. И по мере того, как разрешение экрана растет, пиксельные длины, как, 9999pxоставляют плохой вкус во рту. Это конкретное решение, на мой взгляд, решает проблему элегантным образом.

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


Развернувшись на ответе @ 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/


Ниже приведен способ перехода от любой начальной высоты, включая 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);




css-transitions