Переходи у властивості відображення CSS


1446

Наразі я розробляю CSS-меню «мега-спадне меню» - в основному звичайне спадне меню, що використовується лише для CSS, але таке, яке містить різні типи вмісту.

На даний момент, здається , що CSS 3 переходи не застосовуються до властивості «відображення» , тобто, ви не можете зробити якийсь - або переходу від display: noneдо display: block(або будь-який їх комбінації).

Чи є спосіб, щоб меню другого рівня з вищевказаного прикладу було «зникати», коли хтось наводить курсор на один із пунктів меню верхнього рівня?

Я знаю, що ви можете використовувати переходи у visibility:власність, але я не можу придумати спосіб ефективного використання.

Я також спробував використовувати висоту, але це просто не вдалося.

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


Чи працює перехід CSS, якщо застосувати його до властивості непрозорості, а не відображати?
Пол Д. Уейт,

13
позиція: абсолютна; видимість: приховано; те саме, що і дисплей: немає;
Jawad

8
@Jawad: Тільки якщо ви також додасте щось подібне z-index:0.
DanMan

7
@Jawad: Рекомендується ніколи не використовувати, visibility: hiddenякщо ви не хочете, щоб їх читали екранізатори (тоді як типові веб-переглядачі не будуть). Він визначає лише видимість елемента (як, наприклад, висловлювання opacity: 0), і він все ще вибирається, можна натискати, і все, що раніше було; це просто не видно
Лісовий Катч

1
немає підтримки pointer-eventsв IE 8,9,10, тому це не завжди нормально
Стівен Прибілінський

Відповіді:


1351

Ви можете поєднати два переходи або більше, і visibilityце стане в нагоді цього разу.

div {
  border: 1px solid #eee;
}
div > ul {
  visibility: hidden;
  opacity: 0;
  transition: visibility 0s, opacity 0.5s linear;
}
div:hover > ul {
  visibility: visible;
  opacity: 1;
}
<div>
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
  </ul>
</div>

(Не забудьте префікси постачальника до transitionресурсу.)

Детальніше в цій статті .


10
Ця відповідь здається меншою роботою, ніж інші, і досягається того, що ми очікували від відображення: немає / блок; Дякую. Врятувало мене тону часу.
Брендан

21
Так, проблема в тому, що все за цим буде перекриватися, навіть якщо його не видно. Я знайшов використання висоти: 0 набагато краще рішення
Джош Бедо

739
Це добре, але проблема полягає в тому, що елементи "прихованої видимості" все ще займають простір, а "дисплей немає".
Rui Marques

41
Мені, певно, чогось не вистачає, але чому ви змінюєте і видимість, і непрозорість? Не вдасться встановити непрозорість на 0 приховати елемент - навіщо вам також потрібно встановити видимість на приховану?
GMA

21
@GeorgeMillo, якщо ви встановите лише непрозорість, елемент насправді все ще знаходиться у відображенні сторінки (наприклад, ви не можете натиснути на думку).
adriendenat

800

Вам потрібно приховати елемент іншими способами, щоб змусити це працювати.

Я досягнув ефекту, <div>встановивши обидва s абсолютно і встановивши прихований opacity: 0.

Якщо ви навіть переключите displayвластивість з noneна block, ваш перехід на інші елементи не відбудеться.

Щоб обійти це, завжди дозволяйте елемент бути display: block, але приховуйте елемент, коригуючи будь-який із цих засобів:

  1. Встановіть heightв 0.
  2. Встановіть opacityв 0.
  3. Розташуйте елемент поза рамкою іншого елемента, який є overflow: hidden.

Можливо, є більше рішень, але ви не можете виконати перехід, якщо переключити елемент на display: none. Наприклад, ви можете спробувати щось подібне:

div {
    display: none;
    transition: opacity 1s ease-out;
    opacity: 0;
}
div.active {
    opacity: 1;
    display: block;
}

Але це не вийде . Зі свого досвіду я виявив, що це нічого не робить.

Через це вам завжди потрібно буде зберегти елемент display: block- але ви могли його обійти, зробивши щось подібне:

div {
    transition: opacity 1s ease-out;
    opacity: 0;
    height: 0;
    overflow: hidden;
}
div.active {
    opacity: 1;
    height: auto;
}

29
Дякую Джиму за ретельну відповідь. Ви абсолютно праві щодо того, що якщо дисплей: властивість зміниться взагалі, то ВСІ ваші переходи не працюватимуть. Що соромно - мені цікаво, що це за міркування. У бічній записці, на тому самому посиланні, яке я розмістив у оригінальному запитанні, ви можете бачити, де я з цим. Єдина (невелика) проблема, яка у мене є, є в Chrome [5.0.375.125], коли сторінка завантажується, ви можете побачити, що меню швидко згасає, коли елементи завантажуються на сторінку. Firefox 4.0b2 і Safari 5.0 абсолютно добре ... помилка чи щось я пропустив?
RichardTape

7
Я погоджуюся, що це правильно і сприятиме цьому; вгору майбутнім мандрівникам. Я знайшов робоче рішення в Chrome, але виявив, що це не вдається на iPhone 4: visibility:hidden; opacity:0; -webkit-transition: all .2s ease-in-out;не тільки це не переходить правильно, але й цільовий елемент ніколи не з’явиться. QA не вдасться вам, мені та вашій мамі.
SimplGy

1
Ви також можете перейти на властивість видимості .. просто кажучи
Cu7l4ss

