



🌐 Це неофіційний переклад статті CSS Wrapped 2025 від Chrome DevRel команди. Переклад зроблено для україномовної спільноти розробників. Оригінальний контент належить Google/Chrome.

CSS Wrapped 2025
Українською 🇺🇦
Цього року ми даємо вам нові інструменти для створення динамічного вебу. Створюйте динамічні інтерфейси, розширюйте свою уяву та грайтесь з цими потужними новими CSS-функціями.
Прокрутіть вниз, щоб дослідити
Ми створювали нові функції з думкою про вас. Готові побачити, що ми сформували у 2025 році? Chrome DevRel команда проведе вас через 22 CSS та UI функції, які з'явились на веб-платформі.
#🧩 Кастомізовані компоненти

Цього року було спекотно в майстерні. Ми взяли десятилітню проблему стилізації випадаючих списків і довели її до досконалості. Також ми випустили нові базові блоки, такі як нативне anchor positioning та API для каруселей з прокруткою.
#Invoker Commands
Показуйте <dialog> модально (і не тільки) без JavaScript!
Щоб відкрити <dialog> модально, натиснувши на <button>, зазвичай потрібен обробник onclick, який викликає метод showModal на цьому діалозі.
<button onclick="document.querySelector('#my-dialog').showModal();">Показати діалог</button><dialog id="my-dialog">…</dialog>
З invoker commands — доступними з Chrome 135 — кнопки тепер можуть виконувати дії над іншими елементами декларативно, без потреби в JavaScript.
<button commandfor="my-dialog" command="show-modal">Показати діалог</button><dialog id="my-dialog">…</dialog>
Атрибут commandfor приймає ID — подібно до атрибута for — тоді якcommand приймає вбудовані значення, що забезпечує більш портативний та інтуїтивний підхід.
Наразі можна надсилати команди до [popover] та <dialog> елементів, з можливістю додавання інших типів елементів у майбутньому. Команди відповідають їхнім JavaScript-аналогам:
show-popover:el.showPopover()hide-popover:el.hidePopover()toggle-popover:el.togglePopover()show-modal:dialogEl.showModal()close:dialogEl.close()
Також можна налаштувати власні команди для надсилання елементам. Ці кастомні команди починаються з двох дефісів і обробляються подією toggle.
<button commandfor="some-element" command="--show-confetti">🎉</button>
document.querySelector('#some-element').addEventListener('command', (e) => {if (e.command === "--show-confetti") {// …}});
Доступний поліфіл для Invoker Commands.
#Dialog Light Dismiss
Приємна функція Popover API тепер доступна для <dialog>.
Одна з приємних функцій, представлених Popover API — це поведінка light dismiss для попаверів. Вона дозволяє користувачам закривати попавер, клікнувши поза ним — на ::backdrop — або натиснувши клавішу ESC.
З Chrome 134 ця поведінка light dismiss також доступна для <dialog>через новий атрибут closedby, який контролює поведінку:
<dialog closedby="none">: Жодного закриття діалогу користувачем. Це поведінка за замовчуванням.<dialog closedby="closerequest">: Натискання ESC (або інший тригер закриття) закриває діалог<dialog closedby="any">: Клік поза діалогом або натискання ESC закриває діалог. Подібно до поведінкиpopover="auto".
#popover="hint"
Ефемерні попавери, які не закривають інші.
Hint-попавери з popover="hint" — це новий тип HTML-попаверів, призначений для ефемерних шаруватих UI-патернів, таких як підказки або попередній перегляд посилань. Відкриття hint-попавера не закриває інші відкриті auto чи manual попавери, дозволяючи шаруватим UI-елементам співіснувати.
<button interestfor="callout-1"></button><div id="callout-1" popover=hint>Інформація про продукт тут.</div>
Використання popover="hint" разом з interest invokers (атрибут [interestfor]) значно спрощує створення шаруватих UI-елементів, таких як підказки, hover-картки та попередній перегляд декларативно в HTML та CSS, без складних JavaScript-обхідних шляхів.
#Customizable select
Нарешті можна стилізувати HTML select елементи за допомогою CSS.
Нарешті настав час: тепер ви можете повністю кастомізувати HTML <select> елемент за допомогою CSS!
Щоб почати, застосуйте властивість CSS appearance: base-select до вашого <select> елемента. Це переведе його в новий, мінімальний стан, оптимізований для кастомізації.
select {&::picker(select) {appearance: base-select;}}
Використання base-select відкриває кілька потужних функцій, включаючи повну CSS-кастомізацію. Кожна частина select-елемента, включаючи кнопку, випадаючий список та опції, може бути стилізована за допомогою CSS.

Новий select також дозволяє включати та правильно рендерити HTML-елементи, такі як <img>та <span>, прямо всередині <option> елементів.
#scroll-target-group
Перетворіть список anchor-посилань на з'єднані scroll-маркери.
На додаток до псевдо-елементів ::scroll-button() та ::scroll-marker, CSS-каруселі включають ще одну класну функцію: scroll-target-group. Вона позначає елемент як контейнер для групи навігаційних елементів, наприклад, змісту.
Поєднайте scroll-target-group з псевдо-класом :target-current, щоб стилізувати anchor-елемент, ціль якого зараз видима. Це дає вам силу ::scroll-marker, але з гнучкістю використання власних HTML-елементів для маркерів.
<nav class="toc"><ul><li><a href="#section-1">Секція 1</a></li><li><a href="#section-2">Секція 2</a></li><li><a href="#section-3">Секція 3</a></li></ul></nav><main><section id="section-1">...</section><section id="section-2">...</section><section id="section-3">...</section></main>
.toc {scroll-target-group: auto;}.toc a:target-current {color: red;font-weight: bold;}
#Anchored container queries
Стилізуйте елементи на основі їхньої anchor-позиції.
Минулорічний CSS Wrapped охоплював CSS anchor positioning: захоплююче оновлення, яке змінює спосіб позиціонування елементів відносно один одного. З того часу воно стало частиною Interop 2025, і підтримка браузерами розширилась.
Однак, хоча CSS міг переміщувати елемент до fallback-позиції, він не мав способу дізнатися, який fallback було обрано. Це означало, що якщо ваш tooltip перевертався знизу вгору екрана, стрілка все ще вказувала б у неправильному напрямку. Тепер це вирішено за допомогою anchored container queries.
/* Елемент, до якого прив'язаний tooltip */.anchor {anchor-name: --my-anchor;}/* Позиціонований елемент (tooltip) */.tooltip {position: fixed;position-anchor: --my-anchor;position-area: bottom;position-try-fallbacks: flip-block;/* Робимо його anchored query контейнером */container-type: anchored;}/* Використовуємо anchored query для перевірки fallback */@container anchored(fallback: flip-block) {.tooltip::before {/* Використано 'top' fallback, тому перевертаємо стрілку */content: '▼';top: 100%;}}
Це величезна перемога для anchor positioning та бібліотек компонентів, що дозволяє створювати більш надійні та самодостатні UI-елементи з меншим кодом.
#Interest invokers
Декларативний UI, що активується інтересом, з interestfor.
UI, що активується наведенням та фокусом, є скрізь у вебі — від tooltips до багатих hover-карток та попереднього перегляду сторінок. Хоча цей патерн часто добре працює для користувачів миші, він може бути недоступним для інших модальностей, як-от сенсорний екран.
Новий атрибут interestfor вирішує цю проблему, надаючи нативний, декларативний спосіб стилізації елемента, коли користувачі "виявляють інтерес" до нього без повної активації.
<button interestfor="callout-1"></button><div id="callout-1" popover="hint">Інформація про продукт тут.</div>
Примітка: На відміну від command invokers, які працюють лише на кнопках, interest invokers можуть бути встановлені на посиланнях (<a>) так само як і на кнопках.
Interest Delays
Ще одна нова функція — можливість встановлювати затримки інтересу. Це запобігає занадто передчасному спрацюванню interest-invoked елемента. Ви можете встановити затримку як для відкриття, так і для закриття за допомогою властивості interest-delay.
/* застосовує оновлене значення затримки на кнопку interest-invoking */[interestfor] {interest-delay: 0.2s;}
#⚡ Взаємодії нового покоління

З цим новим інструментарієм взаємодій ви тепер можете анімувати переходи між сторінками за допомогою view transitions та створювати чудові scroll-based досвіди.
#Scroll-state queries
Стилізуйте нащадків залежно від того, чи є щось scrollable, stuck або snapped.
Щоб визначити, чи елемент stuck, snapped або scrollable, раніше потрібно було використовувати купу JavaScript... що не завжди легко зробити, бо треба прикріплювати таймаути до scroll-подій тощо.
Завдяки scroll-state queries — доступним з Chrome 133 — ви можете використовувати CSS для декларативної та більш продуктивної стилізації елементів у цих станах.
.parent {container-type: scroll-state;}
Після цього дочірні елементи можуть запитувати, чи батьківський елемент у певному scroll-state:
- Stuck state: коли елемент прилипає.
- Snapped state: коли елемент snap-нутий.
- Scrollable state: коли елемент має overflow.
.scroller {overflow-x: scroll;scroll-snap-type: x mandatory;> div {container-type: scroll-state;scroll-snap-align: center;@supports (container-type: scroll-state) {> * {transition: opacity .5s ease;@container not scroll-state(snapped: x) {opacity: .25;}}}}}
#Tree counting functions
Поступові анімації, хтось?
Звичайний метод створення поступових (staggered) анімацій для елементів списку, де кожен елемент з'являється послідовно, вимагає підрахунку DOM-елементів і жорсткого кодування цих значень у custom properties (наприклад, --index: 1;, --index: 2;) за допомогою селекторів :nth-child.
Нові функції sibling-index() та sibling-count() полегшують життя, оскільки надають нативну обізнаність про позицію елемента серед його сусідів.
li {/* Створюємо поступову затримку. *//* Віднімаємо 1, бо sibling-index() починається з 1, *//* забезпечуючи, що перший елемент стартує одразу (0s). */transition: opacity 0.25s ease, translate 0.25s ease;transition-delay: calc(0.1s * (sibling-index() - 1));@starting-style {opacity: 0;translate: 1em 0;}}
#scrollIntoView() container
Іноді прокрутка лише найближчого ancestor scroller — це все, що вам потрібно.
Опція container для Element.scrollIntoView дозволяє виконуватиscrollIntoView, прокручуючи лише найближчий ancestor scroll container. Це надзвичайно корисно, якщо у вас є вкладені scroll-контейнери.
slideList.addEventListener('click', (evt) => {// scrollIntoView автоматично визначить позицію.evt.target.targetSlide.scrollIntoView({container: 'nearest', behavior: 'smooth'});});
#Nested View Transition Groups
Зберігайте 3D та clipping ефекти під час view transition.
Nested view transition groups — це розширення для view transitions, яке дозволяє вкладати псевдо-елементи ::view-transition-group один в одного.
Коли view transition groups вкладені, замість того щоб розміщувати їх усі як сусіди під одним псевдо-елементом ::view-transition, можна зберегти 3D та clipping ефекти під час переходу.
.card {view-transition-name: card;overflow: clip;}.card img {view-transition-name: photo;view-transition-group: nearest;}::view-transition-group-children(card) {overflow: clip;}
Для браузерів без підтримки, перегляньте цей запис:
#DOM State-Preserving Move
Переміщуйте iframe та відео по DOM без їх перезавантаження.
Використання insertBefore для переміщення елемента в DOM є деструктивним. Якщо ви переміщуєте відео, що програється, або iframe за допомогою insertBefore, він перезавантажується і повністю втрачає свій стан.
Однак, з Chrome 133, ви можете використовувати moveBefore. Він працює точно так само як insertBefore, але зберігає елемент живим під час переміщення.
const $newSibling = getRandomElementInBody();const $iframe = document.querySelector('iframe');document.body.moveBefore($iframe, $newSibling);
Це означає, що відео продовжують грати, iframe'и не перезавантажуються, CSS-анімації не перезапускаються, а поля введення зберігають фокус — навіть коли ви активно reparent-ите їх по вашому layout.
#🛠️ Оптимізована ергономіка

Ці модулі — не просто plug-and-play; вони справжні хамелеони, що дозволяють користувачам перевизначати інтерфейс, функціональність та естетику аж до атомарного рівня.
#Розширена функція attr()
Типізовані значення для attr() за межами простих рядків.
CSS-функція attr(), яка дозволяє використовувати значення HTML-атрибута у вашому CSS, отримала потужне оновлення.
Раніше attr() можна було використовувати лише в межах властивості content псевдо-елементів і вона могла повертати значення лише як CSS-рядок. Оновлена функція attr()розширює свої можливості, дозволяючи використовувати її з будь-якою CSS-властивістю, включаючи custom properties.
div {color: attr(data-color type(<color>), red);}.card {/* card-1, card-2, card-3, тощо */view-transition-name: attr(id type(<custom-ident>), none);view-transition-class: card;}.star-rating {--percent-fill: calc(attr(data-rating type(<number>)) * 20%);background: linear-gradient(to right, gold var(--percent-fill), transparent var(--percent-fill));&::after {content: attr(data-rating);}}

#ToggleEvent.source
Дізнайтеся, який елемент був відповідальним за toggle цільового елемента.
Коли popover, <dialog> або <details> елемент перемикається, може бути цікаво знати, який елемент був відповідальним за це. Наприклад, знати, чи користувач натиснув кнопку "Прийняти cookies" чи "Відхилити cookies" для закриття cookie-банера — це дуже важлива деталь.
<div id="cookiebanner" popover="auto"><p>Бажаєте печиво?</p><button id="yes" commandfor="cookiebanner" command="hide-popover">Так</button><button id="no" commandfor="cookiebanner" command="hide-popover">Ні</button></div>
$cookiebanner.addEventListener('toggle', event => {if (event.source == $btnYes) {// Дати користувачу cookie} else if (event.source == $btnNo) {// Не давати користувачу cookie}});
#text-box features
Бездоганно центруйте текст вертикально.
Content box шрифту визначається внутрішніми метриками — конкретно ascent та descent, які резервують простір для акцентів та висячих символів.

Оскільки візуальні межі латинського тексту — це cap height та alphabetic baseline, а не ascent та descent, текст виглядатиме оптично зміщеним від центру, навіть коли він математично центрований всередині контейнера.


Властивості text-box роблять можливим тонший контроль вертикального вирівнювання тексту, дозволяючи бездоганно центрувати текст вертикально.
h1, button {text-box: trim-both cap alphabetic;}
#Функція shape()
CSS-функція для складних, адаптивних форм.
Нова функція shape() дозволяє обрізати елемент до складної, неполігональної, адаптивної форми в CSS. Це чудовий варіант для обрізних масок за допомогою clip-path: path(), і безшовно працює з CSS custom properties для визначення координат та контрольних точок.

.flag {clip-path: shape(from 0% 20px,curve to 100% 20px with 25% 0% / 75% 40px,vline to calc(100% - 20px),curve to 0% calc(100% - 20px)with 75% 100% / 25% calc(100% - 40px),close);}
У цьому прикладі горизонтальні координати використовують відсотки для масштабування з шириною елемента, а вертикальні координати для висоти кривої використовують фіксовані значення в пікселях, створюючи адаптивний ефект, де хвиля прапора залишається сталою незалежно від розміру елемента.
Ще один приклад використовує blob generator для shape(), щоб створити цікавий ефект рамки:

#if() statements
Умовні оператори у вашому CSS для динамічної стилізації.
Функція if() в CSS дозволяє встановлювати різні значення для властивості на основі умовного тесту. Думайте про неї як про тернарний оператор у JavaScript, але для ваших стилів.
if(condition-1: value-1; condition-2: value-2; else: fallback-value);
Наразі if() можна використовувати з трьома типами запитів:
media(): для media queries.supports(): для feature queries.style(): для style queries.
.responsive-layout {display: flex;flex-direction: if(media(orientation: landscape): row; else: column);}
#Custom Functions
Перевикористовувані функції для чистіших, підтримуваних стилів.
CSS custom functions — це фантастичне нове доповнення до мови CSS, яке значно полегшує написання композиційної, перевикористовуваної та зрозумілої функціональної логіки стилізації.
/* Функція negate повертає від'ємне значення */@function --negate(--value) {result: calc(-1 * var(--value));}/* Використання */html {--gap: 1em;padding: --negate(var(--gap));}
/* Умовно застосовує радіус, поки ви не в (default: 4px) від краю екрана */@function --conditional-radius(--radius, --edge-dist: 4px) {result: clamp(0px, ((100vw - var(--edge-dist)) - 100%) * 1e5, var(--radius));}/* використання */.box {border-radius: --conditional-radius(1rem);}
Одна з моїх улюблених CSS-функцій — це умовно заокруглений border-radius. Функція прибирає border-radius елемента, коли він опиняється на відстані менше заданої від краю viewport:
#Expanded range syntax
Синтаксис діапазонів у style queries та if() statements.
Одне приємне оновлення цього року — можливість використовувати синтаксис діапазонів у style queries та if() statements. Media queries та container queries вже підтримували цю можливість, але раніше style queries вимагали точного збігу значення.
Тепер ви можете типізувати ваші значення та використовувати їх з операторами порівняння як <, >, <= та >=.
.card-container {container-name: weather;--rain-percent: attr(data-rain-percent type(<percentage>));}@container style(--rain-percent > 45%) {.weather-card {background: linear-gradient(140deg, blue, lightblue);}}
Тепер, якщо шанс дощу більший за 45%, картка отримає синій фон.

#Stretch sizing keyword
Зробіть елемент таким, щоб він заповнював свій containing block, незалежно від box-sizing.
Ключове слово stretch — це ключове слово для використання з CSS-властивостями розмірів (такими як width та height), яке дозволяє елементам рости, щоб точно заповнити доступний простір їхнього containing block.
Це схоже на 100%, за винятком того, що результуючий розмір застосовується до margin box елемента замість box, визначеного box-sizing.
.element {height: stretch;}
#corner-shape
Форми кутів за межами заокруглених країв.
Цього року CSS дає нам більше контролю над формою наших елементів з новою властивістюcorner-shape. Ця експериментальна функція дозволяє кастомізувати форму кутів за межами стандартних заокруглених кутів, доступних з border-radius.
Тепер ви можете створювати різноманітні стилі кутів:
round— заокругленийbevel— скошенийnotch— вирізscoop— зачерпнутийsquircle— суперекліпс
.top-left-petal {grid-area: 1 / 1 / 3 / 3;corner-shape: round round scoop;border-radius: 50%;}

Для ще більшого контролю ви можете використовувати функцію superellipse()для створення будь-якої неперервної кривої, що дозволяє точно налаштовані та унікальні дизайни кутів.
📊 Оновлення Baseline у 2025
- ✓Container Queries досягли Baseline Widely available
- ✓Interop 2025 приніс великі покращення для CSS anchor positioning
- ✓Popover API з'явився у всіх браузерних рушіях
- ✓CSS тригонометричні функції стали Baseline widely available
- ✓Same-document view transitions стали Baseline Newly available

