Проблемы с позиционированием/рендерингом в Safari (OSX и iPad) при добавлении импульсной анимации CSS

Я хотел создать пульсирующую анимацию на вертикально и горизонтально центрированном изображении, используя анимацию CSS. Это отлично работает в Firefox и Chrome (версия для мобильных устройств и OSX). Но в сафари лажает, неправильное позиционирование изображения.

Странно то, что после переключения рабочих столов (три пальца влево или вправо) и возврата в сафари изображение позиционируется правильно.

Я создал jsfiddle, чтобы показать проблему, я пропустил все префиксы, кроме -webkit.

JSfiddle здесь: https://jsfiddle.net/stxnt1sb/9/

HTML

<article>
  <img src="http://lorempixel.com/600/400/sports/">
</article>

CSS

article{
  position:relative;
  width:600px;
  height:400px;
  overflow:hidden;
}
img{
  position:absolute;
  top:50%;
  left:50%;
  width:100%;
  -webkit-transform:translate(-50%,-50%);
  -webkit-animation-name: pulse;
  -webkit-animation-duration: 10s;
  -webkit-animation-timing-function: ease-in-out;
  -webkit-animation-iteration-count: infinite;
  -webkit-animation-direction: normal;
}
@-webkit-keyframes pulse {
  0% {
    -webkit-transform: translate(-50%, -50%) scale(1) ;
  }
  33% {
    -webkit-transform:  translate(-50%, -50%) scale(1.05);
  }
  100% {
    -webkit-transform: translate(-50%, -50%) scale(1) ;
  }
}

Изображение позиционируется абсолютно в относительном контейнере, центрированном с помощью перевода (-50%,-50%). Пульсация выполняется с помощью CSS-анимации, анимирующей масштаб изображения.


person Roy Dendro    schedule 10.02.2016    source источник


Ответы (2)


Как сказал Рикардо, движок рендеринга Safari, вероятно, вызывает сомнения. Safari определяет, что преобразованному элементу нужен составной слой. Эти слои являются специальными слоями, которые визуализируются отдельно. Я предполагаю, что Safari не обновляет составной слой после загрузки изображения.

Это оставляет несколько вариантов.

1: Установить атрибуты высоты и ширины

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

2: принудительное обновление

Пол Льюис, также известный как Aerotwist, создал триггеры CSS, список свойств CSS и того, что они вызывают. Вы можете установить свойство и вызвать перерисовку. В данном конкретном случае я не уверен, нужен ли вам макет, поэтому составной слой определяет размер своего содержимого и соответствующим образом изменяет размер, или составной слой, где слой просто меняет положение.

Есть разные способы сделать это. Вы можете установить свойство CSS, вы можете получить информацию и вызвать обновление, сделав это (например, el.getComputedStyle() и el.offsetTop), или вы можете просто сделать window.dispatchEvent(new Event('resize')). Используйте это в крайнем случае, так как они могут повлиять на производительность рендеринга.

3: Избегайте составных слоев

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

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

Метод display: table старый, но надежный. Если вы используете современные браузеры, центрирование с помощью Flexbox, вероятно, является самым простым методом.

person Tim S.    schedule 12.02.2016

Я думаю, вы можете попробовать другой подход, чем использование реального элемента <img />. Как следует из вашего кода, вы хотите масштабировать изображение в зависимости от его соотношения сторон. Однако вы сможете установить ширину или высоту только на 100%, в противном случае изображение будет растягиваться непропорционально.

К сожалению, в случае Safari я думаю, что изображение загружается после рендеринга таблицы стилей. Это оставляет движок рендеринга Safari в сомнениях относительно того, что делать с вертикальным позиционированием (поскольку высота на данный момент не установлена).

Поэтому я предлагаю заменить обычный <img /> на что-то вроде этого:

article{
  position:relative;
  width:600px;
  height:400px;
  overflow:hidden;
}
.pulsing-background{
  background-position: center center;
  background-size: cover;
  height: 100%;
  width: 100%;
  position:absolute;
  margin: 0;
  padding: 0;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  -webkit-animation-name: pulse;
  -webkit-animation-duration: 10s;
  -webkit-animation-timing-function: ease-in-out;
  -webkit-animation-iteration-count: infinite;
  -webkit-animation-direction: normal;
}
@-webkit-keyframes pulse {
  0% {
    
    -webkit-transform: scale(1) ;
   
  }
  33% {
    
    -webkit-transform: scale(1.05);
  
  }
  100% {
   
    -webkit-transform: scale(1) ;
   
  }
}
<article>
  <figure style="background-image: url(http://lorempixel.com/600/400/sports/)" class="pulsing-background"></figure>
</article>

Это гарантирует, что дочерний элемент (рисунок) всегда имеет размер своего родителя. Это семантически не идеально, и вы также можете найти решение, перейдя на Flex -Box реализации. По крайней мере, теперь вы знаете, где искать.

EDIT: Забыли добавить поле: 0; во фрагменте, чтобы сбросить стиль <figure /> по умолчанию в Safari.

person Ricardo Snoek    schedule 12.02.2016
comment
Вы по-прежнему можете размещать элементы, сохраняя их соотношение сторон (fiddle) - person Tim S.; 12.02.2016
comment
@tim-s Абсолютно! Однако это потребует от вас заранее знать размеры изображения. Я не уверен в практическом варианте использования, который имеет в виду ОП. Использование «размер фона: обложка»; работает с любым соотношением сторон и является надежным способом реализации изображений с различным соотношением сторон внутри контейнера с определенным форматом. Хотя мне не нравится использовать для этого атрибут style. - person Ricardo Snoek; 12.02.2016