2
Якщо ви встановите прихований стан height: 0;і не переходите до нього, перехід не буде працювати. Я спробував це, просто намагаючись перейти непрозорість. Мені довелося знятиheight: 0;
chovy

10
Ви щойно виграли голосування через overflow: hiddenвелике спасибі!
Тіаго

277

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

Приклад коду (ви можете відповідно застосувати його до свого меню) Демо :

Додайте до таблиці стилів такі CSS:

@-webkit-keyframes fadeIn {
    from { opacity: 0; }
      to { opacity: 1; }
}
@keyframes fadeIn {
    from { opacity: 0; }
      to { opacity: 1; }
}

Потім застосуйте fadeInанімацію до дитини на батьківському курсорі (і, звичайно, набір display: block):

.parent:hover .child {
    display: block;
    -webkit-animation: fadeIn 1s;
    animation: fadeIn 1s;
}

Оновлення 2019 - метод, який також підтримує згасання:

(Потрібен деякий код JavaScript)

// We need to keep track of faded in elements so we can apply fade out later in CSS
document.addEventListener('animationstart', function (e) {
  if (e.animationName === 'fade-in') {
      e.target.classList.add('did-fade-in');
  }
});

document.addEventListener('animationend', function (e) {
  if (e.animationName === 'fade-out') {
      e.target.classList.remove('did-fade-in');
   }
});
div {
    border: 5px solid;
    padding: 10px;
}

div:hover {
    border-color: red;
}

.parent .child {
  display: none;
}

.parent:hover .child {
  display: block;
  animation: fade-in 1s;
}

.parent:not(:hover) .child.did-fade-in {
  display: block;
  animation: fade-out 1s;
}

@keyframes fade-in {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

@keyframes fade-out {
  from {
    opacity: 1;
  }
  to {
    opacity: 0;
  }
}
<div class="parent">
    Parent
    <div class="child">
        Child
    </div>
</div>


3
Дякую за це Згаданий вище height: 0трюк (для переходів), здається, не працює, тому що висота встановлюється 0 на переході, але, здається, цей трюк спрацьовує чудово.
Елліот Вінклер

41
Дякую, дуже корисно. Але як його зникнути?
Ілліу

1
Перший параграф цієї відповіді не зовсім має сенс. Веб-переглядачі не просто відключають усі переходи прямо в той момент, коли ви користуєтесь цим displayресурсом - це насправді немає причин. І навіть якщо вони це зробили , чому б тоді анімація працювала? Ви також не можете використовувати displayвластивість у анімації CSS.
BoltClock

7
Найкраща відповідь, не можлива при переходах, але так - з анімацією.
Мікель

6
Як щодо зворотної анімації, тобто коли елемент повинен повільно зникати?
Зелений

77

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

display: none;і visibility: hidden;є два абсолютно різні речі.
Обидва мають ефект зробити невидимим елемент, але visibility: hidden;він все ще відображається в макеті, але просто не помітно .
Прихований елемент як і раніше займає простір, і все ще надається в рядку або як блок, блок-вбудована таблиця або таблиця, або все, що displayелемент каже, щоб він видавав як, і займає простір відповідно.
Інші елементи не рухаються автоматично, щоб зайняти цей простір. Прихований елемент просто не видає фактичні пікселі на вихід.

display: none з іншого боку фактично заважає елементу повністю відображатись .
Він не займає ніякого макета простору.
Інші елементи, які зайняли б частину чи весь простір, зайнятий цим елементом, тепер підлаштовуються під зайняття цього простору, наче елемент просто не існував взагалі .

displayце не просто ще один візуальний атрибут.
Він встановлює весь режим візуалізації елемента, наприклад, чи це ablock , inline, inline-block, table, table-row, table-cell, list-item, або що завгодно!
Кожен з них мають дуже різні наслідки компонування, і не було б ніякого розумного способу одухотворені або плавно переходити їх (спробуйте уявити собі плавний перехід від blockдо inlineабо навпаки, наприклад!).

Ось чому переходи вимикаються, якщо зміни відображаються (навіть якщо зміна переходить на або з none- noneне просто невидимість, це власний режим візуалізації елементів, який означає відсутність візуалізації взагалі!).


8
Як би не було вищевикладене рішення, було дуже задоволення отримати розумне пояснення того, чому переходи не застосовуються до атрибутів відображення.
kqr

8
Я не погоджуюсь. Це могло мати повний сенс. Якщо відображення: немає для відображення: блок стався миттєво на початку переходу, це було б чудово. А для переходу назад, якби він перейшов від display: block to display: немає праворуч в кінці переходу, це було б ідеально.
Кертіс Яллоп

2
Якщо ви не можете уявити, як виглядає анімація від точки до прямокутника, у вас виникли проблеми. Перехід від заняття не простору до заняття прямокутного простору ДУЖЕ очевидний, як, ви робите це кожен раз, коли ви перетягуєте прямокутник з мишкою, як і будь-яка програма. В результаті цього збою, так багато хак, що включають максимальну висоту та негативні поля, це недоцільно. Єдине, що працює - це кешування «реальної» висоти, а потім анімація від нуля до кешованого значення за допомогою JavaScript. Сумно.
Трайнко

2
Tryniko: display: жоден не змінює розмір елемента на прямокутник 0 x 0 - він видаляє його з DOM. Ви можете анімувати від прямокутника до точки, анімувавши властивості ширини та висоти до нуля, а потім інші елементи обтікали б його, як ніби він мав "display: none", але його атрибут "display" залишатиметься "block"; елемент все ще знаходиться в DOM. Поняття анімації між дисплеєм: блоком та дисплеєм: жодне не є смішним: проміжних станів немає. Елемент або існує в DOM, або його немає, незалежно від того, наскільки він малий чи невидимий.
Стів Торп

1
Не смішно оживляти дискретні властивості. Дискретні властивості, як-от displayне можна переходити плавно, як інші властивості, але це не означає, що час не важливий. Вміння контролювати, коли перехід від disply:blockдо того, що display:noneвідбувається, дуже важливо. Так само, як описав це @CurtisYallop. Якщо я хочу перейти з opacity:1на, opacity:0а потім змінити display:blockна, display:noneя маю змогу це зробити.
Єнс

55

Замість зворотних викликів, яких не існує у CSS, ми можемо використовувати transition-delayвластивість.

#selector {
    overflow: hidden; // Hide the element content, while height = 0
    height: 0; opacity: 0;
    transition: height 0ms 400ms, opacity 400ms 0ms;
}
#selector.visible {
    height: auto; opacity: 1;
    transition: height 0ms 0ms, opacity 600ms 0ms;
}

