Як можна перевести висоту переходу: 0; по висоті: авто; за допомогою CSS?


2134

Я намагаюся зробити <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>


Я вважаю, що height:auto/max-heightрішення працюватиме лише в тому випадку, якщо ви розширюєте площу більше, ніж heightхочете обмежити. Якщо у вас є max-heightз 300px, але випадають розкриваються, який може повернутися 50px, то max-heightне допоможуть, 50pxможе змінюватися в залежності від кількості елементів, ви можете прийти до безвихідної ситуації , коли я не можу це виправити , тому що heightНЕ виправлено, height:autoбуло рішенням, але я не можу використовувати переходи з цим.
Крістофер Томас

51
ОП намагається вирішити css, а не js, інакше вони можуть просто використовувати переповнення та анімувати
Toni Leigh

5
@VIDesignz: Але внутрішній поділ -100% -ний запас вершини отримує ширину оболонки, а не висоту. Тож це рішення має таку ж проблему, що і рішення максимальної висоти. Більше того, коли ширина менша за висоту вмісту, не весь вміст приховано на -100% відрив. Тож це неправильне рішення.
GregTom

1
Див. Github.com/w3c/csswg-drafts/isissue/626 для обговорення специфіки та впровадження правильного рішення
Бен Крізі

Відповіді:


2745

Використовувати max-heightв переході і ні height. І встановіть значення на max-heightщось більше, ніж коли-небудь отримає ваш ящик.

Дивіться демонстрацію JSFiddle, представлену Крісом Джорданом, в іншій відповіді тут.

#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>


323
це чудово працює! за винятком затримки, коли вона починається, тому що вона починається з максимальної висоти, яка спочатку дуже висока ... хм, я думаю, це дещо дратує
vsync

175
+1 Відмінне рішення! Швидкість переходу обчислюється як час, який ви визначаєте для переходу до значення максимальної висоти ... але оскільки висота буде меншою, ніж максимальна висота, перехід на фактичну висоту відбудеться швидше (часто значно), ніж вказаний час.
Кінгджефрі

50
Зауважте, що це може спричинити закінчення негарного переходу, коли вам доведеться використовувати значення, які набагато перевищують фактичне обчислене значення. Я помітив це під час спроби змусити Діва зрости з 0 висоти до висоти вмісту, яка сильно змінюється в залежності від різних розмірів екрана (2 рядки на моєму моніторі 2560x1440 проти> 10 рядків на смартфоні). Для цього я в кінцевому рахунку з js.
jpeltoniemi

44
Дуже потворне рішення, оскільки створює затримку в одному напрямку, але не в іншому.
Тім

84
Це досить ледаче рішення. Я припускаю, що OP хоче використовувати висоту: auto, оскільки розширена висота контейнера дещо непередбачувана. Це рішення спричинить затримку до того, як анімація стане видимою. Крім того, видима тривалість анімації буде непередбачуваною. Ви отримаєте набагато більш передбачувані (і, ймовірно, більш плавні) результати, обчисливши комбіновану висоту кожного з дочірніх вузлів контейнерів, а потім полегшивши їх до точного значення висоти.
Шон Віннірі

314

Натомість слід використовувати scaleY.

ul {
  background-color: #eee;
  transform: scaleY(0);    
  transform-origin: top;
  transition: transform 0.26s ease;
}
p:hover ~ ul {
  transform: scaleY(1);
}
<p>Hover This</p>
<ul>
  <li>Coffee</li>
  <li>Tea</li>
  <li>Milk</li>
</ul>

Я створив постачальникову версію вищевказаного коду на jsfiddle і змінив вашу jsfiddle на використання scaleY замість висоти.


6
Я підтримую цю відповідь, тому що вона добре працює в браузерах, здатних до переходу css3, але слід зазначити, що це не буде працювати взагалі в IE <9 , а в IE <10 не буде анімовано (воно просто стрибне)
Гейлвуд

215
Цей метод лише частково досягає бажаного ефекту, але фактично не видаляє простір. Трансформована коробка діє як відносно розташований елемент - простір займає незалежно від того, як воно масштабується. Ознайомтеся з цим jsFiddle, який бере ваш перший і просто додає якийсь хибний текст внизу. Зверніть увагу, як текст під ним не рухається вгору, коли висота поля зменшується до нуля.
animuson

9
Тепер це робиться: jsfiddle.net/gNDX3/1 В основному вам потрібно стилювати елементи відповідно до того, що вам потрібно. У CSS / HTML немає такої срібної кулі чи віджета, як така.
dotnetCarpenter

70
Хоча я аплодую комусь, хто пробує різні підходи, ефект у реальному світі та ускладнення приносить це рішення набагато гірше, ніж і без того жахливий зліт на максимальній висоті. Будь ласка, не використовуйте.
mystrdat

2
@SquareCat все гаразд добре. Ось такий варіант, який виглядає більше, як: jsfiddle.net/dotnetCarpenter/WTL2r
dotnetCarpenter

202

Наразі ви не можете анімувати на висоті, коли одна із задіяних висот auto, ви повинні встановити дві явні висоти.


