Рано или поздно вы столкнетесь с тем, что transition в Firefox просто не будет работать. Без видимых на то причин и ошибок в коде, при том, что в других браузерах (даже ИЕ) все отлично. Так в чем может быть причина?
Самая распространенная ошибка. У вас может быть не задано начальное значение изменяемого параметра. Рассмотрим пример:
.cls {
transition:all 0.5s ease;
position: absolute;
}
div:hover > .cls {
left:100px;
}
Такой transition будет работать везде, кроме Firefox, т.к. не задано начальное значение left (пусть даже там ноль, все равно нужно его задать). Стоит задать left:0; и все отлично работает:
Итак. Начальное значение изменяемого свойства нужно задавать всегда, даже если это ноль или какое-то стандартное значение.
P.S. Похоже, что последний (37) Chrome так же перенял эту баго-фичу.
Предыдущий баг хорошо расписан на stackoverflow и вряд ли кого-то сейчас удивит, а этот люди замечают крайне редко и найти решение становится проблематично.
Если у родительского блока меняется позиционирование (position), то внутренние элементы не будут анимироваться через transition (баг замечен только в Firefox). И снова пример:
.cls2-wrapper {
position: relative;
}
.cls2-parent {
position:relative;
}
.cls2 {
transition:all 0.5s ease;
position: absolute;
left:0;
top:0;
}
.cls2-wrapper:hover .cls2-parent {
position:absolute;
}
.cls2-wrapper:hover .cls2 {
left:100px;
}
Если вы откроете пример выше в Firefox, то красный блок не будет анимироваться при наведении. Дело в том, что при смене position у элемента, Firefox сбрасывает все transition у дочерних элементов и они просто не срабатывают. Решить эту проблему на чистом CSS уже не получится, т.к. нужно добавлять класс в другом потоке. В общем, проще объяснить кодом:
.cls3-wrapper {
position: relative;
}
.cls3-parent {
position:relative;
}
.cls3 {
transition:all 0.5s ease;
position: absolute;
left:0;
top:0;
}
.cls3-wrapper:hover .cls3-parent {
position:absolute;
}
/** Вместо ховера мы используем класс,
который ниже добавляем с помощью JS **/
.cls3-wrapper .cls3.fix {
left:100px;
}
$(function() {
$('.cls3-wrapper').hover(function() {
setTimeout(function() {
$('.cls3-wrapper .cls3').addClass('fix');
});
}, function() {
setTimeout(function() {
$('.cls3-wrapper .cls3').removeClass('fix');
});
});
});
Итак, что здесь происходит. По ховеру мы добавляем к элементу класс, за ссчет которого будет срабатывать transition. Это нужно делать именно через setTimeout, т.е. не в потоке события hover. Иногда рекомендуют поставить задержку в ~50ms, но у меня заработало и без задержки.
Конечно, подобное поведение встречается довольно редко, но это вполне реальный случай. Например, сегодня я с ним столкнулся при верстке плавающего меню, которое имеет измененный шаблон в "плавучем" состоянии.