Отже, що тут відбувається?

  1. Коли visibleклас додано, обидва heightі opacityзапускайте анімацію без зволікань (0 мс), хоча heightдля завершення анімації потрібно 0 мс (еквівалентно display: block) і opacityзаймає 600 мс.

  2. Коли visibleклас видалено, opacityзапускається анімація (затримка 0 мс, тривалість 400 мс), а висота чекає 400 мс, і лише потім миттєво (0 мс) відновлює початкове значення (еквівалент display: noneзворотного виклику анімації).

Зауважте, такий підхід кращий, ніж ті, що використовують visibility. У таких випадках елемент все ще займає простір на сторінці, і це не завжди підходить.

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


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

3
Він працює лише з тим, height:100%що може зруйнувати макет у деяких випадках. Чудове рішення, якщо це не проблема. Один з небагатьох двосторонніх працюючих.
Фабіан фон Еллертс

Це чудово! Мені вдалося ще більше спростити це в моєму випадку, тому що я хотів, щоб час зниклої анімації був таким самим, як час зникання. Замість використання transition: height 0ms 0ms, opacity 600ms 0ms, я просто використовував transition-delay: 0s.
Якоб Локард

52

display не є однією з властивостей, на які працює перехід.

Див. Властивості Animatable CSS для переліку властивостей CSS, які можуть застосовувати переходи до них. Див. Розділ Модулі значень і одиниць CSS Рівень 4, Об'єднання значень: Інтерполяція, Додавання та Накопичення щодо їх інтерполяції.

До CSS 3 було вказано у 9.1. Властивості з CSS (просто закрийте спливаюче попередження)

Я також спробував використовувати висоту, але це просто не вдалося.

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


Посилання більше не вказує безпосередньо на розділ властивостей анімації.
Ендрю Лам

1
Виправлено @AndrewLam. Дякую.
robocat

34

Ви можете додати спеціальну анімацію до властивості блоку вже зараз.

@keyframes showNav {
  from {opacity: 0;}
  to {opacity: 1;}
}
.subnav-is-opened .main-nav__secondary-nav {
  display: block;
  animation: showNav 250ms ease-in-out both;
}

Демо

У цій демонстраційній програмі підменю змінюється з display:noneна display:blockта все ще вдається зникати.


Повинен myfirstбути showNavтут? А як щодо Firefox? На жаль, я не можу знайти щось, що стосується демонстраційної сторінки, яку ви згадуєте.
Себастьян vom Meer

Дякуємо @SebastianG Я вніс виправлення та додав трохи більше інформації вище.
Маніш Прадхан

@Sebastian vom Meer: для старих версій Firefox потрібен префікс постачальника "-moz-", див. Відредагований код
Herr_Schwabullek

23
Якщо я щось не пропускаю, посилання "демонстрація" більше не показує перехід підменю.
Реалістичний

1
Правильний перехід для чогось, що не займає місця (як у випадку з дисплеєм: немає), до чогось, що займає простір (дисплей: блок), - це розширення розмірів, а не зникнення. Якщо це було питанням видимості, прихованої (яка займає простір, але не видно) для видимого, то розмір залишається однаковим, і вицвітання доречне. Жодна з цих відповідей не вирішує проблему.
Трайнко

21

Згідно з робочим проектом W3C 19 листопада 2013 року display не є анімаційною властивістю . На щастя, visibilityце анімація. Ви можете зв'язати його перехід з переходом непрозорості ( JSFiddle ):

  • HTML:

    <a href="http://example.com" id="foo">Foo</a>
    <button id="hide-button">Hide</button>
    <button id="show-button">Show</button>
  • CSS:

    #foo {
        transition-property: visibility, opacity;
        transition-duration: 0s, 1s;
    }
    
    #foo.hidden {
        opacity: 0;
        visibility: hidden;
        transition-property: opacity, visibility;
        transition-duration: 1s, 0s;
        transition-delay: 0s, 1s;
    }
  • JavaScript для тестування:

    var foo = document.getElementById('foo');
    
    document.getElementById('hide-button').onclick = function () {
        foo.className = 'hidden';
    };
    
    document.getElementById('show-button').onclick = function () {
        foo.className = '';
    };

Зауважте, що якщо ви просто зробите посилання прозорим, без налаштування visibility: hidden , воно не може працювати.


1
я взагалі не бачу жодного переходу у прикладі jsfiddle
Gino

@Gino Я виправив це, змінивши 0на 0s. Мабуть, у минулому браузер, який я використовував для тестування, підтримував безвідмовні нульові рази. Однак, нероздільні часи не є частиною Рекомендації щодо кандидата W3C, 29 вересня 2016 року .
feklee

