Работа с пользовательским контентом: тег <content> и <shadow> (Web Components)
🌟 Введение: Почему <content> и <shadow> — это круто
Web Components — это как конструктор LEGO для веба. А теги <content> и <shadow> — это волшебные кирпичики, которые помогают управлять содержимым и создавать изолированные стили.
🔹 Зачем это нужно?
- Чтобы переиспользовать компоненты без костылей.
- Чтобы стили не «убегали» за пределы компонента.
- Чтобы создавать по-настоящему модульные интерфейсы.
🧩 <content>: Управляем вставкой контента
Тег <content> (из спецификации Shadow DOM v0, сейчас заменён на <slot>, но важно знать основы!) позволял «проецировать» внешний контент внутрь шаблона.
🛠️ Пример: Кастомная кнопка
<!-- 1. Объявляем шаблон -->
<template id="my-button">
<style>
button { background: #42b983; color: white; border: none; padding: 10px; }
</style>
<button>
<content></content> <!-- Сюда вставится переданный текст -->
</button>
</template>
<!-- 2. Используем компонент -->
<my-button>Нажми меня!</my-button>
<script>
const template = document.querySelector('#my-button');
customElements.define('my-button', class extends HTMLElement {
connectedCallback() {
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.appendChild(template.content.cloneNode(true));
}
});
</script>
Что произошло?
1. В <content> подставился текст Нажми меня!.
2. Стили кнопки изолированы внутри Shadow DOM.
🕶️ <shadow>: Наследуем и дополняем
Тег <shadow> (устарел, но полезен для понимания) позволял обращаться к «старому» содержимому Shadow DOM при наследовании.
🔄 Пример: Расширение компонента
Допустим, у нас есть базовый компонент <cool-heading>, и мы хотим его улучшить:
<!-- Базовый компонент -->
<template id="cool-heading">
<style> h1 { color: red; } </style>
<h1><content></content></h1>
</template>
<!-- Улучшенная версия -->
<template id="super-heading">
<style> h1 { text-shadow: 2px 2px 4px gray; } </style>
<shadow></shadow> <!-- Рендерим исходный h1 -->
<small>Дополнительный текст</small>
</template>
<script>
customElements.define('cool-heading', class extends HTMLElement {
connectedCallback() {
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.innerHTML = `
<style>h1 { color: red; }</style>
<h1><slot></slot></h1>
`;
}
});
// Переопределяем компонент
const superTemplate = document.querySelector('#super-heading');
customElements.define('super-heading', class extends HTMLElement {
connectedCallback() {
const shadowRoot = this.attachShadow({ mode: 'open' });
shadowRoot.appendChild(superTemplate.content.cloneNode(true));
}
});
</script>
Итог:
— <shadow> показывал исходное содержимое (красный h1).
— Поверх добавлялись новые стили и элементы (<small>).
💡 Современная альтернатива: <slot>
В Shadow DOM v1 <content> и <shadow> заменены на <slot>. Он мощнее и удобнее!
🎯 Пример с именованными слотами
<template id="user-card">
<div class="card">
<h2><slot name="username">Имя пользователя</slot></h2>
<p><slot name="email">Email</slot></p>
</div>
</template>
<!-- Использование -->
<user-card>
<span slot="username">Данила Бежин</span>
<span slot="email">danila@example.com</span>
</user-card>
Плюсы:
- Можно менять порядок вывода.
- Есть fallback-контент (если слот пуст).
📌 Главные выводы
<content>— устаревший, но важный для понимания основ.<shadow>— позволял «наслаивать» Shadow DOM (теперь используйте композицию компонентов).<slot>— современный и гибкий инструмент для работы с контентом.
Для глубокого погружения в Web Components загляните на YouTube-канал Данилы Бежина — там есть разборы с живыми примерами!
Действие → Попробуйте создать свой компонент с <slot> и изолированными стилями. Это первый шаг к чистому и переиспользуемому коду! 🚀