12
Зазвичай існує кілька способів вирішити проблему, і не всі вони є відповідними або можливими. Я не знаю, чому @JedidiahHurt і Райан Руда намагаються обмежити можливі відповіді на веб-сайті Q&A. Особливо враховуючи, що ця відповідь була тут першою. Двічі так, оскільки прийнята відповідь є вирішувальною.
Hooray Im Helping

5
Відповідь від @jake не є ні елегантною, ні правильною. Тут пов'язана відповідь набагато краща. Він працює правильно і обробляє всі випадки розміру - про прийняту відповідь не можна сказати.
GraphicsMuncher

5
Так: такthis.$element[dimension](this.$element[dimension]())[0].offsetHeight
Енді,

4
Чи планується це якось виправити? Я маю на увазі, це цілком природно очікувати на можливість переходу від 0 висоти до auto...
Августин Рідінгер

6
@Meliodas "ні / ти не можеш" - це коректна і прийнятна відповідь на питання щодо переповнення стека.
TylerH

122

Рішення , яке я завжди був першим Fade Out, а потім стиснути font-size, paddingі marginзначення. Це не так, як wipe, але працює без статичного 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>


Працювали акуратно для мене. Не зовсім як jQuery slideUp / Down. Ви можете помітити різницю лише у слабких процесорах, як-от старих комп'ютерах або мобільних пристроях, і відкривати та закривати багато з них одночасно.
Крус Нуньєс

3
Якщо у вас є кнопки або будь-які інші нетекстові елементи, у вас з’явиться небажаний пробіл, не зависаючи.
Денніс Ш

3
Ви можете вдосконалити її, вибравши всі дочірні елементи за допомогою *та застосувавши інші зміни. Однак кнопки повинні були впливати на мій вище код, якщо вони були правильно оформлені em.
Стівен Вачон

1
У моєму випадку мені також потрібно було додати line-height: 0;іborder-width: 0;
Андрій Шатілов

1
Вам не потрібно коригувати, line-heightякщо ви правильно уникаєте одиниць за значенням: developer.mozilla.org/en-US/docs/Web/CSS/…
Стівен Вахон

93

Я знаю, що це тридцять щось відповідь на це питання, але я вважаю, що воно того варте, тому ось що. Це єдине CSS- рішення з такими властивостями:

  • На початку немає затримки, і перехід не припиняється рано. В обох напрямках (розширення та згортання), якщо ви вказали тривалість переходу у вашій CSS, тривалість переходу становить 300 мс, період.
  • Це перехід фактичної висоти (на відміну від 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>

Як це працює?

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

Використання margin-bottomпереходу в поодинці сам по собі має два питання:

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

Виправлення цього другого питання полягає в тому, де відбувається другий перехід, і цей перехід концептуально орієнтований на мінімальну висоту обгортки ("концептуально", оскільки ми фактично не використовуємо min-heightвластивість для цього; докладніше про це пізніше).

Ось анімація, яка показує, як поєднання переходу нижньої межі з мінімальним переходом на висоту, обидва однакової тривалості, дає нам комбінований перехід від повної висоти до нульової висоти, що має однакову тривалість.

анімація, як описано вище

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

Для демонстрації я встановив 50px як верхнє значення мінімальної висоти. Це друге магічне число, і воно повинно бути нижчим, ніж висота поля. 50px також здається розумним; здається малоймовірним, що вам дуже часто хочеться зробити елемент розбірним, який у першу чергу не має навіть 50 пікселів.

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

Для вирішення залишаються дві проблеми:

  1. точка зверху, де поля з висотою понад 2000 пікселів не повністю заховані в згорнутому стані,
  2. і зворотна проблема, коли в не прихованому випадку вікна розміром менше 50 пікселів занадто високі, навіть коли перехід не виконується, оскільки мінімальна висота підтримує їх у 50 пікселів.

Першу задачу ми вирішуємо, надаючи контейнерному елементу a max-height: 0у згорнутому випадку з 0s 0.3sпереходом. Це означає, що це насправді не перехід, але max-heightзастосовується із запізненням; він застосовується лише після закінчення переходу. Для правильної роботи нам також потрібно вибрати число max-heightдля протилежного стану, що не згортається. Але на відміну від випадку 2000px, коли вибір занадто великої кількості впливає на якість переходу, в цьому випадку це насправді не має значення. Тож ми можемо просто вибрати таке високе число, що знаємо, що жодна висота ніколи не наблизиться до цього. Я вибрав мільйон пікселів. Якщо ви вважаєте, що вам може знадобитися підтримувати вміст висотою понад мільйон пікселів, то 1) Вибачте, і 2) просто додайте пару нулів.

