Как стать автором
Обновить

Safari и фиксированное позиционирование фона страницы

Много все писали про эту тему, и уже не первый год, однако полностью подходящего мне решения найти не удалось.
Передо мной стояла задача сделать фиксированный фон у страницы для мобильных устройств. Однако, идея использовать стандартное свойство CSS body {background-attachment: fixed;} споткнулась об Mobile Safari — фоновое изображение, при прокрутке, оказывалось в верху страницы, т.е. имело стандартное положение top: 0 при использовании position: absolute;, в остальных мобильный браузерах на Android задача выполнялась успешно.

В связи с этим проблему пришлось решать более изощренным способом.


Картинка из body была вынесена в отдельный контейнер (), который был помещен перед контентом:

<body>

<div class="wrapper"></div>

  <header></header>
  <section></section>
  <footer></footer>

</body>



Для него был задан стиль:

.wrapper {
  z-index: -1;
  position: fixed;
  top: 0;
  left: 0;
  height: 100%;
  width: 100%;
  background-size: 100%;
  background-image: url('image.jpg');
}



Как мы видим из CSS, элемент получил z-index: -1; для позиционирования на самом низком уровне и фиксированное позиционирование (position: fixed;).

Т.к. средствами CSS проблему решить не удалось, пришлось прибегнуть к использованию JavaScript и, из-за большой лени, дополнительно — jQuery.

// делаем хак для мобильных устройств Apple
if (navigator.platform == 'iPad' || navigator.platform == 'iPhone' || navigator.platform == 'iPod')
    {
    
      // вешаем хэндлер на скролл
      window.onscroll = function()
      {
        // высчитываем значение текущей прокрутки позиции
        var iPadPosition = window.pageYOffset;

        // изменяем фиксированное позиционирование на абсолютное
        $(".wrapper").css("position", "absolute");
 
       //  изменяем значение позиционирования от верха
        $(".wrapper").css("top", iPadPosition);
      }
     
      // вешаем хэндлер на прикосновение пальцем к экрану
      window.ontouchstart = function () 
      {
        // возвращаем фиксированное позиционирование
        $(".wrapper").css("position", "fixed");
        // возвращаем значение позиционирования от верха
        $(".wrapper").css("top", "0");
      }

      // вешаем хэндлер на "убирание" пальца с экрана
      window.ontouchend = function () {
        // возвращаем фиксированное позиционирование
        $(".wrapper").css("position", "fixed");
      }



window.ontouchend было решено применить, когда был найден баг при пролистывании — фон «прыгал».

Также, при скролле была выявлена еще одна проблема: элемент с фоном имеет height: 100%;, а у iPhone скрываются и раскрываются верхняя и нижняя панели, из-за чего, в момент прокрутки (панели скрыты) внизу элемент заканчивался раньше окна. Не найдя про это ничего толкового (каюсь), и определив, что jQuery(window).resize() при этом не отрабатывает, пришлось сделать заточку:

    jQuery(document).ready(function(){
      $(".wrapper").css("height", jQuery(window).height()+150+'px');
    })


но для этого надо предусмотреть фон по-длиннее.



P.S. При тестировании jQuery(window).resize() на iPhone (iOS 7.1.1), и iPad 2 (iOS 7.0.4), был выявлен баг Safari!
Если вывести alert:

      jQuery(window).resize(function(){
       alert('ok');
      })


и повернуть экран — Safari намертво виснет!
Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.