На це варто більше звертати увагу. Я виявив, що це одне з найкращих рішень.
Артур Тарасов

Використання затримки - найкраща логіка, щоб зрозуміти, як це працює. Анімувати та ховати. Відкривати та оживляти. Ідеальне рішення для мене
Бруно Піттелі Гонсалвес

14

Редагувати: дисплей жоден не застосовується в цьому прикладі.

@keyframes hide {
  0% {
    display: block;
    opacity: 1;
  }
  99% {
    display: block;
  }
  100% {
    display: none;
    opacity: 0;
  }
}

Що відбувається вище, це те, що через 99% дисплея анімації встановлено блокування, коли непрозорість згасає. В останній момент властивість відображення не встановлено.

І найважливіший біт - це зберегти останній кадр після закінчення анімації, використовуючи режим анімації-заливки: вперед

.hide {
   animation: hide 1s linear;
   animation-fill-mode: forwards;
}

Ось два приклади: https://jsfiddle.net/qwnz9tqg/3/


з цим рішенням display: noneтоді не працює?
Барт Калікто

Повинен бути режим "анімація-заповнення: вперед", а не "вперед"
Алекс

Зміни повинні бути шістьма символами, і я можу лише запропонувати редагувати, отже, коментар
Алекс

1
@ Алекс Ок. Друкарська помилка. Що цікаво, це те, що моя відповідь навіть не працює, як очікувалося, але логічно думати, що це так, я буду тримати її, поки браузери не підтримають її.
Pawel

3
Як ви бачите в цій скрипці з набором курсорів, display: noneнасправді ніколи не реалізується. jsfiddle.net/3e6sduqh
robstarbuck

13

Мій акуратний фокус JavaScript - розділити весь сценарій на дві різні функції !

Для підготовки речей оголошується одна глобальна змінна та визначається один обробник подій:

  var tTimeout;
  element.addEventListener("transitionend", afterTransition, true);//firefox
  element.addEventListener("webkitTransitionEnd", afterTransition, true);//chrome

Потім, приховуючи елемент, я використовую щось подібне:

function hide(){
  element.style.opacity = 0;
}

function afterTransition(){
  element.style.display = 'none';
}

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

function show(){
  element.style.display = 'block';
  tTimeout = setTimeout(timeoutShow, 100);
}

function timeoutShow(){
  element.style.opacity = 1;
}

Це працює, поки що!


Це працює через затримку часу, а не тому, що команди javascript виконуються в окремих функціях. Часові затримки здаються хорошим рішенням у багатьох випадках :)

10

Я зіткнувся з цим сьогодні з position: fixedмодалом, який я повторно використовував. Я не зміг утримати його, display: noneа потім оживити його, оскільки він просто перейшов у зовнішній вигляд, і, z-index(негативні значення тощо), робив і дивні речі.

Я також використовував height: 0до height: 100%, але це працювало лише тоді, коли з'явився модальний режим. Це те саме, як якщо б ви використовували left: -100%чи щось.

Потім мене вразило, що відповідь проста. Et voila:

По-перше, ваш прихований модальний. Зауважте, що heightє 0, і перевірте heightдекларацію в переходах ... вона має a 500ms, що довше мого opacityпереходу . Пам'ятайте, що це впливає на вихідний перехідний час: повернення модалу у стан за замовчуванням.

#modal-overlay {
    background: #999;
    background: rgba(33,33,33,.2);
    display: block;
    overflow: hidden;
    height: 0;
    width: 100%;
    position: fixed;
    top: 0;
    left: 0;
    opacity: 0;
    z-index: 1;
    -webkit-transition: height 0s 500ms, opacity 300ms ease-in-out;
       -moz-transition: height 0s 500ms, opacity 300ms ease-in-out;
            -ms-transition: height 0s 500ms, opacity 300ms ease-in-out;
         -o-transition: height 0s 500ms, opacity 300ms ease-in-out;
        transition: height 0s 500ms, opacity 300ms ease-in-out;
}

По-друге, ваш видимий модальний. Скажіть, ви встановлюєте .modal-activeна body. Зараз heightє 100%, і мій перехід також змінився. Я хочу, heightщоб миттєво змінилися, і opacityвзяли 300ms.

.modal-active #modal-overlay {
    height: 100%;
    opacity: 1;
    z-index: 90000;
    -webkit-transition: height 0s, opacity 300ms ease-in-out;
       -moz-transition: height 0s, opacity 300ms ease-in-out;
        -ms-transition: height 0s, opacity 300ms ease-in-out;
         -o-transition: height 0s, opacity 300ms ease-in-out;
            transition: height 0s, opacity 300ms ease-in-out;
}

Ось це, це працює як шарм.


Оголошення для вашого стилю вирівнювання впорядкованих властивостей постачальника
George

9

Отримавши з цих кількох відповідей та деяких пропозицій в іншому місці, наступне чудово підходить для меню наведення курсора (я використовую це для  конкретно Bootstrap 3):

nav .dropdown-menu {
    display: block;
    overflow: hidden;
    max-height: 0;
    opacity: 0;
    transition: max-height 500ms, opacity 300ms;
    -webkit-transition: max-height 500ms, opacity 300ms;
}
nav .dropdown:hover .dropdown-menu {
    max-height: 500px;
    opacity: 1;
    transition: max-height 0, opacity 300ms;
    -webkit-transition: max-height 0, opacity 300ms;
}

