Как стать автором
Обновить

Комментарии 42

Два forced layout на операцию — ну такое… Хотя сильно лучше тут, кажется, не выйдет, да (сам с подобной задачей возился полгода назад).

Реализация на javascript была исключена
Опишем обработчик события onClick для elToggle:
image
Имелась ввиду реализация самой анимации, например, с использованием requestAnimationFrame() для уменьшения/увеличения height, + поддержка timing-functions

Лайфхак — можно просто анимировать max-height с ease-in/out в зависимости от направления.

Ну такой себе лайфхак. Тоже требует знания высоты, иначе будет довольно неудачная анимация.

Достаточно знать приблизительную высоту для настройки скорости.

Если знать только приблизительную, то вот эту ошибку будет заметно всё-равно. Да и приблизительную тоже надо как-то считать

Ничего подобного. Делаете max-height 10000px и будет плавная анимация с 0 до высоты блока и обратно. Никаких рывков и прочего. 10к конечно выглядит не супер масштабируемо но вряд ли будет меню с такой высотой.

Работу с element.style.height === '0px' я б заменил на работу с каким-нибудь классом, например,


.is-collapsed {
  height: 0;
}

А layout-триггеры можно заменить на requestAnimationFrame (но с небольшим кроссбраузерным хаком):


function onSchedule(fn) {
  /* да, здесь два requestAnimationFrame */     
  requestAnimationFrame(function() {
    requestAnimationFrame(function() {
      fn();
    });
  });
}

Полный пример — https://jsfiddle.net/95tnmdyr/

Просветите меня кто-нибудь. Зачем 2 вложенных requestAnimationFrame?

Jake Acrhibald показывает пример, почему нужно 2-а requestAnimationFrame.

НЛО прилетело и опубликовало эту надпись здесь
Не хочется кидать камни — но ведь автор явно в начале статьи описывал причину его отказа от `max-height`, или я не прав?..
Конечно, в 90% случаев, думаю, обычного `max-height: 5000px` вполне хватит. Но когда Вы разрабатываете переиспользуемые компоненты с четко описаными требованиями и динамическим контентом — не факт, что Вы не будете в числе 10%.
НЛО прилетело и опубликовало эту надпись здесь
Конечно, в 90% случаев, думаю, обычного `max-height: 5000px` вполне хватит
И какое время анимации задавать для такого max-height? Более того, при возвращении max-height:5000 => max-height:0 — будет страшный лаг во время клика. То есть у нашего списка высота, допустим, 250 пикселей. Нажимаем кнопку, оно начинает анимироваться 0.9 секунд з max-height:5000 до max-height:250, а для пользователя это выглядит как тормоза, а потом за 0.1 секунды резко скрывается. Халтура, а не решение

Вы зря проигнорировали мою ремарку про анимационные функции.

ease-in/ease-out? Они никак не решают этой проблемы. Может слегка уменьшают. Очень мало уменьшают

Во многих случаях достаточно уменьшают.

Та почти во всех случаях они влияют минимально. Более того, невозможно адекватно настроить easing. Для уменьшения много=>ноль при использовании max-height не настраивается ease-in, дл увеличения — ease-out. Выглядит, как результат — отвратительно любому человеку со вкусом
Мне вот интересны аргументы того, кто минусовал. Использование max-height обрезает или начало (в одну сторону) или конец (в другую). Соответствуенно, функции изинга, которые ответственны за начало и конец — работают некорректно
И что тут нормового? Они все открываются за разное, неконтролируемое время. ease-out нету ни на открытии, ни на закрытии (конечно, в коде есть, а визуально — нету).

Такое сырое решение подойдёт разве что в качестве заглушки: «смотрите, тут потом будет нормальная анимация закрытия, но пока и так сойдёт»
И что тут нормового?

Можете провести опрос у пользователей и спросить норм или не норм.


Они все открываются за разное, неконтролируемое время.

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


ease-out нету ни на открытии, ни на закрытии (конечно, в коде есть, а визуально — нету).

Оно там и не надо. Или вы считаете, что все анимации должны быть ease-in-out?


Такое сырое решение подойдёт разве что в качестве заглушки: «смотрите, тут потом будет нормальная анимация закрытия, но пока и так сойдёт»


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

