🕐 7 хв читання

Особливості верстки для мобільних пристроїв

Конспект лекції: Retina-дисплеї, Device Pixel Ratio, viewport мета-тег, мобільні браузери

1. Проблема декоративної графіки на Retina-дисплеях

Декоративні зображення (іконки, фони) вставляються через CSS за допомогою background-image. На екранах з підвищеною щільністю пікселів (Retina) растрова графіка може виглядати розмито.

Фізичні vs CSS-пікселі

CSS-піксель — це віртуальна одиниця. Один CSS-піксель може відповідати 2, 3 або більше фізичним пікселям екрана. Коефіцієнт DPR (Device Pixel Ratio) визначає це співвідношення.

Ситуація Результат
Розмір файлу = background-size Якість ідеальна
Файл більший за background-size Браузер зменшує — якість зберігається
Файл менший за background-size Браузер розтягує — якість втрачається (розмиття)
Приклад: іконка 16×16 px, DPR = 2. Браузер спробує відобразити 32×32 фізичних пікселів, але інформації лише на 16×16 — з'явиться розмиття.

2. Рішення «в лоб» — збільшене зображення

Найпростіший підхід — підготувати зображення в 2× (або 3×) більшому розмірі, а в CSS вказати потрібний background-size:

.icon {
    background-image: url("icon@2x.png");  /* 32×32 px файл */
    background-size: 16px 16px;           /* відображаємо як 16×16 */
    background-repeat: no-repeat;
}
Недоліки: збільшений файл важить більше; при зміні розміру іконки потрібно готувати нове зображення; для DPR 3 потрібен ще один варіант.

3. Іконковий шрифт (Icon Font)

Іконковий шрифт — це шрифт, де замість літер — іконки. Оскільки шрифт — векторний, іконки масштабуються без втрати якості.

Підключення

@font-face {
    font-family: "MyIcons";
    src: url("fonts/icons.woff2") format("woff2");
    font-weight: normal;
    font-style: normal;
}

Використання через псевдоелемент

.link::before {
    content: "\e901";          /* Unicode-код іконки */
    font-family: "MyIcons";
    font-size: 16px;
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
}

Переваги

  • Розмір змінюється через font-size — без втрати якості
  • Колір змінюється через color (як звичайний текст)
  • Готові набори іконок (Font Awesome, Material Icons тощо)

Недоліки

  • Іконка — це символ (текст), а не графіка — семантично неправильно
  • Не можна розфарбувати окремі частини іконки різними кольорами
  • Застарілий підхід — SVG має всі переваги без недоліків

4. SVG — сучасне рішення

SVG (Scalable Vector Graphics) — формат векторної графіки. Масштабується без втрати якості, бо описує фігури формулами, а не пікселями.

Два способи використання

Спосіб Як Зміна кольору Доступ з JS
Зовнішній файл background-image: url("icon.svg") Ні Ні
Вбудований (inline) Тег <svg> прямо в HTML Так (через fill) Так

Структура SVG

<svg class="icon" viewBox="0 0 24 24">
    <path d="M12 2C6.48 2 2 6.48 2 12s..."/>
</svg>
  • <svg> — контейнер; viewBox задає систему координат
  • <path> — контур фігури; атрибут d описує кривні
  • fill — колір заливки (атрибут або CSS-властивість)

Керування кольором inline SVG

/* Видаліть атрибут fill з <path> в розмітці! */
.icon path {
    fill: #333;
}
.link:hover .icon path {
    fill: #0066cc;
}
Якщо fill заданий атрибутом у тезі <path fill="...">, CSS-властивість fill його не перевизначить (як inline-стилі). Видаліть атрибут, щоб керувати кольором з CSS.

Розмір inline SVG

.icon {
    width: 24px;
    height: 24px;
}

5. Порівняння підходів до декоративної графіки

Критерій PNG @2x Іконковий шрифт SVG
Якість при масштабуванні Обмежена розміром файлу Без втрат Без втрат
Зміна кольору в CSS Ні Так (color) Так (fill, тільки inline)
Багатоколірність Так Ні Так (окремі <path>)
Семантичність Графіка Текст (семантично неправильно) Графіка
Підтримка браузерами Усі Усі Усі сучасні

6. Стилізація форм на мобільних пристроях

Мобільні браузери мають власні дефолтні стилі для елементів форм — скруглені кути у <input>, нестандартний вигляд <select>.

Скидання системного вигляду

input, select, textarea, button {
    -webkit-appearance: none;
    -moz-appearance: none;
    border-radius: 0;
}
Властивість appearance без префікса не підтримується всіма браузерами. Завжди використовуйте обидва префікси: -webkit-appearance та -moz-appearance.

Повернення стрілки для select

Після скидання appearance у <select> зникне стрілка. Додайте її через SVG-фон:

select {
    background-image: url("arrow-down.svg");
    background-repeat: no-repeat;
    background-position: right 10px center;
    background-size: 12px;
    padding-right: 30px;
}
Завжди явно задавайте стилі для елементів форм: border, border-radius, background, color, font-size. Не покладайтесь на дефолтні стилі — вони різні на різних платформах.

7. Автовизначення телефонних номерів на iOS

iOS Safari автоматично розпізнає числа, схожі на телефонні номери, і перетворює їх на сині підкреслені посилання з протоколом tel:.

Чому просте скидання стилів не працює

Браузер не змінює ваш тег — він обгортає текст у <a href="tel:..."> всередині вашого елемента. Тому стилі для батьківського елемента не допоможуть.

Рішення 1 — селектор за атрибутом