Ви також можете використовувати heightзамість, max-heightякщо ви вкажете обидва значення, оскільки height:autoце не дозволено із transitions. Значення курсора max-heightповинно бути більше, ніж heightможливо в меню.


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

8

Я знайшов кращий спосіб для цієї проблеми, ви можете використовувати CSS Animation і зробити свій дивовижний ефект для показу елементів.

    .item {
     display: none;
}

.item:hover {
     display: block;
     animation: fade_in_show 0.5s
}

@keyframes fade_in_show {
     0% {
          opacity: 0;
          transform: scale(0)
     }
     100% {
          opacity: 1;
          transform: scale(1)
     }
}

Дякую за цю корисну пораду. Це працює ідеально.
Седат Кумку

6

Я не раз стикався з цією проблемою, а тепер просто:

.block {
  opacity: 1;
  transition: opacity 250ms ease;
}

.block--invisible {
  pointer-events: none;
  opacity: 0;
}

Додаючи клас, block--invisibleцілі Елементи не можна буде натискати, але всі Елементи, що знаходяться за ним, будуть pointer-events:noneпідтримуватися всіма основними браузерами (немає IE <11).


Чи можете ви прикласти це до прикладу, будь ласка?
GarethAS

1
Це добре працює, але слід зазначити, що покажчик-події не працює з IE нижче 11
user1702965

додано примітку для IE нижче 11
ДомінікАнгерер

Якщо вам потрібно, щоб цей елемент був зверху на все (наприклад, меню), це, чесно кажучи, найчистіший спосіб зробити це зараз, коли підтримка в 2019 році є надійноюpointer-events
Джош Давенпорт,

5

Змінити overflow:hiddenна overflow:visible. Це працює краще. Я використовую так:

#menu ul li ul {
    background-color:#fe1c1c;
    width:85px;
    height:0px;
    opacity:0;
    box-shadow:1px 3px 10px #000000;
    border-radius:3px;
    z-index:1;
    -webkit-transition:all 0.5s ease;
    -moz-transition:all 0.6s ease;
}

#menu ul li:hover ul  {
    overflow:visible;
    opacity:1;
    height:140px;
}

visibleкраще, тому що overflow:hiddenдіяти точно так, як display:none.


Цей для мене був квиток. Дякую!
Dan Loewenherz

5

JavaScript не потрібен, і не потрібна велика висота максимальної висоти. Натомість встановіть свої max-heightтекстові елементи та використовуйте відносну шрифт, наприклад, remабо em. Таким чином, ви можете встановити максимальну висоту, що перевищує ваш контейнер, уникаючи затримки або "вискакування", коли меню закриється:

HTML

<nav>
  <input type="checkbox" />
  <ul>
    <li>Link 1</li>
    <li>Link 1</li>
    <li>Link 1</li>
    <li>Link 1</li>
  </ul>
</nav>

CSS

nav input + ul li { // Notice I set max-height on li, not ul
   max-height: 0;
}

nav input:checked + ul li {
   max-height: 3rem; // A little bigger to allow for text-wrapping - but not outrageous
}

Дивіться приклад тут: http://codepen.io/mindfullsilence/pen/DtzjE


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

Чому так мало голосів? Це дійсно гарна відповідь, і я можу бути тим, яким я користуюся.
mwilcox

@mwilcox Тому що він використовує фіксовану висоту, що погано під час роботи з динамічним вмістом (рівна приблизна висота). І це корисно лише для текстового вмісту.
Fabian von Ellerts

5

Після написання прийнятої відповіді від Гільєрмо, специфікація переходу CSS в 2012-04-03 змінила поведінку переходу на видимість, і тепер можна вирішити цю проблему більш коротким способом , без використання переходу-затримки:

.myclass > div {
                   transition:visibility 1s, opacity 1s;
                   visibility:hidden;  opacity:0
               }
.myclass:hover > div
               {   visibility:visible; opacity:1 }

Час запуску, визначений для обох переходів, зазвичай повинен бути однаковим (хоча дещо більший час для видимості не є проблемою).

Для запущеної версії див. Мою публікацію в блозі Видимість переходу CSS .

Напишіть назву питання "Переходи на дисплеї: властивість" та у відповідь на коментарі Руї Маркеса та жоша до прийнятої відповіді:

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

Він не повністю видалить елемент як display:none, просто зробить його невидимим, але він все ще залишається в документообігу та впливає на положення наступних елементів.

Переходи, які повністю видаляють схожий елемент, display:noneможна здійснити за допомогою висоти (як зазначено в інших відповідях та коментарях), максимальної висоти або границі вгорі / внизу, але також див. Як я можу змінити висоту: 0; по висоті: авто; за допомогою CSS? і мій пост у блозі Обхідні шляхи переходів CSS у властивостях відображення та висоти .

У відповідь на коментар від GeorgeMillo: Обидва властивості та обидва переходи потрібні: властивість непрозорості використовується для створення анімації зникнення та згасання та властивості видимості, щоб уникнути того, що елемент все ще реагує на події миші. Переходи потрібні на непрозорість для візуального ефекту та на видимість, щоб затримати приховування до завершення вицвітання.


4

Нарешті я знайшов рішення для мене, комбінуючи opacityз position absolute(не займати місця, коли приховано).

.toggle {
  opacity: 0;
  position: absolute;
  transition: opacity 0.8s;
}

.parent:hover .toggle {
  opacity: 1;
  position: static;
}

4

Я підозрюю, що хтось починає переходи CSS швидко виявляє, що вони не працюють, якщо ви одночасно змінюєте властивість відображення (блок / жоден). Одне вирішення, яке ще не було згадано, - це те, що ви можете продовжувати використовувати display:block/noneдля приховування / показу елемента, але встановити його непрозорість на 0, так що навіть коли цеdisplay:block , він все ще не помітний.

Потім, щоб зменшити його, додайте інший клас CSS, такий як "on", який встановлює непрозорість на 1 і визначає перехід для непрозорості. Як ви могли уявити, вам доведеться використовувати JavaScript, щоб додати клас "on" до елемента, але принаймні ви все ще використовуєте CSS для фактичного переходу.

PS Якщо ви опинитесь у ситуації, коли вам потрібно зробити і те display:block, і додайте клас "on", одночасно відкладіть останні за допомогою setTimeout. В іншому випадку браузер просто бачить, що відбувається одночасно, і відключає перехід.


Відмінно, дякую! Я написав ще одну відповідь на прикладі, з яким насправді працює display:none.
mojuba

4

Це так просто, як нижче :)

@keyframes fadeout {
    0% { opacity: 1; height: auto; }
    90% { opacity: 0; height: auto; }
    100% { opacity: 0; height: 0;
}
animation: fadeout linear 0.5s 1 normal forwards !important;

Поставте його зникати, а потім зробіть це height 0;. Також переконайтесь, що використовуєте форварди, щоб вони залишалися в остаточному стані.


Це миттєво
Шон Т

2

Це рішення має чудову сумісність, і я його ще не бачив:

.hidden-element {
  position: absolute;
  z-index: -1;
  pointer-events: none;
  visibility: hidden;
  opacity: 0;
  transition: visibility 0s, opacity .5s ease-out;
}

.hidden-element.visible {
  position: static;
  z-index: auto;
  pointer-events: auto;
  visibility: visible;
  opacity: 1;
}

Пояснення : він використовує visibility: hiddenтрюк (який сумісний із "показом і анімацією" за один крок), але він використовує комбінацію, position: absolute; z-index: -1; pointer-events: none;щоб переконатися, що прихований контейнер не займає місця і не відповідає на взаємодії користувачів .


1
Але зміна positionвсе-таки змусить елемент стикатися, ні?
Арсиль

Ну, поза межами: position: absoluteозначає, що елемент не займає місця, як описано в поясненні. Коли він переключиться position: staticі з’явиться, він займе простір, як звичайний елемент, в чому полягає питання цього питання. Я пропоную спробувати!
Крістоф Маруа

2
Я зробив. Але якщо я правильно розумію, питання стосувалося переходів . Як і в "гладких анімаціях".
Арсіль

2

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

https://jsfiddle.net/b9chris/hweyecu4/17/

Починаючи з поля, наприклад:

<div id="box" class="hidden">Lorem</div>

Прихований ящик.

div.hidden {
    display: none;
}
#box {
    transition: opacity 1s;
}

Ми будемо використовувати трюк, знайдений у відповідному питанні, перевіряючи зсув Висота, щоб миттєво заглушити браузер:

https://stackoverflow.com/a/16575811/176877

По-перше, бібліотека, що оформляє вищевказаний трюк:

$.fn.noTrnsn = function () {
    return this.each(function (i, tag) {
        tag.style.transition = 'none';
    });
};
$.fn.resumeTrnsn = function () {
    return this.each(function (i, tag) {
        tag.offsetHeight;    
        tag.style.transition = null;
    });
};

Далі ми будемо використовувати його, щоб розкрити скриньку, і вимкнути її:

$('#button').on('click', function() {
    var tag = $('#box');
    if (tag.hasClass('hidden'))
        tag.noTrnsn().removeClass('hidden')
        .css({ opacity: 0 })
        .resumeTrnsn().css({ opacity: 1 });
    else
        tag.css({ opacity: 0 });
});

Це вимикає коробку всередину та поза. Так, .noTrnsn()вимикає переходи, то ми видаляємо hiddenклас, який перевертає displayз noneйого замовчуванням block. Потім ми встановлюємо непрозорість на 0, щоб підготуватися до згасання. Тепер, коли ми встановили етап, ми знову включаємо переходи .resumeTrnsn(). І нарешті, розпочніть перехід, встановивши непрозорість на 1.

Без бібліотеки і зміна відображення, і зміна непрозорості отримали б нам небажані результати. Якщо ми просто видалили дзвінки з бібліотеки, ми взагалі не отримали б переходів.

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

Уява!

https://jsfiddle.net/b9chris/hweyecu4/22/

#box {
    transition: height 1s, opacity 1s;
}

Зараз ми переходимо як на висоту, так і на непрозорість. Зверніть увагу , що ми не ставимо висоту, що означає , що за замовчуванням, auto. Умовно це неможливо перенести - перехід від автоматичного до піксельного значення (як 0) не призведе до переходу. Ми будемо працювати над цим із бібліотекою та ще одним методом бібліотеки:

$.fn.wait = function (time, fn) {
    if (time)
        this.delay(time);
    if (!fn)
        return this;

    var _this = this;
    return this.queue(function (n) {
        fn.call(_this);
        n();
    });
};

Це зручний метод, який дозволяє нам брати участь у існуючій черзі fx / анімації jQuery, не вимагаючи жодної рамки анімації, яка зараз виключається у jQuery 3.x. Я не збираюся пояснювати, як працює jQuery, але достатньо сказати, .queue()і .stop()сантехніка, яку надає jQuery, допомагає нам не допустити, щоб наші анімації наступали один на одного.

Давайте оживимо ефект слайда вниз.

