Блог веб-разработчика v 1.0.0
Symfony2, AngularJS, React, Gulp, PhpStorm и много других страшных слов

Глюк transition в Firefox

10 лет назад
11462 просмотра
CSS Полезности

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

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

Что еще почитать
Создание CSS спрайтов с помощью Gulp
9 лет назад
14845 просмотров
Урок по созданию CSS спрайтов с помощью таск-менеджера Gulp. В отличие от других инструментов: средонезависимо, быстро, удобно, переносимо, настраиваемо.