CSS Shadow Parts — это механизм, позволяющий
стилизовать части веб-компонентов, скрытые внутри их Shadow DOM. В
Stencil использование Shadow DOM обеспечивает инкапсуляцию стилей, что
предотвращает непреднамеренное влияние глобальных CSS на внутренние
элементы компонента. Однако иногда требуется предоставить возможность
внешней стилизации отдельных внутренних элементов. Для этого применяются
part и
::part().
partЛюбой элемент внутри Shadow DOM компонента может быть помечен
атрибутом part. Синтаксис:
<div part="header">Заголовок</div>
part — имя части, доступной для
внешней стилизации.<div part="header title">Заголовок</div>
В Stencil это можно использовать внутри JSX в методе
render():
render() {
return (
<section>
<header part="header">Заголовок</header>
<p part="content">Основной текст</p>
<footer part="footer">Подвал</footer>
</section>
);
}
::part()Внешний CSS может нацеливаться на элементы внутри Shadow DOM с
помощью селектора ::part(). Синтаксис:
my-component::part(header) {
font-size: 24px;
color: #333;
}
my-component::part(content) {
line-height: 1.6;
}
my-component::part(footer) {
text-align: center;
color: #999;
}
Ключевые моменты:
::part() работает только с
элементами, помеченными атрибутом part.my-component::part(header),
my-component::part(footer) {
font-weight: bold;
}
Stencil поддерживает использование CSS переменных внутри Shadow DOM.
При комбинации с ::part() можно создавать гибкие стили,
доступные для настройки извне.
render() {
return (
<button part="button" style={{ '--btn-color': 'var(--primary-color)' }}>
Нажми меня
</button>
);
}
Внешний CSS:
my-button::part(button) {
background-color: var(--btn-color);
padding: 10px 20px;
border-radius: 5px;
}
Это позволяет пользователям компонента изменять стили через глобальные CSS-переменные, сохраняя инкапсуляцию внутренних элементов.
::part() и вложенные компонентыЕсли компонент содержит вложенные компоненты с собственным Shadow
DOM, селектор ::part() работает только на первом уровне.
Чтобы стилизовать внутренние части вложенного компонента, нужно напрямую
использовать ::part() на самом вложенном компоненте:
<outer-component>
<inner-component part="inner"></inner-component>
</outer-component>
CSS:
outer-component::part(inner) {
margin: 20px;
}
inner-component::part(header) {
font-size: 18px;
}
Таким образом обеспечивается точечная настройка стилей без нарушения инкапсуляции.
header, content, footer легче
поддерживать, чем абстрактные part1,
part2.part и их
назначения.part и ::part() есть во всех
современных браузерах, включая Chrome, Edge, Firefox и Safari.::part() не может нацеливаться на псевдоэлементы
(::before, ::after) внутри Shadow DOM.part не влияет на доступность или структуру DOM
— это чисто стилистический инструмент.@Component({
tag: 'card-component',
shadow: true,
styleUrl: 'card-component.css'
})
export class CardComponent {
render() {
return (
<div class="card">
<div part="header">Заголовок карты</div>
<div part="body">
<slot></slot>
</div>
<div part="footer">Подвал карты</div>
</div>
);
}
}
Внешний CSS:
card-component::part(header) {
font-size: 20px;
font-weight: bold;
padding: 10px;
}
card-component::part(body) {
padding: 15px;
}
card-component::part(footer) {
font-size: 12px;
text-align: right;
}
Такой подход позволяет создавать полностью инкапсулированные компоненты с гибкой внешней стилизацией отдельных элементов.