Вёрстка под iOS — это не просто адаптация под маленькие экраны, а учёт десятков нюансов: от особенностей рендеринга в Safari до специфических жестов пользователей. Даже идеально сверстанный сайт на Android может «сломаться» на iPhone из-за неучтённых мелочей: неправильного масштабирования при повороте экрана, «прыгающего» контента при появлении панелей навигации или игнорирования системных шрифтов. В этой статье разберём ключевые отличия вёрстки под iOS, которые игнорируют 90% разработчиков, но из-за которых теряется до 30% трафика с устройств Apple.
По данным StatCounter (2026), доля iOS среди мобильных устройств в России и СНГ составляет ~25%, а в США и Европе — до 50%. При этом 68% пользователей iPhone покидают сайт, если он некорректно отображается или работает с задержками. Мы не будем перечислять базовые принципы адаптивной вёрстки (вроде медиа-запросов) — сфокусируемся на уникальных «яблочных» лайфхаках, которые не описаны в стандартных туториалах. От корректной настройки viewport до обработки свайпов и работы с WebKit-префиксами.
1. Viewport для iOS: почему meta-тег с width=device-width не всегда работает
Базовый тег <meta name="viewport" content="width=device-width, initial-scale=1"> на iOS ведёт себя иначе, чем на Android. Главная проблема — автоматическое масштабирование при повороте экрана. Safari может игнорировать initial-scale=1 и увеличивать контент, если ширина вёрстки превышает 980px (даже на iPhone 15 Pro Max!). Решение:
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover">
Разберём параметры:
- 🔍
maximum-scale=1— блокирует зум при повороте (иначе Safari может увеличить контент на 120–150%). - 🚫
user-scalable=no— отключает жесты масштабирования (актуально для веб-приложений). Не используйте это на контентных сайтах — Apple может отклонить такое приложение в App Store. - 📱
viewport-fit=cover— растягивает вёрстку на весь экран, включая область под «чёлкой» (safe area) на iPhone X и новее.
⚠️ Внимание: Если ваш сайт должен поддерживать iPad в режимеsplit-view(две программы одновременно), добавьтеshrink-to-fit=no. Иначе Safari будет принудительно уменьшать масштаб.
2. Safe Area: как не перекрыть контент «чёлкой» и жестами
Начиная с iPhone X (2017), все устройства Apple имеют вырез («чёлку») и жестовые зоны внизу экрана. Если не учесть safe area, кнопки или текст могут оказаться под системными элементами. Например, фиксированное меню внизу экрана перекроет свайп для возврата назад.
Решение — использовать CSS-переменные Apple:
:root {
--safe-area-inset-top: env(safe-area-inset-top);
--safe-area-inset-bottom: env(safe-area-inset-bottom);
}
body {
padding:
max(10px, var(--safe-area-inset-top)) / Отступ сверху /
0
max(10px, var(--safe-area-inset-bottom)); / Отступ снизу /
}
Для фиксированных элементов (например, нижней панели навигации):
.bottom-nav {
padding-bottom: max(10px, env(safe-area-inset-bottom));
background: white;
position: fixed;
bottom: 0;
left: 0;
right: 0;
}
| Устройство | safe-area-inset-top (портрет) | safe-area-inset-bottom (портрет) |
|---|---|---|
| iPhone 15/14/13/12 | 47px | 34px |
| iPhone 11/XR/XS Max | 44px | 34px |
| iPad Pro (2022+) | 24px | 20px |
| iPad Mini (2021) | 0px | 20px |
⚠️ Внимание: На iPad в ландшафтном режимеsafe-area-inset-leftиsafe-area-inset-rightмогут быть ненулевыми из-за док-станции (если подключена клавиатура). Всегда тестируйте вёрстку в обоих ориентациях!
Учтён отступ сверху (safe-area-inset-top) для «чёлки»
Добавлен отступ снизу (safe-area-inset-bottom) для жестовой панели
Фиксированные элементы (модалки, тулбары) не перекрывают safe area
Тестирование проведено на iPhone и iPad в портретном/ландшафтном режимах-->
3. Шрифты на iOS: почему -apple-system не достаточно
Стандартная рекомендация — использовать системный шрифт Apple:
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
Но этого мало. Проблемы, с которыми столкнётесь:
- 🔤 Несовпадение высоты строк: на iOS
line-height: 1.5может давать визуально разный результат из-за особенностей рендеринга San Francisco. - 📏 Отсутствие полужирного начертания: если не указать
font-weight: 600, текст может отображаться тоньше, чем на других платформах. - 🌐 Проблемы с кириллицей: шрифт San Francisco не оптимизирован для русского языка — буквы «ж», «щ» или «ъ» могут выглядеть размыто.
Решение:
body {
font-family:
-apple-system, / iOS/macOS /
BlinkMacSystemFont, / Chrome на Mac /
"Segoe UI", / Windows /
"Roboto", / Android /
"Helvetica Neue", / Старые iOS /
sans-serif;
font-weight: 400;
line-height: 1.6; / Оптимально для iOS /
-webkit-font-smoothing: antialiased; / Сглаживание для Safari /
-moz-osx-font-smoothing: grayscale;
}
/ Для заголовков /
h1, h2, h3 {
font-weight: 600; / Semi-bold для iOS /
letter-spacing: -0.02em; / Улучшает читаемость /
}
4. Жесты и тачи: обработка свайпов, тапов и 3D Touch
На iOS пользователи ожидают специфические жесты:
- 👆 Свайп справа налево — возврат назад (аналог кнопки «Назад» в браузере).
- 👇 Свайп вниз от верхнего края — обновление страницы (pull-to-refresh).
- 🖱️ 3D Touch / Haptic Touch — контекстное меню при сильном нажатии.
Чтобы не ломать пользовательский опыт:
- 🚫 Не блокируйте свайп назад с помощью
overscroll-behaviorилиtouch-action: none. Safari может игнорировать это, но пользователи будут раздражены. - ⚡ Добавьте pull-to-refresh для одностраничных приложений (SPA):
// Пример для React (используем библиотеку react-pull-to-refresh)
import PullToRefresh from 'react-pull-to-refresh';
function App() {
return (
<PullToRefresh
onRefresh={async () => await window.location.reload()}
className="pull-to-refresh-iOS"
>
{/ Ваш контент /}
</PullToRefresh>
);
}
Для обработки 3D Touch (на iPhone 6s–11) или Haptic Touch (на новых моделях):
// Проверка поддержки 3D Touch
if ('force' in window) {
document.addEventListener('touchforcechange', (e) => {
if (e.touches[0].force > 0.5) {
console.log('Сильное нажатие (3D Touch)');
// Открываем контекстное меню
}
});
}
Как отладить жесты на симуляторе Xcode
1. Запустите симулятор iPhone в Xcode.
2. В меню симулятора выберите Features → Force Touch (для старых моделей) или Features → Haptic Touch (для новых).
3. Используйте клавиши Option + Shift + клик для имитации сильного нажатия.
4. Для свайпов используйте трекпад с нажатой кнопкой (или тачбар на MacBook Pro).
5. Анимации и переходы: почему на iOS они «лагают»
Safari использует другой рендеринг-движок (WebKit), чем Chrome (Blink). Из-за этого анимации на transform и opacity могут тормозить, даже если на Android всё плавно. Правила оптимизации:
- ⚡ Используйте только transform и opacity для анимаций. Избегайте
width,height,margin— они триггерят дорогойlayout. - 🎨 Включите аппаратное ускорение:
.animated-element {
transform: translateZ(0); / Триггерит GPU-ускорение /
will-change: transform, opacity; / Подсказка браузеру /
backface-visibility: hidden; / Фикс для мерцания на iOS /
}
Пример плавной анимации для модального окна:
@keyframes fadeIn {
from { opacity: 0; transform: translateY(20px); }
to { opacity: 1; transform: translateY(0); }
}
.modal {
animation: fadeIn 0.3s ease-out forwards;
/ Для iOS добавляем: /
-webkit-animation: fadeIn 0.3s ease-out forwards;
-webkit-backface-visibility: hidden;
}
Для сложных анимаций (например, паралакс-эффектов) используйте библиотеки, оптимизированные под iOS:
- 📦 GSAP — лучший выбор для высокопроизводительных анимаций.
- 🎭 Framer Motion — если работаете с React.
⚠️ Внимание: На iPad с iPadOS 16+ анимации могут тормозить в режиме Stage Manager (многозадачность). Тестируйте производительность в этом режиме!
6. Формы и инпуты: автозаполнение, клавиатура и валидация
На iOS формы ведут себя иначе:
- 🔑 Автозаполнение: Safari агрессивно предлагает сохранённые пароли, даже если вы отключили
autocomplete. - ⌨️ Клавиатура: может закрывать инпуты, если не настроено правильное позиционирование.
- 📱 Типы инпутов:
type="date"отображает нативный пикер, но он выглядит по-разному на iPhone и iPad.
Решения:
- Отключение автозаполнения (если нужно):
<input type="text" autocomplete="new-password" />
<!-- или -->
<input type="text" autocomplete="off" readonly onfocus="this.removeAttribute('readonly')">
- Фикс для клавиатуры, перекрывающей инпуты:
/ Сдвигаем вьюпорт при фокусе на инпут /
input, textarea {
font-size: 16px; / Минимальный размер для iOS /
}
@media (max-width: 767px) {
.form-container {
padding-bottom: 120px; / Место для клавиатуры /
}
}
Для кастомных селектов (например, с библиотекой Select2) добавьте:
/ Фикс для нативного скролла в селектах на iOS /
.select2-container {
-webkit-overflow-scrolling: touch;
}
7. Тестирование и отладка: инструменты для iOS
Тестировать вёрстку на iOS сложнее, чем на Android, из-за закрытости экосистемы Apple. Основные инструменты:
| Инструмент | Для чего нужен | Особенности |
|---|---|---|
| Xcode Simulator | Эмуляция всех устройств Apple | Требует Mac, не показывает реальную производительность |
| BrowserStack | Тестирование на реальных устройствах | Платный, но поддерживает все версии iOS |
| Safari Web Inspector | Отладка через USB-подключение | Работает только на Mac, требует включения в настройках iPhone |
| LambdaTest | Кроссбраузерное тестирование | Бесплатный тариф с ограничениями |
Как подключить Safari Web Inspector:
- На iPhone: перейдите в
Настройки → Safari → Дополнительно → Веб-инспектори включите его. - Подключите iPhone к Mac по USB.
- Откройте Safari на Mac, в меню выберите
Разработка → [Ваш iPhone] → [Ваш сайт].
Для проверки производительности используйте:
// В консоли Safari Web Inspector
console.profile('Анимация');
// Ваш код
console.profileEnd('Анимация');
⚠️ Внимание: На iOS 17+ Safari может кэшировать агрессивнее, чем раньше. Чтобы обновить страницу без кэша, используйте комбинацию: нажмите и удерживайте кнопку обновления → выберите «Перезагрузить без кэша».
FAQ: Частые вопросы по вёрстке под iOS
Почему на iPhone сайт выглядит размыто, хотя на Android всё чёткое?
Проблема в некорректном viewport или отсутствии поддержки Retina-дисплеев. Проверьте:
- Есть ли тег
<meta name="viewport">сwidth=device-width. - Используются ли векторы (
SVG) или изображения в2x/3xразрешении (например,image@2x.png). - Не применён ли к тексту
-webkit-text-size-adjust: none— это может сделать шрифты размытыми.
Решение: добавьте для изображений:
<img src="image.png" srcset="image@2x.png 2x, image@3x.png 3x">
Как отключить зум на iOS, но оставить возможность масштабирования для пользователей с плохим зрением?
Используйте maximum-scale=1, но добавьте альтернативный способ увеличения контента:
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=5">
Или реализуйте кастомный зум через JavaScript с кнопками «+»/«–» (например, как на сайтах банков).
Почему на iPad сайт отображается как на десктопе, а не как мобильная версия?
Safari на iPad по умолчанию отправляет user-agent десктопного браузера. Чтобы принудительно показать мобильную версию:
- Добавьте в
viewportпараметрshrink-to-fit=no. - Используйте CSS-медиазапросы с
max-width: 1024px(максимальная ширина iPad в портретном режиме). - Для JavaScript-проверки используйте:
if (/iPad/.test(navigator.userAgent) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)) {
// Это iPad — применяем мобильные стили
document.body.classList.add('is-ipad');
}
Как сделать, чтобы видео на iOS автовоспроизводилось без звука?
На iOS автовоспроизведение видео блокируется, если:
- У видео есть звук (даже если
muted). - Видео не в поле зрения (
playsinlineне указан). - Пользователь не взаимодействовал со страницей.
Решение:
<video playsinline muted autoplay loop>
<source src="video.mp4" type="video/mp4">
</video>
Для фоновых видео используйте:
video {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
z-index: -1;
}
Почему на iOS не работает position: fixed?
Проблема в том, что Mobile Safari эмулирует position: fixed через JavaScript, а не нативно. Это приводит к:
- Дёрганью при скролле.
- Неправильной работе с клавиатурой.
- Багу с прокруткой внутри фиксированных блоков.
Решения:
- Замените
fixedнаsticky(если подходит по логике). - Используйте библиотеку ios-fixed-jank-fix.
- Для модальных окон применяйте
position: absoluteс JavaScript-позиционированием.