Хождение по мукам: верстка для Safari под iOS (ч.1)

в 10:02, , рубрики: css, html, iOS, javascript, safari, Веб-разработка, верстка, мобильные устройства, метки: , , , ,

Хождение по мукам: верстка для Safari под iOS (ч.1)

Введение:

Доброго дня!

Работая в успешной веб-студии, ориентированной на западный рынок, практически не существует проекта, в ТЗ к которому нет строки «корректное отображение на мобильных устройствах». Под мобильными устройствами в данном случае подразумеваются смартфоны и планшеты под управлением Android и iOS. Таким образом, современному веб-разработчику (дизайнеру / программисту / верстальщику) никак нельзя не учитывать особенности отображения конечного продукта на вышеупомянутых девайсах.

Нельзя сказать, что валидный, кроссбраузерный код, который корректно отображается на старших настольных братьях даст совершенно иную картину при запуске на мобильной платформе — сейчас уже ситуация обстоит куда лучше, нежели раньше. Однако, как показывает практика, все еще остались некоторые нюансы, которые необходимо учитывать. О тех, с которыми мне пришлось столкнуться в процессе тестирования в Safari под iOS я хочу сегодня рассказать.

Общие положения

Прежде, чем начинать устранять проблемы внешнего вида проекта на iOS устройствах, хорошо бы сразу определиться — что будет более рентабельно. Я достаточно часто наблюдал ситуацию, когда сайт обрастает ненужными, лишними конструкциями в угоду приемлемого вида с айфона. А если оригинальная версия сайта еще грешит и флешем…

Иногда гораздо лучше (как с экономической, так и с точки зрения юзабилити) использовать мобильную версию, со своими стилями и скриптами. Определить, с какого устройства к нам пришел пользователь несложно:

JavaScript:

var detect_ipad = navigator.userAgent.match(/iPad/i) != null; // для iPad
var detect_ipod = navigator.userAgent.match(/iPod/i) != null; // для iPod
var detect_iphone = navigator.userAgent.match(/iPhone/i) != null; // для iPhone

PHP:

strstr($_SERVER['HTTP_USER_AGENT'],'iPad') // для iPad
strstr($_SERVER['HTTP_USER_AGENT'],'iPhone') // для iPhone
strstr($_SERVER['HTTP_USER_AGENT'],'iPod') // для iPod

Подключать стили без использования JS можно 2 способами:

  1. через @media в основном файле стилей
  2. указывая в head путь к стилю

Пример первого способа описан ниже, в пункте «Изображения», второй же выглядит так:

<link href="mobile1024.css" rel="stylesheet" type="text/css" media="only screen and (max-device-width: 1024px)" />

Принцип действия в обоих вариантах один — мы используем в качестве идентификатора максимальное разрешения устройства, на котором будет отображаться проект. Можно, кстати, записать то же, только без "only" — это своего рода защита от старых браузеров.

В принципе, можно сразу отсылать пользователя на мобильную версию сайта (пример для iPad):

RewriteCond %{HTTP_USER_AGENT} ^.*iPad.*$
RewriteRule ^(.*)$ http://mobile.your-site.com [R=301]

Однако, как показывает практика, мобильная версия не всегда удобна и, что более важно — не всегда привычна пользователю. Лучше дайте право выбора: к примеру, при первом переходе на сайт страницу с вопросом/предложением использовать мобильную версию.

Изображения:

Веб разработчики, проверяя свой код на жизнеспособность под iOS время изредка сталкиваются с проблемой использования больших изображений в качестве фона. Причем, «больших» следует понимать как объемных по разрешению. Как оказалось, существует искусственное ограничение для Safari под управлением iOS.

Если вкратце, то дело обстоит так:

  1. Если на борту яблочного девайса ОЗУ менее 256 Мб, то максимальный размер изображений, который можно использовать безболезненно – 3 мегапикселя (что, фактически, ≤ 3 * 1024 * 1024 = 3 145 728 пикс.)
  2. Устройства, значение объема ОЗУ которых больше 256 Мб, корректно отобразят изображения до 5 мегапикселей.

Основной мотивацией данного решения, по версии самой Apple, является невысокая скорость передачи данных в EDGE, 3G и Wi-Fi сетях, однако жесткая привязка к объему памяти явно дает понять, что это не что иное, как попытка избежать «тормозов», которые неизбежно возникнут при декодировании и масштабировании крупных изображений.