Друга проблема - причина, по якій насправді ми не використовуємо min-heightдля переходу мінімальної висоти. Натомість ::afterу контейнері є псевдоелемент, heightякий переходить з 50px до нуля. Це має такий же ефект, як і min-height: Це не дозволить контейнеру скорочуватися нижче, на яку висоту має псевдоелемент. Але оскільки ми використовуємо height, ні min-height, ми тепер можемо використовувати max-height(вкотре застосований із запізненням) для встановлення фактичної висоти псевдоелемента до нуля, коли перехід закінчиться, гарантуючи, що принаймні поза переходом навіть маленькі елементи мають правильна висота. Тому що min-heightце сильніше , ніж 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 ). Говорячи про флексокс, слід зробити це можливим без використання будь-якого флексбоксу; насправді я думаю, ви могли б змусити майже все працювати в IE7 - за винятком того, що у вас не буде CSS переходів, що робить це досить безглуздою вправою.


35
Я б хотів, щоб ви могли скоротити (спростити) своє рішення або хоча б приклад коду - схоже, що 90% прикладу коду не стосується вашої відповіді.
Гіл Епштейн

Чи є спосіб, щоб ці переходи також спрацьовували, якщо collapsible-wrapperпозиція має абсолютну позицію. На overflow: hiddenбатьківщині потрібен перехід, але заважає абсолютно розміщеним елементам.
pmkro

1
@pmkro Так, у мене теж була ця проблема. Я вирішив це, використовуючи clip-path: polygon(...)замість цього overflow: hidden, тому що на відміну від останнього, ви можете перейти на перший. Як резервний варіант для старих браузерів я використав додаткову трансформацію масштабування. Дивіться коментар у верхній частині github.com/StackExchange/Stacks/blob/develop/lib/css/components/…
balpha

2
Приємно. Це працює дуже добре. Має бути прийнята відповідь
Генріх Інг-Сіммонс

83

Ви можете з трішки несемантичного джиггери-покеру. Мій звичайний підхід - анімувати висоту зовнішнього 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 на автоматичну функцію, і це анімувати, але це, здається, не працює (висота встановлюється, але анімація не відбувається).

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.


10
Оскільки це покладається на JavaScript, ви також можете легко додати вимірювальну обгортку, використовуючи і javascript!
Quickredfox

18
Ви можете це зробити без обгортки. Просто: функція rasteDiv () {var зростанняDiv = document.getElementById ('рости'); if (rasteDiv.clientHeight) {зростанняDiv.style.height = 0; } else {rasteDiv.style.height = зростанняDiv.scrollHeight + 'px'; }}
користувач1742529

8
Перевірте це ... поговоріть про просту відповідь jsfiddle.net/n5XfG/2596 ... Ваша відповідь шалено складна без поважних причин. Не потрібно max-height, не потрібно auto, а особливо не потрібно Javascript !! Всього дві прості декларації
VIDesignz

12
@VIDesignz Ви анімуєте понад маржу: 100%. Це на 100% ширина елемента, а не його висота! Це означає, що якщо у вас елемент з висотою, більшою за його ширину, це не приховає. Також реальна швидкість анімації абсолютно інша, ніж визначена.
Тімо Тюршман

3
Я був схвильований відповіддю VIDesignz, поки не прочитав більше про коментар Тімо. Так, margin-topmargin-bottom) відносно ширини, коли їх визначають у відсотках, так, це нерозумно, але це також пояснює, чому відкриті та закриті терміни анімації зовсім інші - це те саме, що ви бачите у відповіді з високим рейтингом, вказуючи важкий -кодована максимальна висота. Чому це так важко зробити правильно?
Кодерер

52

Візуальне вирішення анімації висоти за допомогою переходів 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/ (викреслений з Stephband вище jsFiddle)


3
Я думаю, що це найкраща відповідь. Ця техніка може поширюватися і на коригування накладки на дітей. У моєму випадку мені вдалося поєднати це з явними переходами висоти на деякий вміст, що розкривається, і загальний ефект набагато успішніший, ніж обробка максимальної висоти, що чудово підходить для виявлення, але вводить незручний момент затримка на приховування. Я швидше взагалі не анімую, ніж запроваджую безглузді затримки, які змушують мою програму не відповідати. Я здивований, що багато людей, здається, вважають це прийнятним.
Півколо

17
За винятком того, що тут ви взагалі не анімуєте висоту. Ви оживляєте прокладку ... вона може просто зникнути, оскільки може анімувати з поточного стану до 0, але якщо уважно спостерігати, коли вона розгортається, вона відкривається разом із текстом, а потім прокладка лише оживляє .. тому що це не Я не знаю, як анімувати від 0 до авто .... йому потрібен числовий діапазон ... ось як працює твінінг.
Роб Р

Це хороший спосіб вирішення, який не хакі. Це не найкраща відповідь на це питання, але це альтернатива, яка працювала для мене. Іноді просто потрібен ефект деякої анімації по висоті, а не повна анімація :)
Іван Дерст

Це рішення також виходить з ладу при використанні затримки переходу.
Мішель Джоаніс

Я також погоджуюся, що це рішення - це чисте вирішення, яке забезпечує досить плавні переходи, якщо ваша анімація є досить швидкою (у моєму випадку для акордеона з переходами 0,1 с це ідеально!). Хоча це не дуже багато додатків, але і інші прихильники цього питання не будуть!
Ремі D

