Переходы в свойстве отображения CSS

В настоящее время я разрабатываю «мега раскрывающееся» меню CSS - в основном обычное раскрывающееся меню только для CSS, но содержащее различные типы контента.

На данный момент похоже, что переходы CSS 3 не применяются к свойству 'display', т.е. вы не можете выполнять какой-либо переход от display: none к display: block (или любой комбинации).

Есть ли способ для меню второго уровня из приведенного выше примера «исчезать», когда кто-то наводит курсор на один из пунктов меню верхнего уровня?

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

Я также пробовал использовать высоту, но это с треском провалилось.

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


person RichardTape    schedule 25.07.2010    source источник
comment
Работает ли переход CSS, если вы примените его к свойству непрозрачности, а не к отображению?   -  person Paul D. Waite    schedule 26.07.2010
comment
позиция: абсолютная; видимость: скрыта; такое же, как display: none;   -  person Jawad    schedule 16.09.2012
comment
@Jawad: Только если вы добавите что-то вроде z-index:0.   -  person DanMan    schedule 31.10.2012
comment
@Jawad: рекомендуется никогда не использовать visibility: hidden, если вы не хотите, чтобы программы чтения с экрана читали его (в то время как обычные браузеры этого не делают). Он только определяет видимость элемента (например, opacity: 0), и он по-прежнему доступен для выбора, кликабельности и того, чем он был раньше; это просто не видно.   -  person Forest Katsch    schedule 20.05.2013
comment
@ForestKa это не на 100% правда. вы можете сделать его невыбираемым, -clickable через css: ›pointer-events: none; поддержка разрешена   -  person honk31    schedule 06.06.2014
comment
нет поддержки pointer-events в IE 8,9,10, так что это не всегда нормально   -  person Steven Pribilinskiy    schedule 20.02.2015
comment
Вам нужно отобразить: none, иначе вы наткнетесь на скрытый объект за пределами триггера, и он будет отображаться случайно ... Я просто говорю :)   -  person Samuel Ramzan    schedule 24.12.2015
comment
Я считаю, что использование visibility: collapse вместо visibility: hidden работает   -  person user6122771    schedule 16.01.2020


Ответы (35)


Вы можете объединить два или более перехода, и на этот раз вам пригодится 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.)

Более подробная информация представлена ​​в этой статье.