$('#button').on('click', function() {
    var tag = $('#box');
    if (tag.hasClass('hidden')) {
        // Open it
        // Measure it
        tag.stop().noTrnsn().removeClass('hidden').css({
            opacity: 0, height: 'auto'
        });
        var h = tag.height();
        tag.css({ height: 0 }).resumeTrnsn()
        // Animate it
        .css({ opacity: 1, height: h })
        .wait(1000, function() {
            tag.css({ height: 'auto' });
        });
    } else {
        // Close it
        // Measure it
        var h = tag.noTrnsn().height();
        tag.stop().css({ height: h })
        .resumeTrnsn()
        // Animate it
        .css({ opacity: 0, height: 0 })
        .wait(1000, function() {
            tag.addClass('hidden');
        });
    }
});

Цей код починається з перевірки #boxта чи є він на даний момент прихованим, перевіряючи його клас. Але це досягає більше, використовуючи wait()виклик бібліотеки, додавшиhidden клас в кінці анімації слайд / вимкнення, який, як ви очікували, знайдете, якщо він насправді прихований - щось вище, простіший приклад не міг зробити. Це також дозволяє включити відображення / приховування елемента знову і знову, що було помилкою в попередньому прикладі, оскільки прихований клас ніколи не був відновлений.

Ви також можете бачити зміни CSS та класів, які викликаються після того, .noTrnsn()як загалом встановити анімацію, включаючи проведення вимірювань, наприклад вимірювання кінцевої висоти #boxбез показу цього користувачеві перед тим, як викликати.resumeTrnsn() , та анімувати його з цілком набору стадія до його цільових значень CSS.

Стара відповідь

https://jsfiddle.net/b9chris/hweyecu4/1/

Ви можете переключити його на клік за допомогою:

function toggleTransition() {
  var el = $("div.box1");

  if (el.length) {
    el[0].className = "box";
    el.stop().css({maxWidth: 10000}).animate({maxWidth: 10001}, 2000, function() {
        el[0].className = "box hidden";
    });
  } else {
    el = $("div.box");
    el[0].className = "box";
    el.stop().css({maxWidth: 10001}).animate({maxWidth: 10000}, 50, function() {
        el[0].className = "box box1";
    });
  }

  return el;
}

someTag.click(toggleTransition);

CSS - це те, що ви здогадалися:

.hidden {
    display: none;
}
.box {
    width: 100px;
    height: 100px;
    background-color: blue;
    color: yellow;
    font-size: 18px;
    left: 20px;
    top: 20px;
    position: absolute;
    -webkit-transform-origin: 0 50%;
    transform-origin: 0 50%;
    -webkit-transform: scale(.2);
    transform: scale(.2);
    -webkit-transition: transform 2s;
    transition: transform 2s;
}
.box1{
    -webkit-transform: scale(1);
    transform: scale(1);
}

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

Примітка: я .animate(maxWidth)тут зловживаю, щоб уникати setTimeoutперегонів. setTimeoutшвидко вводити приховані помилки, коли ви чи хтось інший вибирає код, не знаючи про це. .animate()можна легко вбити с .stop(). Я просто використовую його, щоб поставити затримку 50 мс або 2000 мс на стандартну чергу Fx, де її легко знайти / вирішити іншими кодерами, що будують поверх цього.


1

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

Виявляється, visibilityвластивість CSS має значення, collapseяке зазвичай використовується для елементів таблиці. Однак, якщо він використовується на будь-яких інших елементах, він ефективно робить їх прихованими , майже так само, як, display: hiddenале з додатковою здатністю, що елемент не займає ніякого місця, і ви все одно можете оживити відповідний елемент.

Нижче наводиться простий приклад цього в дії.

function toggleVisibility() {
  let exampleElement = document.querySelector('span');
  if (exampleElement.classList.contains('visible')) {
    return;
  }
  exampleElement.innerHTML = 'I will not take up space!';
  exampleElement.classList.toggle('hidden');
  exampleElement.classList.toggle('visible');
  setTimeout(() => {
    exampleElement.classList.toggle('visible');
    exampleElement.classList.toggle('hidden');
  }, 3000);
}
#main {
  display: flex;
  flex-direction: column;
  width: 300px;
  text-align: center;
}

.hidden {
  visibility: collapse;
  opacity: 0;
  transition: visibility 2s, opacity 2s linear;
}

.visible {
  visibility: visible;
  opacity: 1;
  transition: visibility 0.5s, opacity 0.5s linear;
}
<div id="main">
  <button onclick="toggleVisibility()">Click Me!</button>
  <span class="hidden"></span>
  <span>I will get pushed back up...</span>
</div>


1

Найпростіше універсальне рішення проблеми: сміливо вказуйте display:noneу своєму CSS, однак ви зміните його на block(або будь-що інше) за допомогою JavaScript, а потім вам доведеться також додати клас до вашого елемента, про який йдеться. робить перехід за допомогою setTimeout () . Це все.

Тобто:

<style>
    #el {
        display: none;
        opacity: 0;
    }
    #el.auto-fade-in {
        opacity: 1;
        transition: all 1s ease-out; /* Future, future, please come sooner! */
        -webkit-transition: all 1s ease-out;
        -moz-transition: all 1s ease-out;
        -o-transition: all 1s ease-out;
    }
</style>

<div id=el>Well, well, well</div>

<script>
    var el = document.getElementById('el');
    el.style.display = 'block';
    setTimeout(function () { el.className = 'auto-fade-in' }, 0);
</script>

Це було перевірено в останніх здорових браузерах. Очевидно, він не повинен працювати в Internet Explorer 9 чи новіших версіях.


