Spec-Zone.ru › Lit 2

Стили

Шаблон вашего компонента отображается в его теневом корне. Стили, которые вы добавляете в компонент, автоматически ограничиваются теневым корнем и влияют только на элементы в теневом корне компонента.

Shadow DOM обеспечивает строгую изоляцию стилей. Если бы Lit не использовал Shadow DOM, вам пришлось бы быть предельно осторожными, чтобы случайно не стилизовать элементы за пределами компонента — его предков или потомков. Это могло бы потребовать написания длинных и неудобных в использовании имен классов. Благодаря Shadow DOM Lit гарантирует, что любой написанный вами селектор применяется только к элементам в теневом корне компонента Lit.

Добавление стилей в компонент

Вы определяете ограниченные областию видимости стили в статическом поле класса styles с помощью функции шаблонного литерала с тегом css. Такое определение стилей обеспечивает наиболее оптимальную производительность:

Стили, которые вы добавляете в компонент, ограничиваются с помощью Shadow DOM. Краткий обзор см. в разделе Shadow 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';
  }

Обзор стилизации Shadow DOM

В этом разделе приведен краткий обзор стилизации Shadow 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(*) соответствует всем элементам, переданным в slot.
  • ::slotted(p) соответствует абзацам, переданным в slot.
  • p ::slotted(*) соответствует элементам, переданным в slot, у которых <slot> является потомком элемента абзаца.

Обратите внимание: стилизовать с помощью ::slotted() можно только прямые дочерние элементы, переданные в slot.

<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 при работе с содержимым, переданным в slot. Подробные сведения о том, как использовать синтаксис ::slotted() с учетом совместимости с полифилом, см. в разделе Ограничения ShadyCSS.

Определение стилей с ограниченной областью действия в шаблоне

Для оптимальной производительности рекомендуется использовать статическое поле класса styles. Однако иногда может потребоваться определить стили в шаблоне Lit. Есть два способа добавить в шаблон стили с ограниченной областью действия:

  • Добавить стили с помощью элемента <style>.
  • Добавить стили с помощью внешней таблицы стилей (не рекомендуется).

У каждого из этих способов есть свои преимущества и недостатки.

В элементе style

Обычно стили помещают в статическое поле класса styles; однако статическое свойство элемента styles вычисляется один раз для каждого класса. Иногда требуется настраивать стили для каждого экземпляра. Для этого рекомендуется использовать свойства CSS, чтобы создавать элементы с поддержкой тем. Кроме того, в шаблон Lit можно включить элементы <style>. Они обновляются для каждого экземпляра.

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 при использовании выражений. Из-за ограничений полифила ShadyCSS выражения в элементах <style> не обновляются для каждого экземпляра. Кроме того, при использовании полифила 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:

  1. Импортируйте classMap и/или styleMap:

    import { classMap } from 'lit/directives/class-map.js';
    import { styleMap } from 'lit/directives/style-map.js';
  2. Используйте 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, используется оно; в противном случае по умолчанию используется 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/v2/components/styles/

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API