person Guillermo    schedule 04.08.2011
comment
Этот ответ кажется менее трудоемким, чем другие, и дает то, что мы ожидаем от display: none / block; Спасибо. Сэкономил кучу времени. - person Brendan; 28.08.2012
comment
Да, проблема в том, что что-то за ним будет перекрываться, даже если это не видно. Я нашел использование height: 0 гораздо лучшим решением - person Josh Bedo; 03.09.2013
comment
Я обнаружил, что размер шрифта (0 - ›наследовать) может быть полезным. Похожий принцип на text-indent. - person iamkeir; 16.09.2013
comment
Это хорошо, но проблема в том, что скрытые элементы видимости по-прежнему занимают место, а отображение - нет. - person Rui Marques; 14.11.2013
comment
Анимация шоу плавная на :hover. Когда :hover удаляется, элемент скрывается без перехода (после задержки 0,5 с). Есть ли способ добиться плавной анимации в обоих направлениях? Кроме того, ссылка кажется мертвой. - person ; 17.12.2013
comment
Да, как сказал Руи, он по-прежнему занимает место, и, например, работа с выпадающими списками css стала более сложной, потому что иногда они имеют очень большую высоту и превышают высоту основного контейнера с контентом, поэтому в нижнем колонтитуле будет пустое пространство. - person Rantiev; 01.04.2014
comment
Чтобы сделать анимацию плавной при наведении и удалении указателя мыши, добавьте еще одну линию перехода к стилям наведения: transition:visibility 0s linear, opacity 0.5s linear; - это сбрасывает задержку для видимости до нуля. - person koosa; 29.06.2014
comment
Я, наверное, что-то упускаю, но почему вы меняете как видимость, так и непрозрачность? Не устанавливайте непрозрачность на 0, чтобы скрыть элемент - зачем вам также устанавливать видимость на скрытую? - person GMA; 03.07.2014
comment
Для непрозрачности также потребуются префиксы поставщиков. Что касается настройки видимости; Я считаю, что это помогает с обратной совместимостью, когда непрозрачность может не поддерживаться. - person ᴍᴀᴛᴛ ʙᴀᴋᴇʀ; 23.07.2014
comment
@GeorgeMillo, если вы установите только непрозрачность, элемент фактически все еще находится на рендеринге страницы (например, вы не можете щелкнуть мышью). - person adriendenat; 26.08.2014
comment
Префиксы поставщика @ MatthewT.Baker для непрозрачности здесь не нужны, поскольку нет браузера, поддерживающего переход css, но не свойство непрозрачности. Таким образом, он будет изящно ухудшаться, просто скрыв элемент без перехода. - person adriendenat; 26.08.2014
comment
@RuiMarques Вы можете сделать скрытый элемент также position:absolute;, а затем при наведении курсора вы можете дать ему старый добрый position:relative;. Тогда элемент не будет занимать место, когда он скрыт, но заполнит его, когда он является относительным. Я подумал, что скажу что-нибудь на будущее. - person Sam Eaton; 05.04.2015
comment
@scavaJripter Проблема с переключением между position:relative и position:absolute заключается в том, что position не может быть анимирован. Если бы это было так, вы правы, что у нас не было бы дома. Но, видя, что его нельзя анимировать, мы не в лучшем положении по сравнению с переключением display:none. Мы все равно получим довольно простой результат (по крайней мере, в одном направлении), если попробуем ваше решение. jsfiddle.net/eu4jztzr/9 - person Seldom 'Where's Monica' Needy; 01.05.2015
comment
@RuiMarques, если вы не хотите, чтобы окружающие элементы внезапно дергались, когда компонент появляется или исчезает, тогда либо он должен занимать место, когда он скрыт, либо вам все равно придется изменить его ширину или высоту на / от нуля, в этом случае я предполагаю, что вам все равно придется использовать visibility: hidden. Я почти уверен, что браузер не решит за вас, как перенести элемент, чтобы он не занимал место, когда он скрывается. - person Andy; 18.05.2015
comment
Это не следует отмечать как правильный ответ. Он не имеет отношения к свойству отображения, и, как сказал Руи, элемент по-прежнему занимает место, что делает его непрактичным во многих ситуациях. - person Ian S; 06.08.2015
comment
Отличный ответ, но я только что заметил, что переход не работает, когда установлено время 0, его нужно установить на 0s. Для меня это странно, потому что, насколько я знаю, у нуля не должно быть единиц измерения. - person sajran; 05.10.2015
comment
Это не отвечает на вопрос, как это было о свойствах отображения. Иногда вы не хотите использовать видимость, а полностью скрываете элемент из DOM. - person igorpavlov; 06.11.2015
comment
Также вы можете добавить значение задержки к visibility, например: transition: opacity 1s ease, visibility 0s ease 1s;, и убрать его при наведении transition: opacity 1s ease 0s, visibility 0s ease 0s; для анимации "in-out". - person Aureliano Far Suau; 11.12.2015
comment
Добавьте высоту 0 в нормальное состояние и переполнение скрыто, затем в состоянии наведения добавьте подходящую высоту, также следуйте советам по видимости сверху. - person Samuel Ramzan; 24.12.2015
comment
@ChristopherCliff и все остальные, я только что нашел простой способ сделать переход плавным при как при наведении, так и при наведении указателя мыши: переход visibility с одинаковой продолжительностью и функцией времени как opacity: transition: visibility 0.5s linear, opacity 0.5s linear;. Это работает из-за того, как интерполируется переход visibility: промежуточные значения устанавливаются на visible. Для получения дополнительной информации см .: developer.mozilla.org/en- США / docs / Web / CSS / и taccgl.org / blog /. - person DynamicDispatch; 07.03.2016
comment
Также см. Этот ответ @HelmutEmmelmann: stackoverflow.com/a/25338929/5249519. - person DynamicDispatch; 07.03.2016
comment
Я обнаружил, что только display и visibility могут исправить проблему мобильной производительности IE на вложенной фиксированной позиции div. Искал анимацию дисплея без javascript на none. Но на самом деле это решение также помогает исправить упомянутую мною ошибку. - person choz; 26.09.2016
comment
Почему бы просто не использовать pointer-events: none;, чтобы решить элемент, который все еще мешает проблеме? Тогда вам не придется ломать голову над непрозрачностью и видимостью, влияющими на фактическую видимость элемента. - person Arsylum; 18.02.2018
comment
@Arsylum, это нормально для несфокусируемого контента. Однако, если бы это была ссылка, поле ввода или кнопка, этот элемент все равно был бы доступен для фокусировки, если бы вы использовали pointer-events: none. - person ourmaninamsterdam; 26.03.2018
comment
@Guillermo Спасибо, и я люблю тебя. - person darth-coder; 08.07.2019
comment
Обратите внимание: если вы заботитесь о доступности (что вы, вероятно, делаете), этот ответ на самом деле совершенно неверен: не использование display:none означает, что каждый элемент с фокусировкой / индексированием табуляции все еще существует на странице, и ваши пользователи теперь будут слепо табуляцией через элементы, которые полностью невидимы. Хотя это кажется работает, на самом деле это только усугубляет ситуацию для достаточно значительной части веб-пользователей. Вместо этого вам понадобится двухэтапный процесс: отображение: без ›блока и затем затухание непрозрачности и, наоборот, затухание непрозрачности и затем отображение: блок-› нет. - person Mike 'Pomax' Kamermans; 31.03.2020

Вам нужно скрыть элемент другими способами, чтобы это работало.