a[href^="tel"] {
    color: inherit;
    text-decoration: none;
}

Рішення 2 (краще) — одразу робити посилання

<a href="tel:+380441234567">+38 (044) 123-45-67</a>

Стилізуйте посилання як потрібно — і на десктопі, і на мобільних пристроях воно виглядатиме однаково.

Рішення 3 — повне вимкнення автовизначення

<meta name="format-detection" content="telephone=no">
Обережно! Цей мета-тег вимикає автовизначення на всій сторінці. Переконайтесь, що всі номери телефонів оформлені як посилання <a href="tel:..."> вручну.

8. Селектори за атрибутом

Синтаксис Опис Приклад
[attr="value"] Точне співпадіння input[type="text"]
[attr^="value"] Починається з... a[href^="tel"]
[attr$="value"] Закінчується на... a[href$=".pdf"]
[attr*="value"] Містить підрядок a[href*="example"]
[attr|="value"] Дорівнює value або починається з value- [class|="button"]

Спрощення класів-модифікаторів через [class|="..."]

Селектор [class|="button"] вибирає елемент, клас якого дорівнює button або починається з button-. Це дозволяє писати базові стилі один раз для всіх варіантів:

/* Застосується до class="button", class="button-primary", class="button-large" */
[class|="button"] {
  padding: 1em 2em;
  border: none;
  border-radius: 4px;
}

/* Конкретний модифікатор */
.button-accent {
  background-color: hotpink;
}

Замість <div class="button button-primary"> можна писати лише <div class="button-primary"> — базові стилі підхопляться автоматично.

Продуктивність: селектори за атрибутом повільніші за селектори за класом — браузеру потрібно аналізувати рядок. Використовуйте їх лише для специфічних випадків (масове стилізування посилань tel:, mailto: тощо).

9. Тестування верстки з динамічним контентом

Верстка повинна працювати з будь-якою кількістю контенту — коротким текстом, довгим текстом, різною кількістю елементів.

Що тестувати

  • Багато тексту — чи не ламається макет?
  • Мало тексту — чи не з'являються порожні простори?
  • Різна кількість колонок / карток
  • Відсутність зображень
Не використовуйте фіксований margin-top для вертикального центрування! При зміні контенту (більше/менше тексту) вирівнювання зламається. Використовуйте align-self: center або margin: auto у flex.

10. Типи input для мобільних пристроїв

HTML5 додав нові типи для <input>, які змінюють віртуальну клавіатуру на мобільних пристроях:

Тип Клавіатура Додаткові можливості
type="text" Звичайна текстова
type="search" Текстова з кнопкою "Знайти" Хрестик для очищення поля, кнопка пошуку замість Enter
type="email" Латинська з символом @ Перевірка формату з required
type="tel" Цифрова з +, -, #, * Зручний набір номерів
type="number" Цифрова Стрілки збільшення/зменшення, атрибут step

Ці типи впливають тільки на віртуальні клавіатури. Фізична клавіатура комп'ютера не зміниться.

Вбудована валідація з required

Коли required поєднується з типізованим input, браузер перевіряє не тільки заповненість, а й формат:

<input type="email" required>
<!-- Перевірить наявність @ та домену -->

<input type="tel" required>
<!-- Перевірить, що поле заповнене -->

Мінус: вигляд та текст повідомлень відрізняється між браузерами і не налаштовується. Для однакової поведінки потрібна валідація через JavaScript.

inputmode — альтернатива type="number"

type="number" має проблеми з UX: стрілки збільшення/зменшення заважають, випадковий скрол змінює значення. Краща альтернатива — комбінація type="text" з атрибутом inputmode:

<input
  type="text"
  inputmode="numeric"
  pattern="[0-9]*"
  placeholder="Введіть код"
>

inputmode="numeric" викликає цифрову клавіатуру на мобільних, а pattern забезпечує валідацію — без зайвих стрілок та випадкових змін при скролі.

Коли що використовувати: type="number" — для полів, де потрібні стрілки (кількість товарів, крок). inputmode="numeric" — для кодів, PIN, номерів карток, де стрілки заважають.

11. Атрибут pattern для валідації

Атрибут pattern дозволяє вказати регулярний вираз (regex) для перевірки введених даних:

<!-- Тільки цифри, мінімум 3 символи -->
<input type="text" pattern="[0-9]{3,}" required>

<!-- Міжнародний формат телефону -->
<input type="tel" pattern="\+[0-9]{10,13}" required>

HTML-валідація (required, pattern) легко обходиться через DevTools. Для надійної перевірки потрібен JavaScript на клієнті та перевірка на сервері.

12. Підсумкова таблиця

Тема Ключові моменти
Retina та DPR CSS-піксель ≠ фізичний піксель; DPR = фізичний / CSS; растр на Retina — розмивається
Іконковий шрифт Іконки як символи шрифту; масштабується без втрат; застарілий підхід
SVG Векторна графіка; найкраще рішення; inline — дозволяє fill та JS
Форми на мобільних -webkit-appearance: none + явні стилі; стрілка select через SVG-фон
Телефони на iOS Автовизначення; a[href^="tel"] для стилів; найкраще — робити <a href="tel:..."> одразу
Селектори за атрибутом [attr="val"], [attr^="val"], [attr$="val"], [attr*="val"], [attr|="val"]
Типи input search, email, tel, number — змінюють мобільну клавіатуру
inputmode inputmode="numeric" — цифрова клавіатура без стрілок; краще за type="number" для кодів та PIN
pattern Regex-валідація у HTML; обходиться через DevTools; потрібна серверна перевірка
🔍
Почніть вводити назву лекції або тему