46

Моє вирішення полягає в переході максимальної висоти до точної висоти вмісту для приємної плавної анімації, потім використовуйте зворотний виклик перемикання, щоб встановити максимальну висоту до 9999 пікселів, щоб вміст міг вільно змінювати розмір.

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>


14
@ Derija93 Це використання звичайних старих анімацій JavaScript таймауту. Завдання полягає в тому, щоб використовувати замість CSS3 переходи.
Адам

3
Ну так. Але чому б ви замість цього використовували "CSS3 переходи", якщо у вашому прикладі ви вже використовуєте jQuery, бібліотеку, яка надає багато коду "писати менше, робити більше"? Я хотів би зазначити, що ваша версія може виглядати набагато краще, хоч і складніше, якби вона НЕ використовувала jQuery, щоб вона могла працювати практично на будь-якому веб-сайті. Я думаю, я сформулював це сильно неправильно. Вибачте, але це. ;)
Кірусе

27
@ Derija93 Можливо тому, що переходи CSS3 мають (за всіма джерелами, які я можу знайти) набагато кращу продуктивність, ніж анімації jQuery. (Насправді це дуже важливо для мого поточного випадку використання, який привів мене сюди.)
Марк Амерді

4
@ Derija93 'Тому, що анімації Javascript запускаються повільно порівняно з CSS3 переходами bro, а з анімаціями jQuery вам потрібно потурбуватися про цикл анімації. Анімуйте щось при натисканні, а потім швидко натисніть і спостерігайте, як анімації повторюються. Це обробляється за допомогою CSS3.
AlbertEngelB

2
@ Dropped.on.Caprica Це вже трохи старе. Я вже сказав, що я неправильно зрозумів концепцію, яку він намагався продемонструвати. У будь-якому випадку, для простих анімацій, .stopце хитрість для досить складної проблеми циклу анімації. Тепер, коли ви оживляєте висоту та кольори, але хочете лише перервати анімацію висоти, речі стають трохи хитрішими ... Я розумію.
Кірусе

43

Прийнята відповідь працює в більшості випадків, але вона не спрацьовує добре, коли ваш показник 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>


Це може бути корисним, але я не можу сказати, тому що не знаю, як це використати без кращого прикладу.
Іван Дерст

1
Ви просто передаєте будь-який елемент DOM (наприклад, з document.getElementById('mydiv')або $('#mydiv').get()), і функція перемикається між його приховуванням / показом. Якщо встановити переходи CSS, елемент буде анімуватись автоматично.
Олег Васкевич

Я додав фрагмент. Це має перевагу в тому, що добре працювати з динамічним розміром вмісту.
Олег Васкевич

3
-1, оскільки це не "використання CSS". Суть питання полягає у вирішенні проблеми без JS. Я думаю, що "правильна" відповідь, це не злом, буде це, хоча ...
dudewad

16
Зниження на використання JS - серйозно? Половина відповідей тут використовує JS, тож ваш голос не здається справедливим чи необхідним. Крім того, ця відповідь досі використовує CSS для виконання реальної анімації, що ІМО було точкою ОП. Єдине, для чого використовується JS, - це обчислити фактичну висоту, оскільки це неможливо зробити за допомогою чистого CSS (а встановлення, min-heightяк у очікуваній відповіді, спричиняє проблеми зі швидкістю анімації, коли розмір списку може сильно відрізнятися).
Олег Васкевич

30

Мало згадувалося про 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(які в даний час отримують трохи спеціального лікування).


6
Ви не знайшли його в інших відповідях тут, оскільки для взаємодії з DOM за допомогою Element.scrollHeightвластивості потрібен JavaScript, і, як чітко сказано в питанні, вони хочуть зробити це без JavaScript.
TylerH

3
Існує безліч інших частин CSS, крім тих двох псевдокласів, які можуть вирішити цю проблему, як показують відповіді з найбільшою оцінкою на сторінці 1. Встановлення стилю в JavaScript не є "чистим CSS", оскільки він вимагає встановлення JS в першу чергу. Часто, коли людина запитує рішення, що стосується лише CSS, це відбувається тому, що вони не в змозі вводити JavaScript або заборонено діючим проектом чи роллю.
TylerH

29

Використовувати 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/


12
Проблема тут полягає в тому, щоб забезпечити достатньо місця в динамічному середовищі, потрібно використовувати смішні максимальні висоти на зразок 999999px. Це, з іншого боку, змістить вашу анімацію, оскільки кадри обчислюються з цього значення. Таким чином, ви можете закінчити анімацію "затримка" в одному напрямку і дійсно швидкий кінець в інший бік (corr: тимчасові функції)
Julian F. Weinert

29

Немає твердо кодованих значень.

Немає 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 є базовою, якщо перехід не встановлено на "лінійний", це також (очевидно) дуже погано для анімації вмісту CMS, де висота є змінною.
M_Willett

це розумно, але мені не буде зручно дублювати елементи DOM та вміст для цього.
Andre Figueiredo

