nmk

Лекція №3 (2 години). Блокова модель CSS та позиціювання елементів.

План лекції

  1. Способи підключення CSS до HTML (inline, internal, external)
  2. Синтаксис та основні концепції CSS (Селектори, Специфічність, Каскад)
  3. Блокова модель CSS (CSS Box Model)
  4. Типи відображення елементів (Властивість display)
  5. Позиціювання елементів (Властивість position)
  6. Контекст накладання (z-index)
  7. Плаваючі елементи (Floats)
  8. Валідація та перевірка на помилки

Перелік умовних скорочень

Вступ

Сучасна веб-розробка неможлива без глибокого розуміння того, як браузер відображає елементи на сторінці. Основою цього процесу є блокова модель CSS (Box Model). Усе, що ми бачимо на веб-сторінці — це прямокутники, які вкладаються один в одного, розташовуються поруч або перекриваються. Розуміння цієї моделі дозволяє розробникам точно контролювати розміри, відступи та межі елементів.

Другим критично важливим аспектом є позиціювання. Не завжди достатньо стандартного потоку документа (коли елементи йдуть один за одним). Часто виникає потреба закріпити меню навігації на екрані, створити спливаюче вікно, яке перекриває контент, або точно розмістити іконку всередині кнопки. Для вирішення цих задач існують спеціальні властивості позиціювання та управління шарами (z-index).

Мета цієї лекції — розібрати анатомію HTML-елемента з точки зору CSS і навчитися ефективно керувати його розміщенням на сторінці.

1. Способи підключення CSS до HTML

Існує три основні способи додати CSS-стилі до HTML-документа. Кожен з них має свої особливості, переваги та недоліки.

1.1 Зовнішні стилі (External Styles)

Це найбільш рекомендований спосіб. Стилі записуються в окремому файлі з розширенням .css, який підключається в секції <head> за допомогою тегу <link>.

<head>
  <link rel="stylesheet" href="style.css" />
  <!-- CDN -->
  <link
    rel="stylesheet"
    href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css"
  />
</head>

1.2 Внутрішні стилі (Internal Styles)

CSS-правила розміщуються безпосередньо в HTML-файлі всередині тегу <style>, зазвичай у секції <head>.

<head>
  <style>
    body {
      background-color: #f0f0f0;
    }
    h1 {
      color: midnightblue;
    }
  </style>
</head>

1.3 Вбудовані стилі (Inline Styles)

Стилі задаються безпосередньо в атрибуті style конкретного HTML-елемента.

<h1 style="color: red; font-size: 24px;">Привіт, світ!</h1>
Спосіб Де розміщується Пріоритет Рекомендація
External Окремий .css файл Низький Найкраща практика
Internal Тег <style> у <head> Середній Для специфічних сторінок
Inline Атрибут style в тегу Високий Уникати (тільки для JS)

2. Синтаксис та основні концепції CSS

Перш ніж занурюватися у складні макети, необхідно зрозуміти фундаментальні механізми того, як CSS знаходить елементи на сторінці та які стилі до них застосовує.

2.1 Синтаксис CSS (CSS Rule)

Одне правило CSS (Rule set) складається з селектора та блоку оголошень.

/* Селектор { Властивість: Значення; } */
h1 {
  color: blue;
  font-size: 24px;
}

2.2 User Agent Stylesheet (Стилі браузера за замовчуванням)

Браузер має вбудовану таблицю стилів (User Agent Stylesheet), яка застосовується до сторінки автоматично. Саме тому без жодного вашого CSS:

Одним із перших кроків професійної верстки є “скидання” цих стилів (CSS Reset або Normalize.css), щоб сайт виглядав однаково у всіх браузерах.

Приклад CSS Reset:

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

2.3 Селектори (Selectors)

Селектори дозволяють обирати елементи за різними ознаками.

А) Прості селектори

Б) Складні селектори (Комбінатори)

Приклад:

<div>
  <p>Параграф 1</p>
  <p>Параграф 2</p>
  <p>Параграф 3</p>
