Shadow DOM обеспечивает инкапсуляцию компонентов, позволяя отделять их внутренние стили и структуру от остальной страницы. Основная цель — предотвратить утечку стилей внутрь компонента и наружу, однако это накладывает ограничения на наследование CSS, что требует особого подхода при проектировании интерфейсов.
Shadow DOM создает отдельное дерево DOM для компонента. Внутри него:
Это означает, что стандартные CSS-подходы, такие как глобальные классы и теги, работать внутри Shadow DOM не будут без дополнительной настройки.
Некоторые CSS-свойства наследуются естественным образом даже через
границы Shadow DOM. К ним относятся свойства текста: color,
font-family, font-size,
line-height и другие. Эти свойства автоматически
применяются к элементам внутри компонента, если не переопределены
локальными стилями.
Пример:
import { LitElement, html, css } from 'lit';
class MyText extends LitElement {
static styles = css`
p {
font-size: 16px;
color: inherit;
}
`;
render() {
return html`<p>Пример текста, наследующего цвет родителя</p>`;
}
}
customElements.define('my-text', MyText);
В этом примере color: inherit позволяет тексту внутри
компонента наследовать цвет родительского элемента.
Для передачи стилей внутрь Shadow DOM применяются CSS-переменные (custom properties). Они являются ключевым инструментом для гибкой настройки компонентов.
Особенности:
var(--имя-переменной).Пример:
import { LitElement, html, css } from 'lit';
class StyledBox extends LitElement {
static styles = css`
div {
background-color: var(--box-bg, lightgray);
color: var(--box-color, black);
padding: 16px;
}
`;
render() {
return html`<div>Контент с настраиваемыми стилями</div>`;
}
}
customElements.define('styled-box', StyledBox);
В этом примере можно изменить фон и цвет текста компонента, определив переменные на родительском элементе:
styled-box {
--box-bg: #4caf50;
--box-color: white;
}
::part и ::themeДля сложных компонентов, где требуется открытый интерфейс для стилизации, применяются псевдоклассы:
::part позволяет стилизовать конкретные части
компонента, помеченные атрибутом part.::theme в некоторых новых стандартах помогает
определять глобальные темы компонентов.Пример использования part:
import { LitElement, html, css } from 'lit';
class FancyButton extends LitElement {
static styles = css`
button {
background: blue;
color: white;
padding: 10px 20px;
border: none;
border-radius: 4px;
}
`;
render() {
return html`<button part="main-button">Нажми меня</button>`;
}
}
customElements.define('fancy-button', FancyButton);
В CSS внешнего документа можно стилизовать кнопку:
fancy-button::part(main-button) {
background: red;
font-weight: bold;
}
Слоты (slots) позволяют внедрять контент в Shadow DOM, сохраняя его внешние стили. Контент, переданный через слот, продолжает наследовать CSS родительского документа, что обеспечивает комбинацию инкапсуляции и гибкости.
Пример:
import { LitElement, html, css } from 'lit';
class CardElement extends LitElement {
static styles = css`
div {
border: 1px solid #ccc;
padding: 20px;
border-radius: 8px;
}
`;
render() {
return html`<div><slot></slot></div>`;
}
}
customElements.define('card-element', CardElement);
В этом случае любой текст или элементы, помещенные в
<card-element>, сохраняют свои стили родительского
документа.
inherit для базовых свойств, таких как цвет и
шрифты.part.Эффективное управление стилями в Shadow DOM требует понимания границ инкапсуляции и правильного использования инструментов, обеспечивающих взаимодействие с внешним документом без нарушения изоляции компонента.