Я добился эффекта, разместив оба <div> абсолютно и установив скрытый на 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;
}
person Jim Jeffers    schedule 26.07.2010
comment
Спасибо Джиму за обстоятельный ответ. Вы абсолютно правы в том, что если свойство display: вообще изменится, то ВСЕ ваши переходы не будут работать. Что жаль - мне интересно, какова причина этого. Кстати, по той же ссылке, которую я разместил в исходном вопросе, вы можете увидеть, где я нахожусь с этим. Единственная (небольшая) проблема, с которой я столкнулся, - это Chrome [5.0.375.125], когда страница загружается, вы можете видеть, как меню быстро исчезает по мере загрузки элементов на страницу. Firefox 4.0b2 и Safari 5.0 абсолютно в порядке ... ошибка или что-то, что я пропустил? - person RichardTape; 28.07.2010
comment
Я вообще не вижу переходов по этой ссылке - вы что-то изменили? Странно, что ваша проблема возникает только в Chrome. Это может быть ошибка и не ошибка с вашей стороны. - person Jim Jeffers; 29.07.2010
comment
Эээ, ага я идиот и снял стили для тестирования! Кажется, сейчас я «исправил» это, но я абсолютно не знаю, почему и как. Кажется, что это все еще происходит время от времени (возможно, тогда что-то связано с кешированными изображениями ?!). Я не уверен, что это серьезная проблема, просто время от времени на долю секунды выглядит немного «напуганным». - person RichardTape; 29.07.2010
comment
Я согласен, что это правильно, и внесу свой вклад в это; Внимание для будущих путешественников. Я нашел рабочее решение в Chrome, но обнаружил, что оно не работает на iPhone 4: visibility:hidden; opacity:0; -webkit-transition: all .2s ease-in-out; Это не только неправильно, но и целевой элемент никогда не отображается. QA подведет вас, меня и вашу маму. - person SimplGy; 05.04.2011
comment
Привет, я пытался понять это некоторое время, но какой шрифт на вашей демонстрационной странице? Спасибо. P.S. Извините, если это вырванный из контекста или глупый вопрос. - person A.M.K; 15.07.2012
comment
Вы также можете перенести свойство видимости ... просто сказав - person Cu7l4ss; 09.12.2012
comment
Если вы установите для скрытого состояния значение height: 0; и не перейдете к нему, переход не будет работать. Я пробовал это, просто пытаясь изменить непрозрачность. Пришлось удалить height: 0; - person chovy; 27.06.2013
comment
У этого есть проблемы, особенно для неактивного перехода ... см. Мой ответ ниже, чтобы узнать о решении этого (если вы можете его найти). - person Edyn; 23.10.2013
comment
вы только что выиграли голосование, потому что overflow: hidden большое вам спасибо! - person thiagoh; 18.12.2015
comment
Это должен быть лучший ответ :) Спасибо. - person www139; 28.12.2015
comment
Я думаю, что для достижения этой функции лучше использовать видимость, потому что блок display: вызывает проблему, которая загружает элемент при каждом переключении этого события. - person Jason Long; 10.05.2016
comment
Без абс высоты обратный переход не будет работать, чтобы сделать высоту автоматической, анимируйте max-height: 0 до max-height: 999px, см. Ответ @Boomstein stackoverflow.com/a/22258434/1550778 - person Mohamed Hussain; 23.08.2016
comment
Я полагаю, что лучше работать с max-height, когда вы переключаете элемент с помощью height: auto. Потому что во фрагменте, описанном в посте, свойство высоты не анимируется, когда вы меняете opacity на all в объявлении свойства transition. Чтобы анимировать высоту, вы должны использовать max-height: 0 и max-height: 9999px вот так. - person ivkremer; 02.06.2017
comment
Единственное, что с height: auto вы не сможете использовать абсолютное позиционирование с использованием процентов (просто примечание на случай, если кто-то хочет, чтобы все эти вещи были правдой) - person Moseleyi; 30.05.2018
comment
Какая фантастическая альтернатива. Я снова вошел в систему, чтобы проголосовать за это. - person terryeah; 18.09.2018
comment
Спасибо, дружище, пробовал безумные вещи и почти сдался, пока не попробовал. Было сорвано из-за того, что дисплей был испорчен. - person rbnzdave; 04.03.2020
comment
Одна (большая) проблема, если вы заботитесь о доступности (что вам следует): это на самом деле значительно ухудшает ситуацию для большого числа веб-пользователей, потому что все фокусируемые / индексируемые элементы будут все еще существовать на странице, и теперь люди, которые используют табуляцию для обхода вашей страницы, в конечном итоге перебирают невидимые элементы - person Mike 'Pomax' Kamermans; 01.04.2020
comment
Что делать, если у нас есть текстовый контейнер-брат, который занимает пространство ul, и когда ul требует вернуть свое пространство, текст внезапно сдвигается вверх. Как мы можем применить к этому переход? - person booota; 17.10.2020

