Вивчай
· 5 хв читання
cssвеб-розробка

CSS, який ти пропустив — 8 речей, для яких більше не потрібен JavaScript

Розкритий ноутбук із редактором коду і чашкою кави на дерев'яному столі, м'яке денне світлоРозкритий ноутбук із редактором коду і чашкою кави на дерев'яному столі, м'яке денне світло

Є один надійний спосіб зрозуміти, коли людина вивчала CSS: спитати, як вона робить модальне вікно. Якщо відповідь починається зі слів «беру div з position: fixed, пишу обробник на click, ставлю клас .open...» — це CSS зразка 2015 року. Робочий, але з десятками рядків JavaScript там, де тепер вистачає одного атрибута.

За останні кілька років CSS тихо забрав у JavaScript із десяток задач. Тихо — бо жодна з них не потрапила в заголовки. Ось вісім, які варто знати.

Інфо

Біля кожної фічі вказано її статус у Baseline — це спільний стандарт браузерів, який каже, чи можна фічу використовувати без страху. «Широко доступна» означає підтримку в усіх основних браузерах уже щонайменше 30 місяців — бери сміливо. «Нещодавно доступна» — усі підтримують, але старі версії ще зустрічаються.

1. :has() — стилізувати батька за дитиною

Двадцять років у CSS можна було йти лише вниз по дереву: батько → дитина. Стилізувати div, у якому лежить картинка, або форму, в якій є помилка — тільки JavaScript.

/* Картка з картинкою — інша сітка, ніж без неї */
.card:has(img) {
  grid-template-columns: 120px 1fr;
}

/* Форма, в якій є невалідне поле, підсвічує кнопку */
form:has(:invalid) button[type="submit"] {
  opacity: 0.5;
}

Це «батьківський селектор», якого просили з 2000-х. Він працює не лише вгору, а й «убік»: label:has(+ input:focus) — підсвітити мітку, поки фокус на сусідньому полі.

Baseline: широко доступна з грудня 2023.

2. Container queries — компонент дивиться на свій контейнер, а не на екран

Медіа-запити відповідають на одне питання: «якої ширини вікно?». Але картка товару в сайдбарі й та сама картка в основній колонці мають різну ширину при однаковому вікні. Раніше під це заводили окремі класи або перевіряли ширину через ResizeObserver.

.sidebar, .main {
  container-type: inline-size;
}

/* Картка сама перебудовується, коли ЇЇ контейнер вужчий за 400px */
@container (max-width: 400px) {
  .card {
    flex-direction: column;
  }
}

Компонент стає справді самодостатнім: поклади його куди завгодно — він сам підлаштується. Це логічне продовження того, що ми розбирали в уроці про responsive design.

Baseline: широко доступна з лютого 2023.

3. <dialog> — модальне вікно, яке вже все вміє

Той самий приклад із початку. Ось усе, що потрібно:

<button onclick="modal.showModal()">Відкрити</button>

<dialog id="modal">
  <p>Точно видалити?</p>
  <form method="dialog">
    <button>Так</button>
    <button>Ні</button>
  </form>
</dialog>

Один виклик showModal() — і браузер сам: затемнює фон (стилізується через ::backdrop), блокує кліки поза вікном, закриває по Escape, повертає фокус туди, звідки прийшов, і робить вікно доступним для скрінрідерів. Кожен із цих пунктів раніше писали руками — і зазвичай щось забували.

Baseline: широко доступна з березня 2022. Так, уже давно.

4. popover — тултіпи й меню одним атрибутом

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

<button popovertarget="menu">Меню</button>

<div id="menu" popover>
  <a href="/profile">Профіль</a>
  <a href="/logout">Вийти</a>
</div>

Жодного рядка JavaScript. Клік поза меню закриває його, Escape теж, елемент автоматично рендериться поверх усього — без боротьби з z-index.

Baseline: нещодавно доступна з січня 2025.

5. Nesting — вкладені правила без Sass

Половина людей ставила Sass заради однієї речі — можливості писати стилі вкладено. Тепер це вбудовано:

.card {
  padding: 16px;

  & h2 {
    margin: 0;
  }

  &:hover {
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  }

  @media (max-width: 600px) {
    padding: 8px;
  }
}

Медіа-запит усередині правила — окрема радість: стилі компонента лежать в одному місці, а не розкидані по файлу.

Baseline: доступна з кінця 2023, у 2026 вже широко.

6. View Transitions — анімація між станами сторінки

Плавне перетікання елементів при зміні контенту — те, заради чого раніше тягнули анімаційні бібліотеки на сотні кілобайт. Тепер:

// Одна обгортка — і браузер сам анімує різницю між "до" і "після"
document.startViewTransition(() => {
  list.appendChild(newItem);
});

Це єдиний пункт у списку, де є рядок JavaScript — але лише один, і вся анімація описується в CSS через ::view-transition-old і ::view-transition-new. Раніше для того самого треба було вручну рахувати позиції елементів до й після.

Baseline: нещодавно доступна з жовтня 2025 для переходів у межах сторінки. Переходи між сторінками ще не всюди.

7. Scroll-driven animations — анімація, прив'язана до скролу

Елементи, що з'являються при прокрутці, прогрес-бар читання, паралакс — усе це були IntersectionObserver плюс обробник scroll, який ще й гальмував сторінку.

.reveal {
  animation: fade-in linear both;
  animation-timeline: view();
  animation-range: entry 0% entry 40%;
}

@keyframes fade-in {
  from { opacity: 0; transform: translateY(20px); }
  to   { opacity: 1; transform: none; }
}

animation-timeline: view() каже: «прогрес цієї анімації — це те, наскільки елемент увійшов у видиму область». Браузер робить це поза головним потоком, тож ніяких гальм.

Baseline: обмежена. Chrome, Edge і Safari підтримують, Firefox — довго відставав. Використовуй як прикрасу: без підтримки елемент просто буде видимий одразу.

8. Anchor positioning — прив'язати елемент до іншого

Тултіп має стояти над кнопкою. Якщо вгорі не влазить — під нею. Це класична задача, під яку існують цілі бібліотеки (Popper, Floating UI).

.tooltip {
  position: absolute;
  position-anchor: --btn;
  top: anchor(bottom);
  justify-self: anchor-center;
  position-try-fallbacks: flip-block;
}

.button {
  anchor-name: --btn;
}

position-try-fallbacks: flip-block — це те саме «не влазить знизу — покажи зверху», яке бібліотеки роблять через обчислення координат на кожен скрол.

Baseline: найсвіжіша у списку — базова підтримка стала Baseline лише на початку 2026, і в Safari вона ще не повна. Перевір на caniuse перед використанням у продакшені.

Що з цього випливає

Зверни увагу на дати: <dialog> — з 2022 року, container queries — з 2023. Це не «новинки», це речі, які багато хто просто пропустив, бо вчився за матеріалами, написаними раніше.

Спільна ідея всіх восьми одна: браузер тепер уміє те, що раніше писали руками — і вміє краще, бо враховує доступність, продуктивність і граничні випадки, про які вручну завжди щось забувається.

Практичне правило: перед тим як писати JavaScript для UI-поведінки, спитай себе, чи не зробить це CSS. У 2026 відповідь дедалі частіше «зробить».

Якщо базові речі — flexbox, grid, позиціонування — ще не сидять у пальцях, почни з блоку CSS у курсі: ці вісім фіч набагато простіше зрозуміти, коли розумієш, на чому вони стоять. А для швидкого пошуку властивостей є шпаргалки з Flexbox і Grid.