Динамическое изменение стилей

Lit — современный JavaScript-фреймворк для создания веб-компонентов с высокой производительностью и декларативной моделью обновления интерфейса. Одним из ключевых аспектов построения интерактивных компонентов является динамическое управление стилями. Lit предоставляет несколько инструментов для того, чтобы CSS-правила изменялись в зависимости от состояния компонента, свойства или внешних условий.


Свойство static styles и динамическое наследование

В Lit компоненту можно задавать статические стили через свойство static styles:

import { LitElement, css } from 'lit';

class MyComponent extends LitElement {
  static styles = css`
    :host {
      display: block;
      padding: 16px;
      background-color: lightgray;
    }
    .text {
      color: black;
    }
  `;
}

Эти стили применяются один раз при инициализации компонента и не изменяются при обновлении состояния. Для динамического изменения внешнего вида требуется использование реактивных свойств и директив, таких как styleMap и classMap.


Директива styleMap

styleMap позволяет привязывать объект JavaScript к стилям элемента:

import { LitElement, html } from 'lit';
import { styleMap } from 'lit/directives/style-map.js';

class StyledBox extends LitElement {
  static properties = {
    color: { type: String },
    width: { type: String },
  };

  constructor() {
    super();
    this.color = 'blue';
    this.width = '100px';
  }

  render() {
    const styles = {
      backgroundColor: this.color,
      width: this.width,
      height: '100px',
    };
    return html`<div style=${styleMap(styles)}></div>`;
  }
}

Ключевой момент: любые изменения значений color или width автоматически вызовут повторный рендер компонента, и стили обновятся.


Директива classMap

classMap применяется для динамического добавления и удаления CSS-классов:

import { classMap } from 'lit/directives/class-map.js';

class DynamicClass extends LitElement {
  static properties = {
    isActive: { type: Boolean }
  };

  constructor() {
    super();
    this.isActive = false;
  }

  render() {
    const classes = { active: this.isActive, inactive: !this.isActive };
    return html`<div class=${classMap(classes)}>Текст</div>`;
  }
}

С помощью classMap можно легко переключать классы в зависимости от состояния компонента без прямого изменения стилей через объект.


Привязка CSS-переменных

Использование CSS-переменных (--variable-name) обеспечивает гибкое управление стилями на уровне шаблона и стилей компонента:

class CssVariableComponent extends LitElement {
  static properties = {
    color: { type: String }
  };

  constructor() {
    super();
    this.color = 'red';
  }

  render() {
    return html`
      <div style="--box-color: ${this.color};" class="box">Контент</div>
    `;
  }

  static styles = css`
    .box {
      width: 100px;
      height: 100px;
      background-color: var(--box-color);
    }
  `;
}

CSS-переменные позволяют создавать единый стиль и изменять его без пересборки всего CSS. Это особенно полезно для темизации и адаптивного дизайна.


Реактивные свойства и стили

Lit построен на реактивной модели. Любое свойство, объявленное через static properties, автоматически отслеживается. Изменение свойства вызывает повторный рендер шаблона:

class ReactiveStyles extends LitElement {
  static properties = {
    highlighted: { type: Boolean }
  };

  constructor() {
    super();
    this.highlighted = false;
  }

  toggleHighlight() {
    this.highlighted = !this.highlighted;
  }

  render() {
    return html`
      <div style=${styleMap({ 
        backgroundColor: this.highlighted ? 'yellow' : 'white' 
      })}>Текст</div>
      <button @click=${this.toggleHighlight}>Переключить</button>
    `;
  }
}

Использование реактивных свойств вместе с styleMap позволяет создавать сложные визуальные эффекты, управляемые состоянием компонента.


Взаимодействие с внешними стилями

Иногда необходимо, чтобы компонент реагировал на стили, определённые вне него. Для этого можно использовать:

  • CSS-переменные на уровне :host;
  • adoptedStyleSheets для динамического подключения стилей;
  • наблюдение за свойствами DOM через MutationObserver.

Пример применения CSS-переменной из родительского документа:

class HostStyledComponent extends LitElement {
  render() {
    return html`
      <div class="container">Контент</div>
    `;
  }

  static styles = css`
    .container {
      color: var(--host-text-color, black);
    }
  `;
}

Если в родительском документе задана --host-text-color, компонент автоматически изменит цвет текста без внутреннего вмешательства.


Итоговые рекомендации по динамическим стилям

  • Для изменения отдельных CSS-свойств лучше использовать styleMap.
  • Для переключения наборов классов применяется classMap.
  • Для глобальной или темовой адаптации удобны CSS-переменные.
  • Реактивные свойства позволяют управлять стилями через состояние компонента без прямого DOM-манипулирования.
  • Комбинация этих подходов позволяет создавать гибкие, производительные и легко поддерживаемые веб-компоненты.