На момент написания этой публикации все основные браузеры отключают переходы 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>

person Salman von Abbas    schedule 17.02.2012
comment
Спасибо за это. Упомянутый выше трюк height: 0 (для переходов), похоже, не работает, потому что высота устанавливается на 0 при переходе затухания, но этот трюк, похоже, работает нормально. - person Elliot Winkler; 15.03.2012
comment
Спасибо, очень полезно. Но как это угаснуть? - person Illiou; 15.10.2012
comment
круто, но когда я нахожу DIV во время анимации, он мерцает (меняет непрозрачность на более низкое) ... есть идеи? - person ; 01.07.2014
comment
Первый абзац этого ответа не совсем понятен. Браузеры не просто отключают все переходы сразу после того, как вы используете свойство display - на самом деле нет причин для этого. И даже если бы они сделали, почему тогда анимация будет работать? Вы также не можете использовать свойство display в анимации CSS. - person BoltClock; 11.07.2014
comment
Да, измените - я не уверен, почему я сказал использовать там. Я хочу сказать, что вы не можете выполнить переход или animate display, но это не мешает анимации всех других свойств, пока вы не переходите в none. - person BoltClock; 11.07.2014
comment
@BoltClock, к сожалению, не переходит и из: cssdesk.com/rCyBd. Это какое-то ограничение реализации. - person Salman von Abbas; 11.07.2014
comment
так что это ответ в значительной степени - person svnm; 05.05.2015
comment
на самом деле единственная проблема с этим заключается в том, что он скрывает элемент, но анимация не работает в свойстве отображения - person svnm; 05.05.2015
comment
Это быстрое и простое решение для того, что я искал. Ty. - person Dejan Munjiza; 12.10.2015
comment
Лучший ответ, невозможно с переходами, но да с анимацией. - person Mikel; 24.03.2016
comment
Как насчет обратной анимации, когда элемент должен медленно исчезать? - person Green; 23.05.2016
comment
Это было хорошим решением для моей конкретной ситуации, когда использование display было предписано существующей функциональностью JavaScript, но я хотел применить эффект затухания поверх. - person Ryan Williams; 20.06.2016
comment
@SalmanAbbas Это работает для fadeIn, но я не могу заставить его работать для fadeOut. Я просто делаю обратное тому, что вы делаете в fadeIn keyframe - person protoEvangelion; 24.01.2018
comment
Это было здорово! Мне нужно оставить display: none и display: block по причинам доступности - person spasticninja; 25.06.2018
comment
@Illiou Я открыл для этого новый вопрос. stackoverflow.com/questions/51923777/ - person phil294; 20.08.2018
comment
@ Mike'Pomax'Kamermans Пожалуйста, прочтите внимательно, прежде чем выдвигать такие наглые обвинения. В моем коде используется display: none, поэтому любой элемент когда-либо скрывается должным образом. Такие элементы никогда не могут быть в фокусе или перекрываться табуляцией. - person Salman von Abbas; 01.04.2020
comment
Так оно и есть. Однако он также полагается на наведение, но это уже другая проблема. - person Mike 'Pomax' Kamermans; 01.04.2020
comment
@ Mike'Pomax'Kamermans Ага. Возможности для улучшения с использованием :focus-within. - person Salman von Abbas; 02.04.2020

Я подозреваю, что причина отключения переходов при изменении display заключается в том, что на самом деле делает дисплей. Он не меняет ничего, что можно было бы плавно анимировать.

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

display: none, с другой стороны, фактически предотвращает рендеринг элемента полностью.
Он не занимает никакого места для макета.
Другое элементы, которые занимали бы часть или все пространство, занимаемое этим элементом, теперь приспосабливаются к тому, чтобы занимать это пространство, как если бы элемент просто не существовал вообще.

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

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

