Заставить браузер запускать перекомпоновку при изменении CSS
Я строю слайдер изображений, не отвечающий jQuery, на основе переходов CSS3.
Структура проста: область просмотра и внутренняя относительно расположенная UL с плавающими левыми полями.
Я сталкиваюсь с проблемой в такой ситуации:
- Пользователь нажимает стрелку "предыдущая".
- JS добавляет правильный LI перед отображаемым в данный момент узлом LI.
- На данный момент UL установил переход CSS как
none 0s linear
чтобы предотвратить изменения анимации. В этот момент я уменьшаю левое значение UL CSS на ширину слайдера (скажем, от 0px до -1200px), чтобы сделать вид таким же, как был. - Теперь я изменяю свойство перехода UL на
all 0.2s ease-out
, - Теперь я изменяю свойство 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, и, кажется, самый простой и самый портативный способ сделать это банкоматом.