Ви можете зробити це без контейнера та більш ефективної, анімацією transform: scaleY(1), оскільки цей перехід не видаляє простір.
Фабіан фон Еллертс

21

Коли я публікую це, вже є понад 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>


Приємне порівняння @davidtaubmann, ваша ручка дуже добре ілюструє відмінності! Я пішов з translateYнад, scaleтому що мені не сподобалося, як це scaleдало ефект стиснення.
Ендрю Мессьє

Дякую @ andrew-messier, я видалив коментар, тому що є помилка, перекладатиY не виходить у codepen.io/davidtaubmann/pen/zKZvGP (тому що немає дитини, яка б рухалася, потребує виправлення) ... але в цьому ми можемо чудово бачити порівняння ТІЛЬКИ МАКС-ВИСОК і змішуючи його зі шкалою (як зазначено в інших відповідях): codepen.io/davidtaubmann/pen/jrdPER . Все це мені дуже допомогло з використанням цільової методології, яку я використовую
DavidTaubmann

18

Гаразд, тому я думаю, що я придумав надзвичайно просту відповідь ... ні max-height, використовує relativeпозиціонування, працює над liелементами, і чистий CSS. Я не тестував нічого, окрім Firefox, хоч судячи з CSS, він повинен працювати у всіх браузерах.

ПОМОТЬ: http://jsfiddle.net/n5XfG/2596/

CSS

.wrap { overflow:hidden; }

.inner {
            margin-top:-100%;
    -webkit-transition:margin-top 500ms;
            transition:margin-top 500ms;
}

.inner.open { margin-top:0px; }

HTML

<div class="wrap">
    <div class="inner">Some Cool Content</div>
</div>

13
Це буде працювати, поки висота елемента не перевищить його ширину. Це основа, як розраховуються маржі з використанням відсотків: вони обчислюються виходячи з ширини елемента. Отже, якщо у вас є елемент шириною 1000 пікселів, то елемент у 1100 пікселів буде занадто великим, щоб це рішення працювало, це означає, що вам доведеться збільшити цей негативний верхній запас. В основному, це абсолютно та сама проблема, як використання висоти або максимальної висоти.
dudewad

15

EDIT: Прокрутіть униз до оновленої відповіді.
Я робив випадаючий список і побачив цю публікацію ... багато різних відповідей, але я вирішу поділитися і моїм спадному списку, ... Це не ідеально, але принаймні для цього буде використовувати лише css для падіння вниз! Я використовував transform: translateY (y) для перетворення списку у вигляд ... Більше
ви можете побачити в тесті
http://jsfiddle.net/BVEpc/4/
Я розмістив div за кожним li, тому що мій випадаючий список надходить із верхнього списку та щоб правильно їх показати, мій код 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 for LTR
Fiddle for RTL
сподіваємось, хтось вважає це корисним у майбутньому.


11

Ви можете переходити від висоти: 0 до висоти: автоматично, якщо ви також надаєте мінімальну та максимальну висоту.

div.stretchy{
    transition: 1s linear;
}

div.stretchy.hidden{
    height: 0;
}

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

@Stuart Badminton Ви можете надати робочий приклад? Я зібрав це разом, але, схоже, ніде не працює :( jsfiddle.net/gryzzly/n5XfG
Misha Reyzlin

5
Проблема полягає у вашому правилі переходу. щоб змусити його працювати, потрібно також застосувати перехід до min та max висоти. перехід: висота .5с лінійна, мінімальна висота .5с лінійна, максимальна висота .5с лінійна
Стюарт Бадмінтон

2
ось що мені пізніше, як і ви сказали, потрібно анімувати максимальну висоту: jsfiddle.net/gryzzly/n5XfG/3
Міша Рейзлін

11
Звичайно, в цьому є проблема. Час, необхідний для анімації max-height, - це не час, який потрібно для переходу до автоматичної висоти поля: він досягає висоти: спочатку автоматично, перш ніж max-height закінчився анімацією. Аналогічно, при переході до 0 перехід починається не відразу, оскільки максимальна висота починається з висоти, більшої від висоти: авто. Перехід на максимальну висоту: 1000px робить це зрозумілим: jsfiddle.net/n5XfG/11
stephband

Ви маєте рацію, при подальшому тестуванні я це помітив. Я не знаю, чи буде реалізовано коли-небудь повний зріст: 0 до висоти: автоматично, але використання максимальної висоти в деяких ситуаціях вирішує інакше неможливу ситуацію, використовуючи лише CSS.
Стюарт Бадмінтон

10

Рішення Flexbox

Плюси:

  • простий
  • немає JS
  • плавний перехід

Мінуси:

  • елемент потрібно помістити в гнучку ємність з фіксованою висотою

Як це працює, завжди має flex-основу: автоматично на елементі зі змістом, а замість цього переходить flex-raste та flex-shrink.

Редагувати: Покращений JS Fiddle, натхненний інтерфейсом Xbox One.

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  transition: 0.25s;
  font-family: monospace;
}

body {
  margin: 10px 0 0 10px;
}