person Joel_MMCC    schedule 15.06.2012
comment
Это правильно. Это не сразу очевидно, но как только вы задумаетесь об этом, вам не понадобится много времени, чтобы понять, что изменение свойства display не может работать. - person BoltClock; 11.07.2014
comment
Какими бы хорошими ни были приведенные выше решения, было очень приятно получить разумное объяснение того, почему переходы не применяются к атрибутам отображения. - person kqr; 17.09.2014
comment
Я не согласен. Это могло иметь смысл. Если display: none to display: block возник сразу в начале перехода, это было бы здорово. И для перехода назад, если бы он перешел с display: block на display: none прямо в конце перехода, это было бы идеально. - person Curtis Yallop; 02.06.2015
comment
Если вы не можете себе представить, как выглядит анимация от точки до прямоугольника, у вас проблемы. Переход от отсутствия места к использованию прямоугольного пространства ОЧЕНЬ очевиден, например, вы делаете это каждый раз, когда вытаскиваете прямоугольник с помощью мыши, как и любое другое приложение. В результате этого сбоя появилось так много хаков, связанных с максимальной высотой и отрицательными полями, что это просто смешно. Единственное, что работает, - это кеширование «реальной» высоты, а затем анимация от нуля до кешированного значения с помощью JavaScript. Грустный. - person Triynko; 16.03.2017
comment
Tryniko: display: none не изменяет размер элемента до прямоугольника 0 x 0 - он удаляет его из DOM. Вы можете анимировать прямоугольник в точку, анимируя свойства ширины и высоты до нуля, а затем другие элементы будут обтекать его, как если бы он имел 'display: none', но его атрибут 'display' остался бы 'block'; элемент все еще находится в DOM. Концепция анимации между display: block и display: none является нелепой: здесь нет промежуточных состояний. Элемент либо существует в DOM, либо нет, независимо от того, насколько он мал или невидим. - person Steve Thorpe; 07.05.2017
comment
Анимировать дискретные свойства - это не смешно. К дискретным свойствам, таким как display, нельзя переходить плавно, как к другим свойствам, но это не означает, что время не важно. Очень важно иметь возможность контролировать когда переход от disply:block к display:none. Так же, как это описал @CurtisYallop. Если я хочу перейти с opacity:1 на opacity:0 и , тогда сменить display:block на display:none, я смогу это сделать. - person Jens; 12.04.2018
comment
Свойство display можно эффективно использовать в переходах, оно всегда должно изменять режим отображения в конце перехода, если для него установлено значение none, и всегда в начале, если установлено значение любого видимого режима. Я полагаю, это решило бы проблему каждого, кто читает эту ветку. - person thomallen; 17.06.2021

Вместо обратных вызовов, которых нет в 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. В таких случаях элемент по-прежнему занимает место на странице, и это не всегда подходит.

Дополнительные примеры см. В этой статье .

person Webars    schedule 26.05.2018
comment
удивлен, что у него не так много голосов - это умное решение как-то отлично работает. - person fanfare; 19.06.2018
comment
Он работает только с height:100%, что в некоторых случаях может разрушить макет. Отличное решение, если не проблема. Один из немногих двунаправленных рабочих. - person Fabian von Ellerts; 11.10.2018
comment
Отлично! В моем случае мне удалось еще больше упростить его, потому что я хотел, чтобы время затухания анимации было таким же, как время затухания. Вместо того, чтобы использовать transition: height 0ms 0ms, opacity 600ms 0ms, я просто использовал transition-delay: 0s. - person Jacob Lockard; 26.05.2020
comment
Это потрясающее решение. - person Bulent; 17.09.2020

display не является одним из свойств, над которыми работает переход.

См. Анимированные свойства CSS для список свойств CSS, к которым можно применить переходы. См. Модуль значений и единиц CSS, уровень 4, Объединение значений: интерполяция, добавление и "Накопление" для их интерполяции.

До CSS 3 было указано в 9.1. Свойства из CSS (просто закройте всплывающее окно с предупреждением)

Я также пробовал использовать высоту, но это с треском провалилось.

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

person robocat    schedule 22.09.2011
comment
Ссылка больше не указывает прямо на раздел анимированных свойств. - person Andrew Lam; 20.11.2018

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

@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, но все еще исчезает.

person Manish Pradhan    schedule 29.07.2014
comment
Должен ли myfirst быть showNav здесь? А что насчет Firefox? К сожалению, я не могу найти что-то похожее на демо-странице, о которой вы говорите. - person Sebastian vom Meer; 16.09.2014
comment
Спасибо @SebastianG. Я внес исправления и добавил дополнительную информацию выше. - person Manish Pradhan; 16.09.2014
comment
@Sebastian vom Meer: более ранние версии Firefox нуждаются в префиксе поставщика -moz-, см. Отредактированный код - person Herr_Schwabullek; 18.06.2015
comment
@Herr_Schwabullek Я не согласен с тем, что этот тип устаревшего кода должен быть добавлен в пример. Firefox использует версию без префикса с 2012 года и больше даже не упоминает префикс в документации: developer.mozilla.org/en/docs/Web/CSS/@keyframes. Для полноты это можно отметить после примера кода. - person Sebastian vom Meer; 19.06.2015
comment
@Sebastian vom Meer Я не вижу здесь проблемы ... если вы хотите поддерживать старые версии firefox (я полагаю, что ваш предыдущий комментарий здесь ошибочен), нет большой проблемы при использовании этого префикса поставщика. Этот префикс -moz- все еще упоминается на developer.mozilla.org/en -US / docs / Web / CSS / animation, например - person Herr_Schwabullek; 19.06.2015
comment
@Herr_Schwabullek Это не проблема, только мое мнение: я бы больше не стал добавлять специальный код для таких старых браузеров с долей рынка менее 0,0%. - person Sebastian vom Meer; 22.06.2015
comment
Если я чего-то не упустил, демонстрационная ссылка больше не показывает переход подменю. - person Realistic; 17.11.2015
comment
Правильный переход для чего-то, что не занимает места (как в случае с display: none), к тому, что занимает место (display: block), - это расширение измерений, а не постепенное появление. Если бы видимость была скрытой (которая занимает пространство, но не видна) для видимой, то размер остается прежним, и подходит постепенное появление. Ни один из этих ответов не решает проблему. - person Triynko; 16.03.2017

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

