Haunted — это современная библиотека для создания веб-компонентов на базе функционального подхода с использованием Hooks, вдохновлённых React. Встроенные возможности Haunted позволяют использовать CSS-модули для стилизации компонентов, обеспечивая локальный scope стилей и предотвращая их конфликт с глобальными стилями страницы.
CSS-модули — это отдельные файлы .css или
.module.css, которые при сборке проекта преобразуются в
объекты с уникальными именами классов. В Haunted их подключение выглядит
следующим образом:
import { html, component } from 'haunted';
import styles from './Button.module.css';
function Button({ label }) {
return html`
<button class="${styles.button}">
${label}
</button>
`;
}
customElements.define('my-button', component(Button));
Особенности:
styles.button содержит уникальное имя класса,
сгенерированное сборщиком (например, Webpack или Vite).${}.Haunted поддерживает динамическое формирование классов при помощи тернарных операторов и шаблонных литералов:
import { html, component } from 'haunted';
import styles from './Alert.module.css';
function Alert({ message, type }) {
const alertClass = type === 'error' ? styles.error : styles.success;
return html`
<div class="${alertClass}">
${message}
</div>
`;
}
customElements.define('my-alert', component(Alert));
Ключевые моменты:
Любые условия для классов обрабатываются на этапе рендера.
Использование шаблонных литералов позволяет комбинировать несколько классов:
class="${styles.base} ${type === 'warning' ? styles.warning : ''}"В отличие от глобальных стилей, CSS-модули создают локальные имена классов, что гарантирует отсутствие конфликтов:
/* Card.module.css */
.card {
border-radius: 8px;
padding: 16px;
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
}
import styles from './Card.module.css';
function Card({ content }) {
return html`
<div class="${styles.card}">
${content}
</div>
`;
}
Каждый класс .card при сборке превращается в уникальный
идентификатор, например: Card_card__3f7X2. Это делает стили
полностью изолированными, даже если на странице есть другие компоненты с
классом card.
Haunted использует Hooks для управления состоянием компонентов. CSS-модули легко сочетаются с ними:
import { html, component } from 'haunted';
import { useState } from 'haunted';
import styles from './Toggle.module.css';
function Toggle() {
const [active, setActive] = useState(false);
return html`
<button
class="${active ? styles.active : styles.inactive}"
@click=${() => setActive(!active)}
>
${active ? 'Включено' : 'Выключено'}
</button>
`;
}
customElements.define('my-toggle', component(Toggle));
Особенности взаимодействия:
useState) напрямую влияет на
класс через привязку ${}.CSS-модули позволяют изолировать не только базовые стили, но и анимации:
/* Fade.module.css */
.fadeIn {
animation: fadeIn 0.5s ease-in-out;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
import styles from './Fade.module.css';
function FadeBox() {
return html`
<div class="${styles.fadeIn}">
Появление с анимацией
</div>
`;
}
Преимущества:
CSS-модули поддерживают композицию стилей, что позволяет комбинировать базовые и специфические классы:
/* Button.module.css */
.base {
padding: 8px 16px;
border-radius: 4px;
}
.primary {
composes: base;
background-color: blue;
color: white;
}
import styles from './Button.module.css';
function PrimaryButton({ label }) {
return html`<button class="${styles.primary}">${label}</button>`;
}
Особенности:
composes: base; наследует все свойства класса
base.Для использования CSS-модулей в Haunted проекте требуется поддержка сборщика:
css-loader с опцией
modules: true..module.css.Пример конфигурации Webpack:
module.exports = {
module: {
rules: [
{
test: /\.module\.css$/,
use: [
'style-loader',
{
loader: 'css-loader',
options: { modules: true }
}
]
}
]
}
};
Иногда нужно сочетать локальные CSS-модули и глобальные CSS-файлы. Для этого:
import './global.css';
import styles from './LocalComponent.module.css';
function Component() {
return html`
<div class="${styles.container} global-class">
Комбинация локальных и глобальных стилей
</div>
`;
}
styles.CSS-модули в Haunted создают удобный и безопасный способ стилизации веб-компонентов, обеспечивая инкапсуляцию, динамичность и масштабируемость проекта. Они идеально сочетаются с функциональным подходом и хуками, позволяя создавать модульные, управляемые и легко поддерживаемые интерфейсы.