</div>
/* Всі параграфи всередині div */
div p {
  color: red;
}

/* Тільки параграфи, які є безпосередніми нащадками div */
div > p {
  color: blue;
}

/* Перший параграф, який йде одразу після h2 */
h2 + p {
  color: green;
}

/* Всі параграфи, що йдуть після h2 на тому ж рівні вкладеності */
h2 ~ p {
  color: yellow;
}

В) Псевдокласи та Nesting

header {
  background: silver;
  & h1 {
    color: white;
  } /* h1 всередині header */
}

::marker {
  color: red; /* колір маркера списку */
}

::selection {
  background-color: yellow; /* колір виділеного тексту */
}

2.4 Специфічність (Specificity) та !important

Коли на один елемент діють суперечливі правила (наприклад, одне фарбує в червоний, а інше в синій), браузер обчислює “вагу” (специфічність) кожного селектора.

Вага селекторів (від меншого до більшого):

  1. Тег (div, p) — 1 бал.
  2. Клас (.my-class), псевдоклас (:hover) — 10 балів.
  3. ID (#my-id) — 100 балів.
  4. Вбудовані (Inline) стилі (style="...") — 1000 балів.

!important: Додавання !important до будь-якої властивості перебиває всі розрахунки специфічності. color: red !important; завжди переможе. Порада: Використання !important вважається поганою практикою і має використовуватися лише як останній аргумент в екстрених випадках, оскільки це ламає логіку каскаду.

2.5 Каскад (Cascade)

CSS розшифровується як Cascading Style Sheets. Каскад — це алгоритм поєднання стилів з різних джерел:

  1. Джерело: (Style sheets розробника мають пріоритет над User Agent).
  2. Специфічність: (Виграє важчий селектор).
  3. Порядок: (Якщо специфічність однакова, виграє правило, яке в коді написане останнім).

2.6 Can I use (Сумісність браузерів)

Can I use (https://caniuse.com/) — це найважливіший онлайн-сервіс для веб-розробника, який дозволяє перевірити, які властивості CSS, HTML5 або JavaScript підтримуються різними браузерами (Chrome, Firefox, Safari, Edge тощо) та їх версіями.

Веб-стандарти розвиваються дуже швидко, але не всі користувачі вчасно оновлюють свої браузери. Тому, перед тим як використовувати нову чи експериментальну можливість CSS, розробник повинен переконатися, що вона працюватиме у цільової аудиторії проекту.

Як користуватися (Приклад):

  1. Пошук: Введіть назву властивості в пошуковий рядок на сайті (наприклад, aspect-ratio або grid).
  2. Таблиця підтримки: Ви побачити сітку з назвами браузерів та номерами версій:
    • Зелений: Властивість підтримується повністю.
    • Червоний: Не підтримується.
    • Оливковий/Жовтий: Часткова підтримка (можливо, потрібні вендорні префікси або є певні обмеження).
  3. Глобальна статистика: У верхньому правому куті відображається відсоток користувачів у всьому світі, у яких ця властивість буде працювати (наприклад, 97.5%).

Приклад: Якщо ви вирішили використовувати властивість CSS Nesting, caniuse покаже, що вона підтримується всіма сучасними браузерами, але користувачі зі старими версіями Safari (до 16.5) її не побачать. Це сигнал для розробника, що потрібно або використати інструменти автоматичної обробки коду (PostCSS), або обрати старіший спосіб написання стилів.

2.7 Відлагодження CSS

Інструменти розробника (DevTools)

Браузери мають вбудовані інструменти для відлагодження CSS. Щоб відкрити їх, натисніть F12 або Ctrl+Shift+I (Windows/Linux) або Cmd+Option+I (Mac).

Основні вкладки для роботи з CSS:

  1. Elements (Елементи): Показує структуру HTML-документа. Ви можете вибирати елементи, переглядати їхні стилі та редагувати їх в реальному часі.
  2. Styles (Стилі): Показує всі CSS-правила, що застосовуються до вибраного елемента. Тут ви можете бачити, які правила перекривають інші (завдяки специфічності), і навіть редагувати стилі прямо в браузері.
  3. Computed (Обчислювані): Показує фінальні, обчислені значення всіх CSS-властивостей для вибраного елемента. Це корисно, коли ви не розумієте, чому елемент виглядає певним чином — тут ви побачите, які саме значення були застосовані після врахування всіх правил та специфічності.
  4. Layout (Макет): Дозволяє візуалізувати блокову модель елементів, переглядати їхні розміри, відступи, рамки та позиціонування.

Поширені проблеми та як їх знайти:

  1. Стилі не застосовуються: Перевірте, чи правильно написаний селектор, чи немає помилок у CSS-файлі, чи не перекривають інші правила ваші стилі (використовуйте вкладку Styles).
  2. Неправильні розміри елемента: Використовуйте вкладку Computed або Layout, щоб побачити реальні розміри елемента та перевірити, чи не впливають на них padding, border або margin.
  3. Неочікуване позиціонування: Перевірте значення position, top, left, right, bottom та z-index у вкладці Computed.

2.8 Правила неймінгу CSS-класів та архітектури (BEM, OOCSS, SMACSS)

Коли проект стає великим (більше 500 рядків CSS), випадкові назви класів на кшталт .box1, .red-text або .btn2 призводять до хаосу. Щоб код був зрозумілим і легким у підтримці, розробники використовують спеціальні методології.

1. BEM (Block, Element, Modifier) — Галузевий стандарт

Це найпопулярніший спосіб іменування класів, створений для створення модульних інтерфейсів.

Приклад BEM:

<article class="product-card product-card--featured">
  <img src="..." class="product-card__image">
  <h3 class="product-card__title">Назва товару</h3>
  <button class="product-card__button product-card__button--primary">Купити</button>
</article>

2. OOCSS (Object Oriented CSS)

Розділяє структуру елемента та його зовнішній вигляд (шкіру). Замість створення унікального класу для кожної кнопки, ви створюєте загальні класи.

3. SMACSS (Scalable and Modular Architecture for CSS)

Пропонує ділити весь CSS на 5 категорій:

  1. Base: Скидання стилів (html, body).
  2. Layout: Глобальна сітка (header, footer, sidebar).
  3. Module: Компоненти (віджети, картки, меню).
  4. State: Стани елементів (.is-hidden, .is-active).
  5. Theme: Візуальна тема (темна/світла).

4. ITCSS (Inverted Triangle CSS)

Методологія для керування специфічністю. Весь код організовується у вигляді перевернутого трикутника: від найбільш загальних правил (вгорі) до найбільш специфічних та важливих (внизу). Це запобігає конфліктам, коли одне правило неочікувано перебиває інше.

5. Atomic CSS / Utility-first (Tailwind)

Замість написання “семантичних” класів (.product-card), ви використовуєте сотні маленьких “утилітарних” класів, кожен з яких робить одну річ. Приклад (Tailwind style):

<div class="flex p-4 bg-white rounded-lg shadow-md hover:bg-gray-50">
  <h2 class="text-xl font-bold text-blue-600">Заголовок</h2>
</div>

3. Блокова модель CSS (CSS Box Model)

Кожен елемент на веб-сторінці браузер розглядає як прямокутний блок. Блокова модель CSS описує структуру цього блоку та визначає, як обчислюються його кінцеві розміри.

Блок складається з чотирьох основних областей (від центру до країв):

  1. Content (Контент) — вміст елемента: текст, зображення, відео тощо. Розміри цієї області визначаються властивостями width та height.
  2. Padding (Внутрішні відступи) — прозорий простір між контентом і межею (border) елемента. Фон елемента поширюється на цю область.
  3. Border (Межа) — лінія, яка оточує контент і внутрішні відступи (padding). Може мати колір, товщину та стиль (суцільна, пунктирна тощо).
  4. Margin (Зовнішні відступи) — прозорий простір поза межею елемента. Відокремлює елемент від сусідніх елементів на сторінці.

Приклад структури блокової моделі:

.box {
  width: 200px;
  height: 100px;
  padding: 20px;
  border: 5px solid black;
  margin: 15px;
}

Проблема класичної моделі (content-box)

За замовчуванням у CSS застосовується властивість box-sizing: content-box. Це означає, що властивості width та height задають розміри лише контентної області. У прикладі вище реальна ширина елемента на екрані складатиме: 200px (width) + 20px (padding-left) + 20px (padding-right) + 5px (border-left) + 5px (border-right) = 250px. Це було незручно, оскільки додавання відступів “ламало” сітку макету.

Рішення: border-box

Сучасний підхід полягає у використанні box-sizing: border-box. В цьому режимі width та height визначають повний розмір елемента (включаючи контент, padding та border). Якщо задати width: 200px, контентна область автоматично стиснеться так, щоб у ці 200 пікселів влізли і border, і padding.

Best Practice (Найкраща практика) — застосовувати скидання box-sizing для всіх елементів на сторінці:

*,
*::before,
*::after {
  box-sizing: border-box;
}

Схлопування зовнішніх відступів (Margin Collapsing)

Це специфічна поведінка браузерів: коли вертикальні margin двох блоків (один над одним) зустрічаються, вони не сумуються. Замість цього береться найбільше значення з двох. Приклад: Блок 1 має margin-bottom: 20px, Блок 2 (під ним) має margin-top: 30px. Відстань між ними буде 30px, а не 50px. Схлопування працює лише для вертикальних відступів блокових елементів у нормальному потоці.

4. Типи відображення елементів (Властивість display)

Поведінка елемента в потоці документа залежить від його типу відображення.

5. Позиціювання елементів (Властивість position)

За замовчуванням браузер розташовує елементи один за одним: блокові зверху вниз, рядкові — зліва направо. Це називається нормальним потоком документа (Normal flow). Властивість position дозволяє виймати елементи з цього потоку або зміщувати їх.

Керування позицією відбувається за допомогою координатних властивостей: top, right, bottom, left.

6. Контекст накладання (z-index)

Коли елементи перекривають один одного (наприклад, через абсолютне позиціювання або від’ємні марджини), браузер повинен вирішити, що відобразити зверху. За замовчуванням, елемент, який написаний у HTML-коді нижче, буде перекривати елементи, які написані вище.

Властивість z-index дозволяє змінити цей порядок. Це працює як вісь Z (глибина), спрямована на користувача.

Важливо: Контексти накладання (Stacking Contexts) z-index працює не глобально по всій сторінці, а в межах локальних контекстів. Якщо Батько А має z-index: 1, а Батько Б має z-index: 2, то будь-який дочірній елемент Батька А (навіть із z-index: 9999) ніколи не зможе перекрити Батька Б.

7. Плаваючі елементи (Floats)

Властивість float була створена для “обтікання” зображень текстом, подібно до того, як це робиться у традиційній типографії та газетних статтях.

Приклад обтікання зображення текстом:

<img src="logo.png" style="float: left; margin-right: 15px;" />
<p>
  Цей текст буде обтікати зображення з правого боку. Якщо тексту багато, він
  продовжиться під зображенням, коли пройде його висоту.
</p>

Проблема “випадіння” з контейнера

Основна проблема з плаваючими елементами полягає в тому, що вони частково вилучаються з нормального потоку документа. Якщо батьківський контейнер містить лише плаваючі елементи (float: left або float: right), його висота “склопнеться” до нуля (стане 0px), оскільки браузер не враховує висоту плаваючих нащадків. Це призводить до того, що фон батька зникає, а наступні неплаваючі елементи наїжджають на плаваючі.

Вирішення проблеми: Властивість clear та хак .clearfix

Щоб сказати браузеру “зупини обтікання і повернися до нормального потоку”, використовується властивість clear (значення left, right, або both). Вона забороняє елементу підніматися поруч із плаваючим сусідом.

Історичний хак .clearfix: Оскільки створення додаткового порожнього <div style="clear: both;"></div> після плаваючих елементів засмічувало HTML-код, розробники придумали CSS-рішення, яке застосовується до самого батьківського контейнера:

.clearfix::after {
  content: "";
  display: block;
  clear: both;
}

Історична довідка: Протягом багатьох років (до появи Flexbox та Grid) розробники будували цілі сітки сайтів (колонки) за допомогою float. Сьогодні використання float для макетування вважається застарілим і поганою практикою (anti-pattern). Зараз цю властивість слід застосовувати виключно за прямим призначенням — для обтікання контенту навколо зображень чи окремих блоків.

8. Валідація та перевірка на помилки

Написання CSS-коду може здаватися простим, але з часом обсяг стилів зростає, і стає легше допустити помилки, які важко відстежити. Валідація допомагає підтримувати код чистим, виправляти синтаксичні помилки та забезпечувати кращу сумісність.

8.1 W3C CSS Validator

Основним інструментом для перевірки відповідності вашого CSS стандартам є W3C CSS Validator (Jigsaw).

8.2 Linters (Stylelint)

У професійній розробці перевірка відбувається автоматично під час написання коду за допомогою лінтерів. Найпопулярнішим для CSS є Stylelint.

8.3 Поширені помилки в CSS

  1. Пропущена крапка з комою (;): Наступна властивість не буде розпізнана браузером.
  2. Помилки у назвах (Typos): collor: red замість color: red буде просто ігноруватися браузером без жодних попереджень.
  3. Неправильна вкладеність: Особливо актуально для сучасного CSS Nesting або препроцесорів (Sass/Less).
  4. Використання зарезервованих слів: Наприклад, назви класів, що збігаються з новими елементами HTML або властивостями CSS.
  5. Логічні помилки: Наприклад, задання width та height для елементів з display: inline, що не має ефекту.

Висновки

  1. Блокова модель визначає розміри кожного елемента на веб-сторінці. Використання box-sizing: border-box є необхідним стандартом для передбачуваного розмічання.
  2. Тип відображення (display) визначає, чи буде елемент переносити рядок і чи можна йому вручну задавати розміри. Блокові, рядкові та рядково-блокові мають принципові відмінності у поведінці.
  3. Для зміни візуального розташування елементів без зміни HTML-структури використовується властивість position. Найпопулярніша комбінація — position: relative для батька та position: absolute для нащадка.
  4. Властивість z-index керує шарами перекриття, але вимагає обережності через формування локальних контекстів накладання. Може викликати складні для відладки баги.
  5. Валідація CSS за допомогою інструментів W3C та використання лінтерів дозволяє уникнути синтаксичних помилок та підтримувати код професійним і чистим.

Джерела

  1. MDN Web Docs: CSS Box Model
  2. MDN Web Docs: Position
  3. CSS-Tricks: The z-index Property and Stacking Contexts
  4. Learn CSS (web.dev) - Box Model
  5. W3C CSS Validator

Запитання для самоперевірки

  1. Назвіть три способи підключення CSS до HTML. Який з них вважається “кращою практикою”?
  2. Що таке User Agent Stylesheet?
  3. Як обчислюється специфічність селекторів? Що має більшу вагу: ID чи клас?
  4. Що робить оператор !important і чому його варто уникати?
  5. Поясніть принципи каскаду в CSS.
  6. Які чотири складові містить блокова модель CSS?
  7. Що змінює правило box-sizing: border-box у розрахунку розмірів елемента?
  8. В чому різниця між властивостями display: none та visibility: hidden?
  9. Які стилі застосовуватимуться до елемента, якщо він є display: inline і йому задати width: 100px та margin-top: 50px?
  10. Що таке “схлопування зовнішніх відступів” (margin collapsing)?
  11. Відносно чого позиціюється елемент із position: absolute? Що станеться, якщо у нього немає жодного спозиційованого батьківського елемента?
  12. Чим position: sticky відрізняється від position: fixed?
  13. Чому елемент із z-index: 999 може знаходитись ПІД елементом із z-index: 2? У яких випадках це відбувається?
  14. Назвіть кілька поширених синтаксичних помилок у CSS. Як їх можна знайти автоматично?