@scope
Експериментальне
Це експериментальна технологія.
Перед її використанням у промисловій розробці уважно перевірте Таблицю сумісності з браузерами.
Директива CSS @scope
(контекст) дає змогу вибирати елементи в конкретних піддеревах DOM, точно націлюючись на елементи без написання надспецифічних селекторів, які важко пересилити, і без занадто тісного зв'язування селекторів зі структурою DOM.
У JavaScript до @scope
можна звернутися за допомогою інтерфейсу об'єктної моделі CSS CSSScopeRule
.
Синтаксис
Директива @scope
містить одне або декілька наборів правил (що звуться контекстними стилістичними правилами) і визначає контекст, у якому ці правила застосовуються до вибраних елементів. Її можна використовувати двома способами:
-
Як самостійний блок у CSS, у випадку чого вона включає підготовчий розділ, який містить селектори кореня контексту і необов'язкові селектори межі контексту – вони визначають верхнє і нижнє обмеження контексту.
@scope (scope root) to (scope limit) { rulesets }
-
Як вбудовані стилі, включені в елементі
<style>
у HTML, у випадку чого підготовчий розділ пропускається, а вкладений набір правил автоматично обмежується контекстом батьківського елемента щодо<style>
.<parent-element> <style> @scope { rulesets } </style> </parent-element>
Опис
Складний вебдокумент може містити компоненти штибу колонтитулів, новинних статей, карт, медіаплеєрів, рекламних оголошень та іншого. Зі зростанням складності ефективне керування оформленням цих компонентів стає все більшим клопотом, і ефективне обмеження стилів допомагає керувати цією складністю. Розгляньмо наступне дерево DOM:
body
└─ article.feature
├─ section.article-hero
│ ├─ h2
│ └─ img
│
├─ section.article-body
│ ├─ h3
│ ├─ p
│ ├─ img
│ ├─ p
│ └─ figure
│ ├─ img
│ └─ figcaption
│
└─ footer
├─ p
└─ img
Якщо потрібно вибрати елемент <img>
всередині <section>
з класом article-body
, можна зробити так:
- Написати селектор виду
.feature > .article-body > img
. Однак він має високу специфічність, тому його важко пересилити, а також тісно зв'язаний зі структурою DOM. Якщо структура розмітки зміниться у майбутньому, можливо, доведеться переписувати CSS. - Написати щось менш специфічне, виду
.feature img
. Проте такий селектор вибере всі зображення всерединіsection
.
Саме в такій ситуації @scope
стає корисною. Вона дає змогу точно визначити контекст, в якому селекторам дозволено націлюватись на елементи. Наприклад, проблему вище можна було б вирішити за допомогою самостійного блоку @scope
так:
@scope (.article-body) to (figure) {
img {
border: 5px solid black;
background-color: goldenrod;
}
}
Селектор кореня контексту визначає верхнє обмеження контексту дерева DOM, у якому набір правил буде застосований, а селектор межі контексту figure
визначає нижнє обмеження. В результаті будуть вибрані лише елементи <img>
всередині <section>
з класом article-body
, але не всередині елементів <figure>
.
Примітка: Обмеження такого роду – з верхнім і нижнім обмеженнями – заведено звати кільцевим контекстом.
Якщо потрібно вибрати всі зображення всередині <section>
з класом article-body
, можна пропустити межу контексту:
@scope (.article-body) {
img {
border: 5px solid black;
background-color: goldenrod;
}
}
Або ж можна додати свій блок @scope
вбудованим стилем всередині елемента <style>
, який знаходиться всередині <section>
з класом article-body
:
<section class="article-body">
<style>
@scope {
img {
border: 5px solid black;
background-color: goldenrod;
}
}
</style>
<!-- ... -->
</section>
Примітка: Важливо розуміти, що хоча
@scope
дає змогу ізолювати застосування селекторів до конкретних піддерев DOM, вона не ізолює застосовані стилі всередині цих піддерев повністю. Це особливо помітно при успадкуванні: властивості, які успадковуються дочірніми елементами (наприклад,color
абоfont-family
), все ж успадковуються, попри будь-які межі контекстів.
Псевдоклас :scope
У контексті блоку @scope
псевдоклас :scope
представляє корінь контексту – він надає простий спосіб застосування стилів до самого кореня контексту зсередини цього контексту:
@scope (.feature) {
:scope {
background: rebeccapurple;
color: antiquewhite;
font-family: sans-serif;
}
}
Фактично, :scope
неявно ставиться на початку всіх контекстних стилістичних правил. Якщо бажаєте, можна явно ставити :scope
на початок або ж використовувати селектор вкладеності (&
), щоб отримати той самий ефект, якщо таке представлення вам легше зрозуміти.
Три правила в наступному блоку є рівносильними щодо того, що вибирають:
@scope (.feature) {
img { ... }
:scope img { ... }
& img { ... }
}
Примітки щодо використання селекторів у контекстах
-
Межа контексту може використовувати
:scope
, щоб вказати конкретну вимогу до відношення між межею контексту і коренем. Наприклад:/* figure є межею лише тоді, коли є безпосереднім нащадком :scope */ @scope (.article-body) to (:scope > figure) { ... }
-
Межа контексту може посилатися на елементи поза коренем контексту за допомогою
:scope
. Наприклад:/* figure є межею лише тоді, коли :scope знаходиться всередині .feature */ @scope (.article-body) to (.feature :scope figure) { ... }
-
Контекстні стилістичні правила не можуть виходити за межі піддерева. Селекції виду
:scope + p
є недійсними, оскільки такий вибір вийшов би за межі піддерева. -
Цілком дійсним є визначення кореня і межі контексту як списку селекторів, – у такому випадку визначається кілька контекстів. У наступному прикладі стилі застосовуються до будь-якого елемента
<img>
всередині<section>
з класомarticle-hero
абоarticle-body
, але не всередині<figure>
:@scope (.article-hero, .article-body) to (figure) { img { border: 5px solid black; background-color: goldenrod; } }
Специфічність у @scope
Додавання набору правил всередину блоку @scope
не впливає на специфічність його селектора, незалежно від селекторів, використаних для кореня і межі контексту. Наприклад:
@scope (.article-body) {
/* img має специфічність 0-0-1, як і очікувалося */
img { ... }
}
Проте якщо вирішити явно додати псевдоклас :scope
на початку контекстних селекторів, то доведеться враховувати його при розрахунку їх специфічності. :scope
, як і всі звичайні псевдокласи, має специфічність 0-1-0. Наприклад:
@scope (.article-body) {
/* :scope img має специфічність 0-1-0 + 0-0-1 = 0-1-1 */
:scope img { ... }
}
При використанні селектора &
всередині блоку @scope
, &
представляє селектор кореня контексту; він внутрішньо обчислюється як цей селектор, обгорнутий у функцію псевдокласу :is()
. Так, наприклад, у:
@scope (figure, #primary) {
& img { ... }
}
Запис & img
рівносильний щодо :is(figure, #primary) img
. Оскільки :is()
переймає специфічність свого найбільш специфічного аргументу (у цьому випадку #primary
), то специфічність контекстного селектора & img
становить 1-0-0 + 0-0-1 = 1-0-1.
Різниця між :scope
і &
всередині @scope
Псевдоклас :scope
представляє відповідний корінь контексту, натомість селектор &
представляє селектор, який використовується для пошуку цього кореня контексту. У зв'язку з цим можна використовувати &
кілька разів поспіль. Однак :scope
можна використовувати лише один раз: неможливо знайти корінь контексту всередині кореня контексту.
@scope (.feature) {
/* Вибирає .feature всередині відповідного кореня .feature */
& & { ... }
/* Не працює */
:root :root { ... }
}
Як розв'язуються конфлікти @scope
Директива @scope
додає новий критерій до каскаду CSS – контекстну наближеність. Він визначає, що коли два контексти мають конфліктні стилі, то застосовується стиль, який має найменшу кількість кроків вгору по ієрархії дерева DOM до кореня свого контексту. Розгляньмо приклад, щоб зрозуміти, що це означає.
Для прикладу – наступний уривок HTML, де картки різних тем вкладені одна в одну:
<div class="light-theme">
<p>Текст у світлій темі</p>
<div class="dark-theme">
<p>Текст у темній темі</p>
<div class="light-theme">
<p>Текст у світлій темі</p>
</div>
</div>
</div>
Якщо написати CSS для теми так, то виникне проблема:
.light-theme {
background: #ccc;
}
.dark-theme {
background: #333;
}
.light-theme p {
color: black;
}
.dark-theme p {
color: white;
}
Найглибший абзац повинен був би бути чорним, тому що знаходиться всередині картки світлої теми. Однак на нього націлюється як .light-theme p
, так і .dark-theme p
. Оскільки правило .dark-theme p
з'являється пізніше в порядку коду, воно застосовується, і абзац виявляється помилково забарвленим у білий колір.
Щоб це виправити, можна використати @scope
так:
@scope (.light-theme) {
:scope {
background: #ccc;
}
p {
color: black;
}
}
@scope (.dark-theme) {
:scope {
background: #333;
}
p {
color: white;
}
}
Тепер найглибший абзац правильно забарвлений у чорний колір. Це пов'язано з тим, що він знаходиться лише за один рівень ієрархії від кореня контексту .light-theme
, але за два рівні від кореня контексту .dark-theme
. Тому перемагає стиль світлої теми.
Примітка: Контекстна наближеність пересилює порядок у коді, але сама пересилюється іншими критеріями вищого пріоритету, такими як вага, шари та специфічність.
Формальний синтаксис
Інформація про синтаксис недоступна
Жодного значення не знайшлося в базі даних.
Приклади
Базовий стиль всередині коренів контексту
У цьому прикладі використовуються два окремі блоки @scope
, щоб давати збіг з посиланнями всередині елементів з класами .light-scheme
і .dark-scheme
відповідно. Зверніть увагу на те, як :scope
вживається для вибирання та оформлення самих коренів контекстів. У цьому прикладі коренями контекстів є елементи <div>
, до яких застосовуються класи.
HTML
<div class="light-scheme">
<p>
ВебДоки містять чимало інформації про
<a href="/uk/docs/Web/HTML">HTML</a>, <a href="/uk/docs/Web/CSS">CSS</a> і
<a href="/uk/docs/Web/JavaScript">JavaScript</a>.
</p>
</div>
<div class="dark-scheme">
<p>
ВебДоки містять чимало інформації про
<a href="/uk/docs/Web/HTML">HTML</a>, <a href="/uk/docs/Web/CSS">CSS</a> і
<a href="/uk/docs/Web/JavaScript">JavaScript</a>.
</p>
</div>
CSS
@scope (.light-scheme) {
:scope {
background-color: plum;
}
a {
color: darkmagenta;
}
}
@scope (.dark-scheme) {
:scope {
background-color: darkmagenta;
color: antiquewhite;
}
a {
color: plum;
}
}
Результат
Код вище візуалізується так:
Корені контекстів і межі контекстів
У цьому прикладі – уривок HTML, що відповідає структурі DOM, про яку мова була раніше, в розділі Опису. Ця структура представляє типовий підсумок статті. Основні риси, на які варто звернути увагу, – елементи <img>
, які вкладені на різних рівнях цієї структури.
Метою цього прикладу є показати, як використовувати корені контекстів і межі контекстів для оформлення елементів <img>
, починаючи з верхнього рівня ієрархії, але лише до (і не включаючи) <img>
всередині елемента <figure>
– фактично, створюючи кільцевий контекст.
HTML
<article class="feature">
<section class="article-hero">
<h2>Заголовок статті</h2>
<img alt="image" />
</section>
<section class="article-body">
<h3>Підзаголовок статті</h3>
<p>
На постійній основі організація використовує вигідні захоплюючі технології
новаторства, інновацій та накопичення. Незмінно зміцнює позиції широкий
вибір відкриттів: розробка програмного забезпечення, телекомунікації і
свіжі овочі та фрукти для киян і стильних особистостей.
</p>
<img alt="image" />
<p>Систематичне вдосконалення, фінансово відповідальні технології.</p>
<figure>
<img alt="image" />
<figcaption>Моя інфографіка</figcaption>
</figure>
</section>
<footer>
<p>Написано Максимом Шевченком.</p>
<img alt="image" />
</footer>
</article>
CSS
У CSS є два блоки @scope
:
- Перший блок
@scope
визначає свій корінь контексту як елементи з класом.feature
(у цьому випадку, лише зовнішній<div>
), демонструючи, як@scope
можна використовувати для оформлення конкретної підмножини HTML. - Другий блок
@scope
також визначає свій корінь контексту як елементи з класом.feature
, але додатково визначає межу контекстуfigure
. Завдяки цьому всі вміщені набори правил будуть застосовуватися лише до відповідних елементів усередині кореня контексту (<div class="figure"> ... </div>
у цьому випадку), які не вкладені всередині елементів-нащадків<figure>
. У цьому блоку@scope
є один набір правил, який оформлює елементи<img>
товстою чорною рамкою і золотистим фоном.
/* Контекстний CSS */
@scope (.feature) {
:scope {
background: rebeccapurple;
color: antiquewhite;
font-family: sans-serif;
}
figure {
background-color: white;
border: 2px solid black;
color: black;
padding: 10px;
}
}
/* Кільцевий контекст */
@scope (.feature) to (figure) {
img {
border: 5px solid black;
background-color: goldenrod;
}
}
Результат
У візуалізованому коді зверніть увагу на те, що всі елементи <img>
оформлені товстою рамкою і золотистим фоном, за винятком того, що знаходиться всередині елемента <figure>
(підписаного «Моя інфографіка»).
Специфікації
Сумісність із браузерами
Дивіться також
:scope
CSSScopeRule
- Обмежуйте область дії своїх селекторів за допомогою директиви CSS
@scope
на developer.chrome.com (2023)