Стоит заметить, что данные ограничения актуальны для изображений .GIF, .PNG, и .TIFF формата. Что касается изображений формата JPEG, то можно с чистой совестью использовать изображения до 32 мегапикселей, но только в режиме сабсэмплинга. Напомню, что при сохранении изображения в том же Photoshop, сабсэмплинг автоматически используется для уровня качества «Low» и «Medium». Это, в свою очередь, означает то, что фактически же, максимальное разрешение при кодировании в более-менее приемлемом качестве ограничено теми же 32 / 16 = 2 мегапикселями.

Решение:

Специально перерезаем наше изображение на уменьшенное, подгружая его одним из вышеописанных способов, например — через @media:

@media screen and (max-device-width: 1024px;) {

.my-background { background: url(images/bg_idevice.jpg) 0 0  no-repeat !important; } 

}

Для экранов с разрешением > 1024 будет отображаться фон, указанный в CSS ранее.

Скрипты:

Скрипты, время выполнения которых превышает 10 секунд, принудительно убиваются — причем, не факт, что это будет лицеприятный этап: в лучшем случае может статься, что пользователь увидит то, что ему видеть не следует, по крайней мере, не нажав пару кнопок.

Решение:

Оптимизация, только оптимизация. И тестируйте ваши скрипты. Причем, именно на тех устройствах, где они должны работать. На случай, если кто-то забыл — приведу код того, как это сделать:

var begin = new Date();
 
// сюда вставляем свой код
 
var finish = new Date();
alert('Script time ' + (finish.getTime()-begin.getTime()) + ' ms');

И гораздо лучше, если время выполнения будет максимально отдалено от критических 10 секунд — вы никогда не знаете, что еще висит в фоне и отъедает ресурсы и какая именно версия девайса будет у юзера в руках (соответственно — производительность). Хотя, за скрипты, которые даже близко подходят к этой отметке, следует отрывать руки.

Если тяжеловесной конструкции не избежать — задумайтесь об отдельной версии проекта для мобильных устройств, либо хотя бы об «облегченной» версии скрипта.

Input'ы:

По умолчанию у мобильной версии Safari есть одна неприятная особенность, которую замечаешь, когда проверяешь проект на строгое соответствие макету:
углы элементов input и textarea закругляются.

Решение:

Решается это просто — обнулением через CSS свойства border-radius:

border-radius:0px;
-webkit-radius:0px; 
-moz-radius:0px; 
-khtml-radius:0px;

Я это предпочитаю делать конструкцией для всех браузеров сразу [паранойя], хотя можно обойтись и одной строкой.

Label'ы:

Оказалось, что и с Label'ами у нас проблема. Как известно, по клику на label можно совершать действие со связанным элементом, например, с чекбоксом. Как оказалось, мобильная версия Safari и этому сопротивляется, решительно не производя ничего при клике на вышеупомянутый.

Решение:

Решений данной проблемы несколько, существует и на чистом js, без подключения сторонних библиотек, однако мне понравилась реализация на jQuery:

$(function(){
    $('label').bind('click', function(){ $(input, this).click(); return false; });
  });

Ссылки:

Бывают случаи (см.активные карты), когда js лишний раз использовать не хочется и необходимо при наведении на родительский элемент вывести ранее скрытый дочерний. На первый взгляд верна конструкция:

div.parent:hover div.child {display:block}

Однако, результатом этого на iPhone будет… решительно ничего.

Решение:

Дело в том, что в таком ключе браузер не воспринимает псевдокласс :hover, т.к. он применен к элементу div.

Для корректной работы на iPhone необходимо применять hover-эффекты именно к ссылке:

a.parent:hover span.child {display:block}

(Не забываем о правилах вложенности элементов: в данном случае используем именно span для успешного прохождения валидации).

И обязательно — для ссылок:

<a href="javascript:void(0);"><span>Скрытый текст</span></a>

При таком подходе при клике на ссылку не будет происходить перезагрузки страницы, и, в то же время, мы получим работающий hover на айфоне — т.к. для девайсов с сенсорным экраном действуют следующие правила:

  • Клик по ссылке -> переход по ссылке
  • Клик-1 по ссылке с заданным псевдоклассом :hover -> :hover {...} свойства,
  • Клик-2 по ссылке с заданным псевдоклассом :hover -> переход по ссылке.

Самое наболевшее прозвучало и, на сегодня — все.
В планах — материал об определении ориентации устройства

Автор: Matrosked

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js