Заставить браузер запускать перекомпоновку при изменении CSS

Я строю слайдер изображений, не отвечающий jQuery, на основе переходов CSS3.

Структура проста: область просмотра и внутренняя относительно расположенная UL с плавающими левыми полями.

Я сталкиваюсь с проблемой в такой ситуации:

  1. Пользователь нажимает стрелку "предыдущая".
  2. JS добавляет правильный LI перед отображаемым в данный момент узлом LI.
  3. На данный момент UL установил переход CSS как none 0s linear чтобы предотвратить изменения анимации. В этот момент я уменьшаю левое значение UL CSS на ширину слайдера (скажем, от 0px до -1200px), чтобы сделать вид таким же, как был.
  4. Теперь я изменяю свойство перехода UL на all 0.2s ease-out,
  5. Теперь я изменяю свойство left UL для запуска CSS3-анимации. (скажем, от -1200px до 0px).

В чем проблема? Браузер упрощает изменения и не создает анимации.

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

Это часть кода, делающая это (я упустил браузерные префиксы для упрощения):

ul.style.transition = 'none 0s linear 0s';ul.style.left = '-600px';ul.style.transition = 'all 0.2s ease-out';ul.style.left = '0px';

Вот скрипка, чтобы увидеть проблему в действии: http://jsfiddle.net/9WX5b/1/

2 ответа

Решение

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

function reflow(elt){
    console.log(elt.offsetHeight);
}

И называйте это там, где требуются оплавления. Смотрите этот пример: http://jsfiddle.net/9WX5b/2/

РЕДАКТИРОВАТЬ: недавно нужно было сделать это, и задавался вопросом, есть ли лучший способ, чем к console.log это. Вы не можете просто написать elt.offsetHeight как собственное утверждение, оптимизатор (по крайней мере, Chrome) не будет инициировать перекомпоновку, потому что он просто обращается к свойству без заданного метода получения, нет необходимости даже оценивать его. Итак, AFAIK самый дешевый способ сделать это void(elt.offsetHeight), так как не знает наверняка, void имеет побочные эффекты или нет. (может быть переопределено или что-то, IDK).

function reflow( element ) {
    if ( element === undefined ) {
        element = document.documentElement;
    }
    void( element.offsetHeight );
}

Он работает нормально с Chrome и FF, и, кажется, самый простой и самый портативный способ сделать это банкоматом.

Другие вопросы по тегам