.box {
  width: 150px;
  height: 150px;
  margin: 0 2px 10px 0;
  background: #2d333b;
  border: solid 10px #20262e;
  overflow: hidden;
  display: inline-flex;
  flex-direction: column;
}

.space {
  flex-basis: 100%;
  flex-grow: 1;
  flex-shrink: 0;    
}

p {
  flex-basis: auto;
  flex-grow: 0;
  flex-shrink: 1;
  background: #20262e;
  padding: 10px;
  width: 100%;
  text-align: left;
  color: white;
}

.box:hover .space {
  flex-grow: 0;
  flex-shrink: 1;
}
  
.box:hover p {
  flex-grow: 1;
  flex-shrink: 0;    
}
<div class="box">
  <div class="space"></div>
  <p>
    Super Metroid Prime Fusion
  </p>
</div>
<div class="box">
  <div class="space"></div>
  <p>
    Resident Evil 2 Remake
  </p>
</div>
<div class="box">
  <div class="space"></div>
  <p>
    Yolo The Game
  </p>
</div>
<div class="box">
  <div class="space"></div>
  <p>
    Final Fantasy 7 Remake + All Additional DLC + Golden Tophat
  </p>
</div>
<div class="box">
  <div class="space"></div>
  <p>
    DerpVille
  </p>
</div>

JS Fiddle


7

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

Отже, 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/


1
Я не знаю, чому це отримало -1. Насправді я вважаю, що це краща спроба, ніж хтось із людей, що додають набір JavaScript. Це не ідеальне рішення, але за допомогою певного налаштування це добре справляється, я виявив, що це працює для повернення значення. перехід: усі 500мб куб-безьє (0,000, 1,225, 0,085, 0,385); Це ґрунтувалося на переході 2s при відкритті, а потім вищевказаному коді, щоб повернутися до початкового стану. Дякую ... Це допомогло мені краще за все вищезазначене. +1 Я використовував цей сайт, щоб створити bezier matthewlein.com/ceaser
gcoulby

Добре, це зайняло трохи більше налаштування. перехід: усі 500мб кубічно-безьє (0,000, 1,390, 0,000, 0,635); Я повинен зазначити, що мій перехід йде від 5% -100% (але насправді кінцеве значення становить близько 28%), тому це залежить від проекту.
gcoulby

Абсолютно, це не ідеально, але це швидке виправлення, якщо ви знаєте круглі місця, яким буде середній зріст.
jamie

7

Я думаю, що я придумав дійсно міцне рішення

ДОБРЕ! Я знаю, що ця проблема стара, як Інтернет, але я думаю, що у мене є рішення, яке я перетворив на плагін під назвою мутант-перехід . Моє рішення встановлює style=""атрибути відслідковуваних елементів щоразу, коли відбувається зміна DOM. кінцевим результатом є те, що ви можете використовувати хороший CSS для своїх переходів і не використовувати хакі-виправлення чи спеціальний JavaScript. Єдине, що вам потрібно зробити - це встановити те, що ви хочете відслідковувати на розглянутому елементі data-mutant-attributes="X".

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

Це воно! Це рішення використовує MutationObserver для контролю за змінами в DOM. Через це вам не потрібно нічого налаштовувати або використовувати javascript для ручного анімування речей. Зміни відстежуються автоматично. Однак, оскільки він використовує MutationObserver, це перехід лише в IE11 +.

Загадки!


12
Зазвичай, коли хтось запитує, як зробити щось "без JavaScript", це означає, що рішення повинно працювати на браузерах, у яких відключений JavaScript. Це не означає "без написання власних сценаріїв". Тож сказати, що ваш плагін можна використовувати без використання JavaScript в кращому випадку вводить в оману - враховуючи, що це плагін JavaScript.
BoltClock

Я маю уточнити: Коли я кажу, що вам не потрібно використовувати якийсь спеціальний JavaScript, я маю на увазі, що вам не потрібно писати жодний JavaScript. просто включіть бібліотеку JS та вкажіть, які атрибути ви хочете переглянути в HTML. Вам не доведеться використовувати css фіксованої висоти або щось розбирати. просто стиль та йди.
JonTroncoso

"(...) вам не потрібно нічого налаштовувати або використовувати javascript для ручного анімування речей (...)", тому ви використовуєте JavaScript для розваги
Roko C. Buljan

6

Ось спосіб переходу з будь-якої стартової висоти, включаючи 0, до автоматичного (повнорозмірний та гнучкий), не вимагаючи жорсткого коду на основі вузла або будь-якого коду користувача для ініціалізації: https://github.com/csuwildcat / перехід-авто . В основному це святий грааль для того, що ви хочете, я вважаю -> 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-файл на свою сторінку - все це просто працює ™

/ * Код висоти: авто; перехід * /

(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);

9
Хоча це набагато чистіше та гнучкіше рішення, ніж інші, які були запропоновані, я особисто вважаю, що це не повинно взагалі чіпати JS. Не кажучи, що ви помиляєтесь, це просто зітхання.
mystrdat

@mystrdat, але зрозуміло, що JS використовується лише для спостереження за певними умовами та додавання декількох атрибутів / тимчасових значень CSS на основі подій / умов, які він переглядає. Перехід все ще робиться в CSS. Хоча я згоден, цей рівень налаштування та тримання рук необхідний, щоб справді задовольнити, здавалося б, простий варіант використання! : /
csuwldcat

1
@KarolisRamanauskas ні, це не проблема - IE підтримує як CSS Keyframes, так і requestAnimationFrame. Я використовував clipв якості тригера властивості манекена, і IE чомусь перестав дозволяти анімацію кліпу. Я перейшов на непрозорість, і все знову працює: codepen.io/csuwldcat/pen/FpzGa . Я оновив код у відповіді, щоб відповідати.
csuwldcat

1
@csuwldcat Дуже приємне рішення, я помітив, що вміст з’являється і зникає на невелику частку, чому це відбувається? Це можна уникнути?
Бето Авейга

12
Я хочу підтвердити це, але замість того, щоб відповісти на питання, як змусити його працювати, ви поділилися плагіном, який ви написали, щоб він працював. Нам, допитливим, залишається повернути інженеру ваш плагін, що не дуже цікаво. Я хочу, щоб ви оновили свою відповідь, щоб вона містила більше пояснень, що робить ваш плагін і чому. Змініть код, щоб він був більш пояснювальним. Наприклад, у вас є цілий розділ коду, який просто виписує статичний CSS. Я б швидше бачив CSS, ніж код, який його генерує. Ви можете залишити нудні частини, наприклад повторення всіх префіксів браузера.
gilly3

6

Відповідь Джейка анімувати максимальну висоту чудова, але я знайшов затримку, викликану встановленням великої максимальної висоти, яка дратує.

Можна перемістити вміст, що згортається, у внутрішній діл та обчислити максимальну висоту, отримавши висоту внутрішнього діла (через JQuery це буде externalHeight ()).

$('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/


5

Я розумію, що цей потік старіє, але він займає високі позиції в певних пошуках Google, тому я вважаю, що варто оновити.

Ви також просто отримуєте / встановлюєте власну висоту елемента:

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

Вам слід скинути цей Javascript одразу після закриття тегу target_box у вбудованому тезі сценарію.


document.getElementById ('target_box'). getBoundingClientRect (). висота повинна найкраще робити.
змінити

5

Я зміг це зробити. У мене є .childі в .parentDIV. Дитячий дівоць ідеально вписується в ширину / висоту батьків з 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. Потім цей діва маскує .childдіва, коли він ковзає вниз.


Робочий приклад цього буде дуже вдячний.
Нейромедіатор

5

Я опублікував відповідь з деяким JavaScript і отримав зворотну силу, тому роздратований і спробував ще раз, і зламав його лише за допомогою CSS!

Це рішення використовує декілька "прийомів":

  • padding-bottom:100% 'hack', де відсотки визначаються з точки зору поточної ширини елемента. Детальніше про цю техніку.
  • float-термоусадочне обгортання (що вимагає додаткового діва, щоб застосувати хакінг поплавця)
  • несемантичне використання https://caniuse.com/#feat=css-writing-mode та деякі перетворення для його скасування (це дозволяє використовувати хакінг для підкладки вище у вертикальному контексті)

Підсумком цього є те, що ми отримуємо ефективний перехід лише за допомогою CSS та єдину функцію переходу, щоб плавно досягти переходу; святий грааль!

Звичайно, є і мінус! Я не можу розробити, як контролювати ширину, при якій вміст відсікається ( overflow:hidden); із-за обшивки внизу ширина та висота тісно пов'язані. Хоча може бути спосіб, тому повернемось до нього.

https://jsfiddle.net/EoghanM/n1rp3zb4/28/

body {
  padding: 1em;
}

.trigger {
  font-weight: bold;
}

/* .expander is there for float clearing purposes only */
.expander::after {
  content: '';
  display: table;
  clear: both;
}

.outer {
  float: left; /* purpose: shrink to fit content */
  border: 1px solid green;
  overflow: hidden;
}

.inner {
  transition: padding-bottom 0.3s ease-in-out;  /* or whatever crazy transition function you can come up with! */
  padding-bottom: 0%;  /* percentage padding is defined in terms of width. The width at this level is equal to the height of the content */
  height: 0;

  /* unfortunately, change of writing mode has other bad effects like orientation of cursor */
  writing-mode: vertical-rl;
  cursor: default; /* don't want the vertical-text (sideways I-beam) */
  transform: rotate(-90deg) translateX(-100%);  /* undo writing mode */
  transform-origin: 0 0;
  margin: 0;  /* left/right margins here will add to height */
}

.inner > div { white-space: nowrap; }

.expander:hover .inner,  /* to keep open when expanded */
.trigger:hover+.expander .inner {
  padding-bottom: 100%;
}
<div class="trigger">HoverMe</div>
<div class="expander">
  <div class="outer">
    <div class="inner">
      <div>First Item</div>
      <div>Content</div>
      <div>Content</div>
      <div>Content</div>
      <div>Long Content can't be wider than outer height unfortunately</div>
      <div>Last Item</div>
    </div>
  </div>
</div>
<div>
  after content</div>
</div>


Іншим недоліком цього є те, що ви не можете переміщувати курсор від розділення "hoverme" на список елементів, щоб взаємодіяти з ними (начебто, причина запиту ОП), тому корисна лише як функція підказки, а не , скажімо, меню з вкладеними підменю.
TylerH

Це суто наслідок того, як було сформульовано запитання і не пов'язане з технікою. Ви можете змінити тригер на input[type="checkbox"]:checkedзамість того, :hoverякщо хочете (тобто ви не хочете використовувати JavaScript для додавання класів)
EoghanM

Я маю на увазі, незалежно від того, як формулюється питання, якщо реалізація рішення є настільки обмеженою, це, мабуть, слід згадати у відповіді цього рішення (або бажано враховувати ). Ви згадуєте, що це рішення є «святим граалем», але перехідний дів навіть не може бути накладений на мене… не здається таким кінцевим рішенням для мене.
TylerH

Привіт @TylerH, вибачте, я пропустив той факт, що тригер в оригінальному запитанні оточує розширений список, тож список повинен залишатися відкритим, коли його навести на нього. Я оновив свою відповідь, щоб це відобразити. Як я вже згадував, те, як це спрацьовує, не все є таким германом, оскільки я представляю нову техніку, яка раніше не вважалася можливою лише в CSS (я шукав рішення вже кілька років).
EoghanM

4

Ось таке рішення, яке я щойно використав у поєднанні з 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 }

