::slotted для контента слотов

В Atomico слоты реализуются аналогично Web Components. Слоты позволяют вставлять внешний контент внутрь компонента, сохраняя его структуру и стилизацию. Для управления стилями элементов внутри слота используется псевдокласс ::slotted, который играет ключевую роль при стилизации вставленного контента.


Синтаксис ::slotted

Псевдокласс ::slotted применяется внутри CSS компонента и позволяет выбирать элементы, переданные в слот. Основной синтаксис:

::slotted(selector) {
    /* стили для элементов, попадающих в слот */
}
  • selector — селектор элементов, находящихся в слоте.
  • Псевдокласс работает только с непосредственными потомками слота. Глубокие вложенные элементы не будут затронуты.

Пример компонента с использованием слотов:

import { c, css, html } from "atomico";

function MyCard() {
    return html`
        <div class="card">
            <slot name="header"></slot>
            <slot name="content"></slot>
        </div>
    `;
}

MyCard.styles = css`
    .card {
        border: 1px solid #ccc;
        padding: 16px;
        border-radius: 8px;
        background: #fff;
    }

    ::slotted([slot="header"]) {
        font-weight: bold;
        font-size: 1.2em;
        margin-bottom: 8px;
    }

    ::slotted([slot="content"]) {
        color: #333;
        line-height: 1.5;
    }
`;

customElements.define("my-card", c(MyCard));

В этом примере ::slotted([slot="header"]) применяет стили только к элементам, переданным в слот с именем header.


Ограничения и особенности

  1. Невозможность вложенной селекции Псевдокласс ::slotted не поддерживает глубокие вложенные селекторы. Например:

    ::slotted(div span) {
        color: red; /* НЕ будет работать */
    }

    Работает только прямой элемент, вставленный в слот:

    ::slotted(div) {
        color: red; /* Работает */
    }
  2. Совместимость с атрибутами Стилизация через ::slotted может использовать атрибутные селекторы, что удобно для динамических компонентов:

    ::slotted([data-type="highlight"]) {
        background: yellow;
    }
  3. Наследование стилей Стили, применяемые через ::slotted, не наследуются на потомков переданного элемента. Для управления вложенными элементами необходимо использовать обычные классы внутри самого переданного контента.


Применение в Atomico

Atomico позволяет сочетать слоты и ::slotted с реактивными свойствами компонента:

import { c, css, html, useState } from "atomico";

function AlertBox() {
    const [type, setType] = useState("info");

    return html`
        <div class="alert ${type}">
            <slot></slot>
        </div>
    `;
}

AlertBox.styles = css`
    .alert {
        padding: 12px 16px;
        border-radius: 4px;
        font-size: 1em;
    }

    .alert.info {
        background: #e0f0ff;
        border: 1px solid #b0d4ff;
    }

    .alert.error {
        background: #ffe0e0;
        border: 1px solid #ffb0b0;
    }

    ::slotted(p) {
        margin: 0;
        font-weight: bold;
    }
`;

customElements.define("alert-box", c(AlertBox));

С помощью ::slotted(p) внутри AlertBox можно гарантированно стилизовать все переданные абзацы <p> без изменения их внутренней структуры.


Динамическая стилизация

Для компонентов, где тип или состояние меняются динамически, ::slotted работает в сочетании с классами на корневом элементе:

::slotted(.warning) {
    color: orange;
    font-style: italic;
}

В этом случае любой элемент с классом warning, вставленный в слот, получит нужное оформление, независимо от того, какой компонент его оборачивает.


Практические советы

  • Использовать селекторы по атрибутам или классам для точного контроля внешнего контента.
  • Избегать вложенных селекторов, рассчитывая на прямых детей слота.
  • Для сложной стилизации внутреннего контента предпочтительнее применять классы на уровне самого компонента, передавая их через API компонента.
  • Комбинировать реактивные состояния Atomico с ::slotted для динамического изменения внешнего вида слотов.

::slotted в Atomico обеспечивает безопасную и предсказуемую стилизацию контента слотов, сохраняя инкапсуляцию и гибкость компонентов, что делает его незаменимым инструментом при построении масштабируемых UI.