1

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

@-webkit-keyframes fadeIn {
    from { opacity: 0; }
      to { opacity: 1; }
}

@-webkit-keyframes fadeOut {
    from { opacity: 1; }
      to { opacity: 0; }
}

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

jsFiddle приклад

CSS

@-webkit-keyframes pushDown {
  0% {
    height: 10em;
  }
  25% {
    height: 7.5em;
  }
  50% {
    height: 5em;
  }
  75% {
    height: 2.5em;
  }
  100% {
    height: 0em;
  }
}

.push-down {
    -webkit-animation: pushDown 2s forwards linear;
}

JavaScript

var element = document.getElementById("element");

// Push item down
element.className = element.className + " push-down";

1

Ви можете це зробити з подіями переходу, так що ви будуєте два класи CSS для переходу, один тримає анімацію, інший тримає дисплей без стану. А ви перемикаєте їх після закінчення анімації? У моєму випадку я можу знову відобразити діви, якщо натиснути кнопку та видалити обидва класи.

Спробуйте фрагмент нижче ...

$(document).ready(function() {
  // Assign transition event
  $("table").on("animationend webkitAnimationEnd", ".visibility_switch_off", function(event) {
    // We check if this is the same animation we want
    if (event.originalEvent.animationName == "col_hide_anim") {
      // After the animation we assign this new class that basically hides the elements.
      $(this).addClass("animation-helper-display-none");
    }

  });

  $("button").click(function(event) {

    $("table tr .hide-col").toggleClass(function() {
      // We switch the animation class in a toggle fashion...
      // and we know in that after the animation end, there
      // is will the animation-helper-display-none extra
      // class, that we nee to remove, when we want to
      // show the elements again, depending on the toggle
      // state, so we create a relation between them.
      if ($(this).is(".animation-helper-display-none")) {
        // I'm toggling and there is already the above class, then
        // what we want it to show the elements , so we remove
        // both classes...
        return "visibility_switch_off animation-helper-display-none";
      }
      else {
        // Here we just want to hide the elements, so we just
        // add the animation class, the other will be added
        // later be the animationend event...
        return "visibility_switch_off";
      }
    });
  });
});
table th {
  background-color: grey;
}

table td {
  background-color: white;
  padding: 5px;
}

.animation-helper-display-none {
  display: none;
}

table tr .visibility_switch_off {
  animation-fill-mode: forwards;
  animation-name: col_hide_anim;
  animation-duration: 1s;
}

@-webkit-keyframes col_hide_anim {
  0% {opacity: 1;}
  100% {opacity: 0;}
}

@-moz-keyframes col_hide_anim {
  0% {opacity: 1;}
  100% {opacity: 0;}
}

@-o-keyframes col_hide_anim {
  0% {opacity: 1;}
  100% {opacity: 0;}
}

@keyframes col_hide_anim {
  0%   {opacity: 1;}
  100% {opacity: 0;}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
  <theader>
    <tr>
      <th>Name</th>
      <th class='hide-col'>Age</th>
      <th>Country</th>
    </tr>
  </theader>
  <tbody>
    <tr>
      <td>Name</td>
      <td class='hide-col'>Age</td>
      <td>Country</td>
    </tr>
  </tbody>
</table>

<button>Switch - Hide Age column with fadeout animation and display none after</button>


0

Якщо ви використовуєте jQuery для встановлення своїх класів, це буде працювати 100%:

$(document).ready(function() {
  $('button').click(function() {
    var container = $('.container');
    
    if (!container.hasClass('active')) {
      container.addClass('show').outerWidth();
      container.addClass('active');
    }
    else {
      container.removeClass('active').one('transitionend', function() {
        container.removeClass('show');
      });
    }
  });
});
.container {
  display: none;
  opacity: 0;
  transition: opacity 0.3s ease;
}

.container.show {
  display: flex;
}
 
.container.active {
  opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type="button">Toggle</button>

<div class="container">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</div>

Звичайно, ви можете просто використовувати jQuery .fadeIn()та .fadeOut()функції, але перевага встановлення класів замість цього полягає в тому випадку, якщо ви хочете перейти на інше значення, ніж block(як за замовчуванням з .fadeIn()і .fadeOut()).

Ось я переходжу до дисплея flexз приємним ефектом згасання.


0

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

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


0

Ви можете просто використовувати видимість CSS : приховано / видно замість дисплея : none / block

div {
    visibility:hidden;
    -webkit-transition: opacity 1s ease-out;
    -moz-transition: opacity 1s ease-out;
    -o-transition: opacity 1s ease-out;
    transition: opacity 1s ease-out;
    opacity: 0;
}

parent:hover > div {
    opacity: 1;
    visibility: visible;
}

5
Це затримує простір, залишаючи порожній отвір. Якщо ви хочете обвалити простір, вам доведеться оживити висоту чи якусь іншу властивість.
Марсі Саттон

0

Я розпочав проект скелету з відкритим кодом під назвою Toggle Display Animate .

Цей помічник скелету дозволить вам легко імітувати показ / приховування jQuery, але з анімацією переходу CSS 3.

Він використовує перемикачі класів, тому ви можете використовувати будь-які потрібні вам методи CSS для елементів, крім дисплея: жоден | блок | таблиця | вбудований тощо, а також інші альтернативні варіанти використання, які можна придумати.

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

Більшість розміток для концепції, над якою я працюю, - це CSS, і насправді використовується дуже мало JavaScript.

Тут є демонстрація: http://marcnewton.co.uk/projects/toggle-display-animate/

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