Стили
Шаблон вашего компонента отображается в его корневом теневом DOM. Стили, добавленные в компонент, автоматически ограничиваются корневым теневым DOM и влияют только на элементы в корневом теневом DOM компонента.
Теневой DOM обеспечивает строгую инкапсуляцию стилей. Если бы Lit не использовал теневой DOM, вам пришлось бы быть предельно осторожными, чтобы случайно не стилизовать элементы за пределами компонента — ни его предков, ни его дочерние элементы. Возможно, для этого пришлось бы использовать длинные и неудобные имена классов. Благодаря теневому DOM Lit гарантирует, что любой написанный вами селектор применяется только к элементам в корневом теневом DOM вашего компонента Lit.
Добавление стилей в компонент
Определяйте стили с ограниченной областью действия в статическом поле класса styles с помощью функции css, использующей помеченный шаблонный литерал. Такой способ определения стилей обеспечивает оптимальную производительность:
Стили, добавленные в компонент, ограничиваются теневым DOM. Краткий обзор см. в разделе Теневой DOM.
Значением статического поля класса styles может быть:
-
Один помеченный шаблонный литерал.
static styles = css`...`;
-
Массив помеченных шаблонных литералов.
static styles = [ css`...`, css`...`];
Статическое поле класса styles почти всегда лучше всего подходит для добавления стилей в компонент, но есть случаи, которые таким способом не обработать, — например, настройка стилей для каждого экземпляра. Другие способы добавления стилей см. в разделе Определение стилей с ограниченной областью действия в шаблоне.
Использование выражений в статических стилях
Статические стили применяются ко всем экземплярам компонента. Любые выражения в CSS вычисляются один раз, а затем используются повторно для всех экземпляров.
Для настройки стилей на основе дерева элементов или для каждого экземпляра используйте пользовательские свойства CSS, чтобы элементы можно было оформлять с помощью тем.
Чтобы компоненты Lit не выполняли потенциально вредоносный код, тег css допускает только вложенные выражения, которые сами являются строками или числами, помеченными тегом css.
const mainColor = css`red`;
...
static styles = css`
div { color: ${mainColor} }
`;
Это ограничение защищает приложения от уязвимостей, при которых вредоносные стили или даже код могут внедряться из ненадёжных источников, таких как параметры URL или значения в базе данных.
Если необходимо использовать в литерале css выражение, которое само по себе не является литералом css, и вы уверены, что выражение получено из полностью надёжного источника, например константы, определённой в вашем коде, оберните его функцией unsafeCSS:
const mainColor = 'red';
...
static styles = css`
div { color: ${unsafeCSS(mainColor)} }
`;
Используйте тег unsafeCSS только с доверенными данными. Внедрение непроверенного CSS представляет угрозу безопасности. Например, вредоносный CSS может «позвонить домой», добавив URL изображения, указывающий на сторонний сервер.
Наследование стилей от суперкласса
Используя массив помеченных шаблонных литералов, компонент может наследовать стили суперкласса и добавлять собственные:
Вы также можете использовать super.styles, чтобы обратиться к свойству стилей суперкласса в JavaScript. Если вы используете TypeScript, рекомендуем не использовать super.styles, поскольку компилятор не всегда преобразует его корректно. Явная ссылка на суперкласс, как в примере, позволяет избежать этой проблемы.
При написании компонентов, предназначенных для расширения в TypeScript, поле static styles следует явно типизировать как CSSResultGroup, чтобы пользователи могли переопределять styles массивом:
// Prevent typescript from narrowing the type of `styles` to `CSSResult` // so that subclassers can assign e.g. `[SuperElement.styles, css`...`]`; static styles: CSSResultGroup = css`...`;
Совместное использование стилей
Стили можно использовать в нескольких компонентах, создав модуль, экспортирующий помеченные стили:
export const buttonStyles = css`
.blue-button {
color: white;
background-color: blue;
}
.blue-button:disabled {
background-color: grey;
}`;
Затем элемент может импортировать стили и добавить их в статическое поле класса styles:
import { buttonStyles } from './button-styles.js';
class MyElement extends LitElement {
static styles = [
buttonStyles,
css`
:host { display: block;
border: 1px solid black;
}`
];
}
Использование escape-последовательностей Unicode в стилях
Escape-последовательность Unicode в CSS — это обратная косая черта, за которой следуют четыре или шесть шестнадцатеричных цифр: например, \2022 для символа-маркера списка. Этот формат похож на формат устаревших восьмеричных escape-последовательностей JavaScript, поэтому использование таких последовательностей в помеченном шаблонном литерале css приводит к ошибке.
Есть два способа добавить escape-последовательность Unicode в стили:
- Добавить вторую обратную косую черту (например,
\\2022). - Использовать escape-последовательность JavaScript, начинающуюся с
\u(например,\u2022).
static styles = css`
div::before {
content: '\u2022';
}
Обзор стилизации теневого DOM
В этом разделе кратко рассматривается стилизация теневого DOM.
Стили, добавленные в компонент, могут влиять на:
- Теневое дерево (отрисованный шаблон компонента).
- Сам компонент.
- Дочерние элементы компонента.
Стилизация теневого дерева
По умолчанию шаблоны Lit отображаются в теневом дереве. Стили, ограниченные теневым деревом элемента, не влияют на основной документ или другие теневые деревья. Аналогично, за исключением наследуемых свойств CSS, стили уровня документа не влияют на содержимое теневого дерева.
При использовании стандартных селекторов CSS они выбирают только элементы в теневом дереве вашего компонента. Это значит, что часто можно использовать очень простые селекторы: не нужно опасаться, что они случайно повлияют на другие части страницы. Например: input, * или #my-element.
Стилизация самого компонента
Для стилизации самого компонента можно использовать специальные селекторы :host. (Элемент, которому принадлежит теневое дерево, то есть элемент, который его «хостит», называется элементом-хостом.)
Чтобы задать стили по умолчанию для элемента-хоста, используйте псевдокласс CSS :host и функцию-псевдокласс CSS :host().
-
:hostвыбирает элемент-хост. -
:host(selector)выбирает элемент-хост, только если он соответствует селектору.
Обратите внимание: на элемент-хост могут также влиять стили за пределами теневого дерева, поэтому правила :host и :host() следует рассматривать как стили по умолчанию, которые пользователь может переопределить. Например:
my-element {
display: inline-block;
}
Стилизация дочерних элементов компонента
Компонент может принимать дочерние элементы (например, элемент <ul> может содержать дочерние элементы <li>). Чтобы отобразить дочерние элементы, шаблон должен содержать один или несколько элементов <slot>, как описано в разделе Отображение дочерних элементов с помощью элемента slot.
Элемент <slot> служит заполнителем в теневом дереве, где отображаются дочерние элементы элемента-хоста.
Используйте псевдоэлемент CSS ::slotted(), чтобы выбирать дочерние элементы, включённые в шаблон с помощью элементов <slot>.
-
::slotted(*)выбирает все распределённые элементы. -
::slotted(p)выбирает распределённые абзацы. -
p ::slotted(*)выбирает распределённые элементы, у которых<slot>является потомком элемента абзаца.
Обратите внимание: стилизовать с помощью ::slotted() можно только непосредственно распределённые дочерние элементы.
<my-element> <div>Stylable with ::slotted()</div> </my-element> <my-element> <div><p>Not stylable with ::slotted()</p></div> </my-element>
Кроме того, стили дочерних элементов можно задавать за пределами теневого дерева, поэтому стили ::slotted() следует считать стилями по умолчанию, которые можно переопределить.
my-element > div {
/* Outside style targetting a slotted child can override ::slotted() styles */
}
Ограничения полифила ShadyCSS при работе с распределённым содержимым. Подробные сведения о том, как использовать синтаксис ::slotted() с учётом совместимости с полифилом, см. в разделе Ограничения ShadyCSS.
Определение стилей с ограниченной областью действия в шаблоне
Для оптимальной производительности мы рекомендуем использовать статическое поле класса styles. Однако иногда может потребоваться определить стили в шаблоне Lit. Есть два способа добавить в шаблон стили с ограниченной областью действия:
- Добавить стили с помощью элемента
<style>. - Добавить стили с помощью внешней таблицы стилей (не рекомендуется).
У каждого из этих способов есть свои преимущества и недостатки.
В элементе style
Обычно стили размещают в статическом поле класса styles, однако статические styles элемента вычисляются один раз для каждого класса. Иногда может потребоваться настроить стили для каждого экземпляра. Для этого мы рекомендуем использовать свойства CSS, чтобы создавать элементы с поддержкой тем. Также можно включить элементы <style> в шаблон Lit. Они обновляются для каждого экземпляра.
render() {
return html`
<style>
/* updated per instance */
</style>
<div>template content</div>
`;
}
Ограничения полифила ShadyCSS при стилизации отдельных экземпляров. Полифил ShadyCSS не поддерживает стилизацию отдельных экземпляров. Подробности см. в разделе Ограничения ShadyCSS.
Выражения и элементы style
Использование выражений внутри элементов style имеет ряд важных ограничений и может приводить к проблемам с производительностью.
render() {
return html`
<style>
:host {
/* Warning: this approach has limitations & performance issues! */
color: ${myColor}
}
</style>
<div>template content</div>
`;
}
Ограничения полифила ShadyCSS при работе с выражениями. Выражения в элементах <style> не обновляются для каждого экземпляра в ShadyCSS из-за ограничений полифила ShadyCSS. Кроме того, при использовании полифила ShadyCSS узлы <style> нельзя передавать в качестве значений выражений. Дополнительную информацию см. в разделе Ограничения ShadyCSS.
Вычисление выражения внутри элемента <style> крайне неэффективно. При изменении любого текста внутри элемента <style> браузеру приходится заново анализировать весь элемент <style>, что приводит к ненужным затратам.
Чтобы уменьшить эти затраты, разделяйте стили, требующие вычисления для каждого экземпляра, и стили, которым это не требуется.
static styles = css`/* ... */`;
render() {
const redStyle = html`<style> :host { color: red; } </style>`;
return html`${this.red ? redStyle : ''}`
Импорт внешней таблицы стилей (не рекомендуется)
Хотя в шаблон можно включить внешнюю таблицу стилей с помощью <link>, мы не рекомендуем этот подход. Вместо этого стили следует размещать в статическом поле класса styles.
Особенности использования внешних таблиц стилей.
- Полифил ShadyCSS не поддерживает внешние таблицы стилей.
- Внешние стили могут вызывать вспышку неоформленного содержимого (FOUC) во время загрузки.
- URL в атрибуте
hrefуказывается относительно основного документа. Это допустимо при разработке приложения с заранее известными URL ресурсов, но при создании переиспользуемого элемента следует избегать внешних таблиц стилей.
Динамические классы и стили
Один из способов сделать стили динамическими — добавить выражения в атрибуты class или style шаблона.
В Lit есть две директивы — classMap и styleMap, — которые упрощают применение классов и стилей в HTML-шаблонах.
Дополнительные сведения об этих и других директивах см. в документации по встроенным директивам.
Чтобы использовать styleMap и/или classMap:
-
Импортируйте
classMapи/илиstyleMap:import { classMap } from 'lit/directives/class-map.js'; import { styleMap } from 'lit/directives/style-map.js'; Используйте
classMapи/илиstyleMapв шаблоне элемента:
Дополнительные сведения см. в разделах classMap и styleMap.
Темы
Сочетание наследования CSS и переменных CSS и пользовательских свойств позволяет легко создавать элементы с поддержкой тем. С помощью CSS-селекторов можно настраивать пользовательские свойства CSS, что упрощает применение тем для целых деревьев элементов и отдельных экземпляров. Вот пример:
Наследование CSS
Наследование CSS позволяет родительским элементам и элементам-хостам передавать определённые свойства CSS своим потомкам.
Наследуются не все свойства CSS. К наследуемым свойствам CSS относятся:
color-
font-familyи другие свойстваfont-* - Все пользовательские свойства CSS (
--*)
Дополнительные сведения см. в статье «Наследование CSS» на MDN.
С помощью наследования CSS можно задать стили для элемента-предка, которые унаследуют его потомки:
<style>
html {
color: green;
}
</style>
<my-element>
#shadow-root
Will be green
</my-element>
Пользовательские свойства CSS
Все пользовательские свойства CSS (--custom-property-name) наследуются. Это можно использовать, чтобы настраивать стили компонента извне.
Следующий компонент задаёт цвет фона с помощью переменной CSS. Если селектор, соответствующий элементу-предку в дереве DOM, установил значение --my-background, переменная CSS использует это значение; в противном случае используется значение по умолчанию yellow:
class MyElement extends LitElement {
static styles = css`
:host {
background-color: var(--my-background, yellow);
}
`;
render() {
return html`<p>Hello world</p>`;
}
}
Пользователи этого компонента могут задать значение --my-background, используя тег my-element в качестве CSS-селектора:
<style>
my-element {
--my-background: rgb(67, 156, 144);
}
</style>
<my-element></my-element>
Значение --my-background можно настраивать для каждого экземпляра my-element:
<style>
my-element {
--my-background: rgb(67, 156, 144);
}
my-element.stuff {
--my-background: #111111;
}
</style>
<my-element></my-element>
<my-element class="stuff"></my-element>
Дополнительные сведения см. в статье «Пользовательские свойства CSS» на MDN.
© Google LLC
Licensed under the Creative Commons Attribution 3.0 Unported License.
https://lit.dev/docs/components/styles/