.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)
     }
}
person ThisIsWilliam    schedule 15.12.2019
comment
Спасибо за этот полезный совет. Он работает отлично. - person Sedat Kumcu; 12.05.2020

Согласно Рабочий проект W3C от 19 ноября 2013 г. display не является свойство animatable. К счастью, 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, она останется интерактивной.

person feklee    schedule 02.02.2014
comment
я вообще не вижу перехода в примере jsfiddle - person Gino; 26.10.2016
comment
@Gino Я исправил это, изменив 0 на 0s. Судя по всему, в прошлом браузер, который я использовал для тестирования, поддерживал безразмерный ноль раз. Однако безразмерное время не является частью рекомендации кандидата W3C. , 29 сентября 2016 г.. - person feklee; 27.10.2016
comment
За это следует проголосовать больше. Я нашел это одним из лучших решений. - person Arthur Tarasov; 13.07.2017
comment
Использование задержки - лучшая логика, чтобы понять, как это работает. Анимируйте и прячьте. Показать и оживить. Идеальное решение для меня - person Bruno Pitteli Gonçalves; 30.09.2018

Изменить: display none в этом примере не применяется.

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

Что происходит выше, так это то, что 99% отображения анимации настроено на блокировку, а непрозрачность исчезает. В последний момент для свойства display установлено значение none.

И самый важный момент - сохранить последний кадр после окончания анимации с помощью animation-fill-mode: forwards

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

Вот два примера: https://jsfiddle.net/qwnz9tqg/3/

person Pawel    schedule 30.10.2015
comment
с этим решением display: none тогда не работает? - person Bart Calixto; 23.01.2016
comment
Должно быть 'animation-fill-mode: forward', а не 'forward'. - person Alex; 10.03.2016
comment
Изменения должны состоять из шести символов, и я могу только предложить редактировать, поэтому комментарий - person Alex; 10.03.2016
comment
@ Alex Хорошо. Опечатка исправлена. Интересно то, что мой ответ даже не работает так, как ожидалось, но логично думать, что это будет, поэтому я сохраню его, пока браузеры не будут его поддерживать. - person Pawel; 14.03.2016
comment
Как вы можете видеть в этой скрипке с установленными курсорами, display: none на самом деле никогда не реализуется. jsfiddle.net/3e6sduqh - person robstarbuck; 18.08.2017

Мой изящный трюк с 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;
}

Пока это работает!

person Sasa Milenkovic    schedule 14.12.2012
comment
Это работает из-за временной задержки, а не потому, что команды javascript находятся в отдельных функциях. Временные задержки кажутся хорошим решением во многих случаях :) - person ; 04.05.2015

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

Я также использовал от height: 0 до height: 100%, но он работал только при появлении модального окна. Это то же самое, как если бы вы использовали left: -100% или что-то в этом роде.

Тогда меня осенило, что есть простой ответ. И вуаля:

Во-первых, скрытое модальное окно. Обратите внимание, что height - это 0, и проверьте объявление height в переходах ... у него есть 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;
}

Вот и все, это работает как шарм.

person hotmeteor    schedule 19.04.2012
comment
Голосование за ваш стиль согласования свойств с префиксом поставщика ???? - person George Green; 17.05.2017

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

person Edyn    schedule 23.10.2013
comment
Хороший трюк, но у него есть недостаток. Время перехода зависит от высоты. Если есть несколько меню с переменной высотой, элементы с высотой, близкой к max-height, будут хорошо анимированы. Однако более короткие будут анимироваться слишком быстро, что приведет к противоречивому восприятию. - person user; 14.02.2016

Я сталкивался с этой проблемой несколько раз и теперь просто решил:

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

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

При добавлении класса block--invisible все элементы не будут доступны для кликов, но все элементы, стоящие за ним, будут из-за pointer-events:none, который поддерживается всеми основными браузерами (без IE ‹11).

person DominikAngerer    schedule 07.08.2017
comment
Не могли бы вы привести это в пример? - person GarethAS; 05.09.2017
comment
Это работает хорошо, но следует отметить, что события-указатели не работают с IE ниже 11. - person user1702965; 03.06.2018
comment
добавлено примечание для IE ниже 11 - person DominikAngerer; 04.06.2018
comment
Если вам нужно, чтобы упомянутый элемент был поверх всего (например, меню), это, честно говоря, самый чистый способ сделать это сейчас, когда в 2019 году надежная поддержка для pointer-events - person Josh Davenport; 25.10.2019

Измените 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.

person jesus    schedule 09.09.2012
comment
Это был билет для меня. Спасибо! - person dwlz; 19.08.2018

Я наконец нашел для себя решение, объединив opacity с position absolute (чтобы не занимать место в скрытом состоянии).

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

.parent:hover .toggle {
  opacity: 1;
  position: static;
}
person Damjan Pavlica    schedule 16.10.2017
comment
да, я тоже добавил z-index: -1. - person Hebe; 25.10.2020

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

person mindfullsilence    schedule 12.05.2014
comment
Подобно этому, вы можете установить высоту строки в тексте и преобразовать ее в ноль. Если внутри будет только текст, это скроет контейнер. - person vicmortelmans; 12.12.2014
comment
Почему так мало голосов? Это действительно хороший ответ, и, возможно, я использую его. - person mwilcox; 17.07.2017
comment
@mwilcox Потому что он использует фиксированную высоту, что плохо при работе с динамическим контентом (даже приблизительная высота). И это полезно только для текстового контента. - person Fabian von Ellerts; 11.10.2018

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

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

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

Работающую версию см. В моем сообщении в блоге Переход CSS Видимость.

W.r.t. заголовок вопроса «Переходы на дисплее: свойство» и в ответ на комментарии Руи Маркеса и Джоша к принятому ответу:

Это решение работает в тех случаях, когда не имеет значения, используется ли свойство display или visibility (как, вероятно, имело место в этом вопросе).

Он не удалит полностью элемент как display:none, просто сделает его невидимым, но он все равно останется в потоке документов и влияет на положение следующих элементов.

Переходы, которые полностью удаляют элемент, аналогичный display:none, могут быть выполнены с использованием высоты (как указано в других ответах и ​​комментариях), максимальной высоты или поля сверху / снизу, но также см. Как я могу изменить высоту: 0; по высоте: авто; используя CSS? и мое сообщение в блоге Обходные пути для переходов CSS в свойствах отображения и высоты.

В ответ на комментарий Джорджа Милло: необходимы оба свойства и оба перехода: свойство opacity используется для создания анимации постепенного появления и исчезновения, а свойство видимости позволяет избежать реакции элемента на события мыши. Переходы необходимы для непрозрачности для визуального эффекта и для видимости, чтобы отложить скрытие до тех пор, пока не закончится постепенное исчезновение.

person Helmut Emmelmann    schedule 16.08.2014

Это очень просто :)

@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;. Также не забудьте использовать форварды, чтобы он оставался в конечном состоянии.

person vSimak    schedule 29.05.2019
comment
Это мгновенно сбрасывается при удалении класса, поэтому это не очень хорошая идея. - person Sean T; 01.08.2019

Увеличьте его с помощью CSS-анимации:

.item {
     display: none;
}

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

@keyframes fadeIn {
     from {
          opacity: 0;
     }

     to {
          opacity: 1;
     }
}
person nCardot    schedule 15.02.2021

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

Затем, чтобы постепенно усилить его, добавьте еще один класс CSS, например «on», который устанавливает непрозрачность на 1 и определяет переход для непрозрачности. Как вы, возможно, догадались, вам придется использовать JavaScript, чтобы добавить этот класс «on» к элементу, но, по крайней мере, вы все еще используете CSS для фактического перехода.

P.S. Если вы оказались в ситуации, когда вам нужно одновременно сделать и display:block, и добавить класс «on», отложите последнее с помощью setTimeout. В противном случае браузер просто видит обе вещи как происходящие одновременно и отключает переход.

person Larry Gerndt    schedule 25.02.2012
comment
Отлично, спасибо! Я написал еще один ответ с примером, который действительно работает с display:none. - person mojuba; 31.08.2012

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

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

Начиная с коробки вроде:

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

Скрытый ящик.

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

Мы собираемся использовать трюк, найденный в связанных q / a, проверяя offsetHeight, чтобы мгновенно задросселировать браузер:

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.

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

Обратите внимание, что приведенное выше не устанавливает для отображения значение «none» снова в конце анимации постепенного затухания. Хотя мы можем стать красивее. Давайте сделаем это с тем, что исчезает и растет от 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, где его легко найти / разрешить другими кодировщиками, строящими поверх этого.

person Chris Moschini    schedule 15.06.2016

Простейшее универсальное решение проблемы: не стесняйтесь указывать display:none в своем CSS, однако вам придется изменить его на block (или что-то еще) с помощью JavaScript, а затем вам также придется добавить класс к рассматриваемому элементу. который фактически выполняет переход с setTimeout (). Это все.

I.e.:

<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 или более ранней версии.

person mojuba    schedule 30.08.2012
comment
хороший, работает! можете ли вы объяснить, почему использование setTimeout имеет значение? - person OfirD; 23.08.2020
comment
@OfirD setTimeout есть, поэтому он запускается в следующем тике после, он стал блоком - person Mahaveer; 03.10.2020
comment
Обратите внимание, будущее уже здесь. - person agm1984; 08.02.2021

У этого решения отличная совместимость, и я его еще не видел:

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