це не відображається належним чином із новітньою версією jquery
oliverbachmann

4

Я нещодавно переходив 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


3

Я детально не читав все, але у мене була ця проблема останнім часом, і я зробив наступне:

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 - це межа, яку я накладаю. Переконайтеся, що ви маєте перехід на non: навести курсор, інакше у вас може виникнути якесь дивне відображення. Таким чином:: hover успадковується від non: hover.

Перехід не працює від px до% або до автоматичного. Потрібно використовувати ту саму одиницю вимірювання. Це добре працює для мене. Використання HTML5 робить його ідеальним ....

Пам'ятайте, що навколо завжди є робота ...; )

Сподіваюся, хтось вважає це корисним


3

Рішення про максимальну висоту від Джейка добре працює, якщо жорстко закодоване значення максимальної висоти не набагато більше реального (тому що в іншому випадку виникають небажані затримки та проблеми з термінами). З іншого боку, якщо жорстко зафіксоване значення ацидентно не більше реальної висоти, елемент не відкриється повністю.

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

Ідея полягає у використанні від'ємного значення для margin-bottom (або margin-top для трохи відрізняється анімації) та розміщення змістового елемента в середньому елементі з переповненням: приховано. Від'ємний запас елемента вмісту настільки зменшує висоту середнього елемента.

У наведеному нижче коді використовується перехід у нижній частині поля від -150px до 0px. Це одне добре працює, доки елемент вмісту не перевищує 150 пікселів. Крім того, він використовує перехід на максимальну висоту для середнього елемента від 0px до 100%. Це, нарешті, приховує середній елемент, якщо елемент вмісту вище 150 пікселів. Для максимальної висоти перехід використовується просто для затримки його застосування на секунду при закритті, а не для плавного візуального ефекту (і тому він може працювати від 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


3

Ви можете зробити це, створивши зворотну (згорнуту) анімацію з clip-path.

#child0 {
    display: none;
}
#parent0:hover #child0 {
    display: block;
    animation: height-animation;
    animation-duration: 200ms;
    animation-timing-function: linear;
    animation-fill-mode: backwards;
    animation-iteration-count: 1;
    animation-delay: 200ms;
}
@keyframes height-animation {
    0% {
        clip-path: polygon(0% 0%, 100% 0.00%, 100% 0%, 0% 0%);
    }
    100% {
        clip-path: polygon(0% 0%, 100% 0.00%, 100% 100%, 0% 100%);
    }
}
<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>


2

Це не зовсім "вирішення" проблеми, а більше рішення. Він працює лише так, як написано з текстом, але може бути змінено на роботу з іншими елементами, якщо потрібно, я впевнений.

.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 і перехід, який замість висоти, або максимальної висоти, або масштабу Y () і т.д. досить швидким темпом, щоб висота трансформувалася до того, що ви хочете. Перетворити фактичну висоту за допомогою CSS в автоматичну наразі неможливо, але перетворення вмісту всередині є, отже, переходом до розміру шрифту.

  • Примітка - у кодері є javascript, але мета полягає лише в тому, щоб додати / видалити класи css при натисканні на гармошку. Це можна зробити за допомогою прихованих радіо кнопок, але я не зосереджувався на цьому, а лише перетворення висоти.

1
Ефективно дублює цю відповідь , але не вражає ефект непрозорості.
SeldomNeedy

Домовились. Кращий підхід.
Майк С.
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.