Дисклеймер: хотел создать скромный пост, а не статью, но не справился с управлением новым редактором. А старый редактор не поддерживает посты.
Допустим, у нас есть блок (скажем, бутстраповская ячейка <div class="col-12">
) и мы хотим её схлопывать (скажем, по клику на кнопке).
Пишем пару простых классов:
:root { … --fast: 0.4s; --all-fast-ease: all var(--fast) ease; … } .all-fast-ease { transition: var(--all-fast-ease); } .collapsed { overflow: hidden; height: 0; }
Помечаем наш блок классом all-fast-ease
, чтобы он сворачивался плавно:
<div class="col-12 all-fast-ease">
Затем добавляем класс collapsed
в коде обработчика (везде используется jQuery):
$('.contact-form .hugh-mann-detector').on("click", function () { … if (100 == progressValue) // Пять кликов, progressValue += 20 { $(this) .data('is-hugh-mann', true) .parent().addClass('collapsed'); } }
И… ничего не происходит. Всё правильно: мы пытаемся анимировать высоту (height
) к значению 0
из значения auto
. А для этого нам требуется явно сообщить о своих намерениях:
.collapsed { overflow: hidden; height: 0; interpolate-size: allow-keywords; /* Chrome 129+ */ }
Значение allow-keywords
поддерживается в Chrome и Edge уже пару версий, и, надо полагать, Firefox с Safari тоже скоро подтянутся.
Однако, если блок содержит элементы управления (а в нашем случае он содержит кнопку), нас ждёт сюрприз. Оформить «детектор Чела Века» (.hugh-mann-detector
) именно как кнопку нужно из соображений accessibility. Во-первых, до неё должно быть можно добраться при помощи клавиатуры (Tab
), если человеку трудно двигаться. Во-вторых, скринридер должен сообщить о наличии кнопки, которую можно нажать.
Но именно по этой причине кнопка, даже скрытая в блоке нулевой высоты, крадёт клавиатурный фокус. А это говорит о том, что свёрнутый блок надо скрывать полностью, например, задав ему display: none
.
Первым делом хочется написать setTimeout
и отложенно добавить к нашему блоку класс d-none
.
Проблема в том, что для этого нам нужно как-то найти время анимации. Конечно, можно просто явно указать значение (400 миллисекунд), благо мы сами описали анимацию.
Но это нарушит принцип DRY («не сотвори себе копипасту»). Проблема осложняется тем, что у нас период времени вынесен в отдельную переменную (--fast
), и если мы будем определять её значение, а в разметке all-fast-ease
будет заменён на какой-нибудь all-slow-ease
, мы об этом не узнаем. Другое осложнение в том, что значение придётся парсить, чтобы получить миллисекунды.
А это значит, что лучше всего анимировать display
там же, где происходит и схлопывание. Да, с августа теперь так можно! Создадим специализацию для быстро-анимированного-свёрнутого блока:
.collapsed.all-fast-ease { transition: var(--all-fast-ease), display var(--fast) ease allow-discrete; }
Теперь display
будет анимироваться наравне с высотой, поскольку мы задали поведение allow-discrete
. Можно было бы просто объединить его с прочими анимациями (вписав allow-discrete
в конец переменной --all-fast-ease
), но это нарушило бы ещё один принцип: указывать только то, что нужно (так получается более универсальная стилизация с меньшим количеством сюрпризов).
И теперь вместо setTimeout
достаточно написать в обработчике события:
.parent().addClass('collapsed d-none');
Результат вы видели на КДПВ.
ссылка на оригинал статьи https://habr.com/ru/articles/870172/
Добавить комментарий