person Christophe Marois    schedule 04.05.2016
comment
Но изменение position все равно заставит элемент дергаться, не так ли? - person Arsylum; 18.02.2018
comment
Ну, конечно: position: absolute означает, что элемент не занимает места, как описано в объяснении. Когда он переключается на position: static и появляется, он займет место, как обычный элемент, о чем и идет речь в этом вопросе. Предлагаю вам попробовать! - person Christophe Marois; 19.02.2018
comment
Я сделал. Но если я правильно понимаю, вопрос был о переходах. Как в плавных анимациях. - person Arsylum; 20.02.2018

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

person Deadmano    schedule 29.04.2019

Думаю, у SalmanPK есть наиболее близкий ответ. Он действительно добавляет или исчезает элемент со следующими CSS-анимациями. Однако свойство display не анимируется плавно, только непрозрачность.

@-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";
person svnm    schedule 05.05.2015

Вы можете сделать это с помощью событий перехода, поэтому вы создаете два класса CSS для перехода, один из которых содержит анимацию, а другой - состояние display none. А вы их переключаете после окончания анимации? В моем случае я могу снова отобразить div, если я нажму кнопку и удалю оба класса.

Попробуйте приведенный ниже фрагмент ...

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

person Miguel    schedule 16.03.2017

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

.className{
  visibility:hidden;
  opacity: 0;
  transition: .2s;
  width:0;
}

.className:hover{
  visibility:visible;
  margin-right: .5rem;
  opacity: 1;
  width:unset;
}
person AdibTE    schedule 01.10.2020

Если вы используете 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 с красивым эффектом затухания.

person MAXIM    schedule 26.10.2018

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

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

person Community    schedule 25.07.2010

Вы можете просто использовать CSS видимость: скрытый / видимый вместо display: 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;
}
person foxdanni    schedule 23.01.2013
comment
Тем не менее, это резервирует пространство, оставляя пустое отверстие. Если вы хотите свернуть пространство, вам нужно анимировать высоту или другое свойство. - person Marcy Sutton; 18.09.2013

Вы также можете использовать это:

.dropdown {
    height: 0px;
    width: 0px;
    opacity: .0;
    color: white;
}
.dropdown:hover {
    height: 20px;
    width: 50px;
    opacity: 1;
    transition: opacity 200ms;
    /* Safari */
    -webkit-transition: opacity 200ms;
}
person Community    schedule 24.07.2013

Я начал скелетный проект с открытым исходным кодом под названием Toggle Display Animate .

Этот помощник по скелету позволит вам легко имитировать отображение / скрытие jQuery, но с анимацией перехода CSS 3.

Он использует переключатели классов, поэтому вы можете использовать любые методы CSS для элементов, кроме display: none | block | table | inline и т. Д., А также другие альтернативные варианты использования, которые можно придумать.

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

Большая часть разметки для концепции, над которой я работаю, - это CSS, а на самом деле используется очень мало JavaScript.

Здесь есть демонстрация: http://marcnewton.co.uk/projects/toggle-display-animate/

person Marc    schedule 15.07.2017

Я ценю все ответы. Вот что я использую для аналогичных целей: переход против анимации.

Пример: https://jsfiddle.net/grinevri/tcod87Le/22/.

<div class="animation"></div>
<div class="transition"></div>
@keyframes animationTo {
  0% { background-color: rgba(0, 0, 0, 0.1); }
  100% { background-color: rgba(0, 0, 0, 0.5); }
}

@keyframes animationFrom {
  0% { background-color: rgba(0, 0, 0, 0.5); }
  100% { background-color: rgba(0, 0, 0, 0.1); }
}

.animation,
.transition{
  margin: 5px;
  height: 100px;
  width: 100px;
  background-color: rgba(0, 0, 0, 0.1);
}

.animation{
  animation: animationFrom 250ms;
}

.animation:hover{
  background-color: rgba(0, 0, 0, 0.5);
  animation: animationTo 250ms;
}

.transition{
  transition: background-color 250ms;
}

.transition:hover{
  background-color: rgba(0, 0, 0, 0.5);
}
person Roman Grinev    schedule 22.06.2021

С этим можно справиться, используя функции времени перехода step-end и step-start.

Например: https://jsfiddle.net/y72h8Lky/.

$(".run").on("click", function() {
    $(".popup").addClass("show");
});
$(".popup").on("click", function() {
    $(".popup").removeClass("show");
})
.popup {
    opacity: 0;
    display: block;
    position: absolute;
    top: 100%;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 1450;
    background-color: rgba(0, 175, 236, 0.6);
    transition: opacity 0.3s ease-out, top 0.3s step-end;
}
.popup.show {
    transition: opacity 0.3s ease-out, top 0.3s step-start;
    opacity: 1;
    top: 0;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="popup"></div>
<button class="run" style="font-size: 24px;">Click on me</button>

person Andrey Izman    schedule 02.06.2017