О! Ну раз вы прикольную картинку нашли, то однозначно правы. Ведь подмена тезиса, уход в крайности, сравнивание оппонента с белками-истеричками — это ведь так умно и оригинально (на самом деле нет)

Время появления любого элемента напрямую зависит от его позиции
Хуже, что оно неконтролируемое.

Оно там и не надо. Или вы считаете, что все анимации должны быть ease-in-out?
Я считаю, что это должен решать разработчик, а не плохой технический костыль.

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

Вы преувеличиваете масштаб трагедии. Из-за чего для реализации простой вещи потратите куда больше времени на написание кода и вылавливание в нём багов. Но никто ваши старания не оценит.

А я считаю, что вы — преуменьшаете. Из таких мелочей в итоге получается хороший или халтурный продукт.

Вот так звездолёты и получаются, которые то и дело ломаются, которые очень сложно поддерживать, и которые свою основную функцию выполняют абы как, потому, что разработчик большую часть времени разработки потратил не на её проработку, а на вылизывание вещей, на которые пользователю плевать — он ваше приложение открывает не на физически точные анимации любоваться.

Я сочувствую, что у вас такие продукты. Я слышал, что не у всех получается разработка.

Хорошо, что у меня нет таких проблем с качеством.
Добавлю, что именно халтурный подход к разработке приводит к продуктам, которые часто ломаются и которые свою основную функцию выполняют абы как, ведь:

1. «Пользователям это не нужно»
2. «Этого пользователь точно не заметит»
3. «Никогда не будет такого флоу у пользователя»
4. «Такие данные никогда не придут»
5. «На этот баг никто не обратит внимание»

Вместо акцента на качестве разработчик выбирает Lazy Driven Development, а все замечания списывает на «вы просто неправильный пользователь», «и вы неправильный пользователь», пока не остаются только три правильных пользователя

На самом же деле, пользователям это оказывается нужно, пользователи всё замечает, они выбирают не те флоу, которые кажутся программисту правильными и вводят совершенно неожиданные данные, а баги оказываются критикалами.

Ага, мы тут все говнокодеры, а вы один д'артаньян, который пишет код любой сложности без багов за разумное время. Я безмерно рад за вас. Давайте на этом закончим наш бессмысленный диалог.

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

Нормально работает. Выбирая между выкатить новую бизнес-функцию или "идеально разворачивающееся меню" почти во всех реальных бизнес случаях бизнес выберет функцию. Если это не какое-то критически важное место в системе, без которого ну совсем никак. Кода 10 строк, ломаться нечему, работает более менее — норм же. Не идеально, а приемлемо.


https://easings.net/en можно еще функцию подобрать более подходящую

Такому бизнесу отлично зайдёт решение с `display:block`, заодно не будет зря нагружать халтурными анимациями компьютер пользователя

Строго говоря да :) но анимации не такие уж прям халтурные, справедливости ради.

Спасибо, интересное решение. Но весь смысл статьи теряется из-за, того что вы не объясняете зачем тут вообще нужна строка:
window.getComputedStyle(elBlock, null).getPropertyValue("height");

Было бы очень полезно если бы вы это описали. Кстати эту строку можно заменить на эту:
elBlock.clientHeight;
Если блок развёрнут, его height=auto, а для перехода необходимо конкретное значение, которое получаем через scrollHeight. Затем нужно пересчитать («применить») height, для этого используется getComputedStyle() (MDN: getComputedStyle).

Да, действительно, можно использовать clientHeight, его вызов «применяет» текущее значение height. Благодарю за совет!



Рисунок — Отличия между offsetHeight, clientHeight и scrollHeight
тьфу блин. я думал действительно будет рассказано про переход height от 0 до auto. а тут очевидное решение про от 0 до scrollHeight. ничего нового. зачем обманывать.

Никогда не понимал зачем писать рядом с нулём единицы измерения. Если скалярная величина 0, то какая нам разница чего 0. 0px? А если не указывать px, то всё пропало?

Разницы никакой. Если не указать px, сравнение (elBlock.style.height === "0px") не сработает, т.к. при чтении свойства возвращается "0px", даже если перед этим задать ему "0".
Для моих целей помогает добавление к классу .visible — padding-top/padding-bottom. Анимация применяется к ним, создавая плавное раскрытие/скрытие.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации