BEM in Vue: Saubere Styles für skalierbare Komponenten
BEM bleibt in Vue-Projekten relevant, dank seiner strengen Klassen-Hierarchie, die Stilkonflikte in komponentenbasierten Architekturen verhindert. Vue kümmert sich um Reaktivität und Logik, während BEM für die Unabhängigkeit von Blöcken und Elementen sorgt. Diese Kombination vermeidet CSS-Chaos, wenn die App wächst.
BEM basiert auf drei Kernprinzipien:
- Block: Eine eigenständige Einheit wie
.headeroder.card, ohne externe Abhängigkeiten. - Element: Ein Unterteil eines Blocks, markiert mit Doppelunterstrich –
.button__icon. - Modifier: Eine Variante oder ein Zustand mit Einzelunterstrich –
.button_disabled,.card_theme_dark.
Diese Struktur isoliert Styles und macht Debugging sowie Refactoring kinderleicht.
Styling in Vue-Komponenten
In Vue landen Styles im <style scoped>, was den Gültigkeitsbereich auf die Komponente beschränkt. Scoped verhindert Stil-Lecks, aber Achtung bei tiefer Verschachtelung.
Nutzen Sie :deep() nur für externe Bibliotheken, wo scoped nicht reicht. Vermeiden Sie es, um eigene Architekturprobleme zu kaschieren – das ist ein Warnsignal.
BEM harmoniert perfekt mit scoped, indem es Klassen logisch gruppiert. Der Block definiert den Basisstil, Modifier Varianten, Elemente die innere Struktur.
Praktisches Beispiel: Button mit Zuständen
Ohne System vermehren sich Klassen chaotisch. Hier ein typischer Fehltritt:
<template>
<button :class="{
'button-basic': isBasic,
'button-href': isHref,
'button-avatar': isAvatar
}">
{{ text }}
</button>
</template>
Probleme:
- Keine Hierarchie: Klassen hängen nicht am Block.
- Skalierbarkeit: Neue Zustände bedeuten mehr Bedingungen.
- Lesbarkeit: Logik verliert sich im Lauf der Zeit.
Mit BEM vereinfacht und dokumentiert sich das Template selbst:
<template>
<button :class="[
'button',
{
'button_disabled': disabled,
'button_loading': loading,
},
{
'button_size_xl': size === 'xl',
'button_size_l': size === 'l',
},
{
'button_primary': color === 'primary',
'button_secondary': color === 'secondary',
}
]">
{{ text }}
</button>
</template>
Klassen gruppiert nach Semantik: Basisblock, Zustände, Größen, Themes. Im CSS:
.button {
/* Basis-Styles */
padding: 12px 24px;
border: none;
border-radius: 4px;
}
.button_disabled {
opacity: 0.5;
cursor: not-allowed;
}
.button_loading {
position: relative;
}
.button_primary:not(.button_disabled):hover {
background-color: #0055ff;
}
Der :not()-Selektor filtert kollidierende Zustände ohne Extraklassen.
Skalierung und Teamarbeit
In großen Projekten reduziert BEM die kognitive Belastung: Entwickler sehen Block und Modifier direkt im Template. Kein Wühlen im CSS, um Styles zu verstehen.
Teamvorteile:
- Vorhersagbarkeit: Klassen Namen spiegeln den Zweck wider.
- Isolation: Blöcke stören sich nicht.
- Erweiterbarkeit: Neue Modifier ohne Refactoring.
Beispiel für eine komplexe Komponente – Produktkarte mit Themes und Größen:
<template>
<div class="card" :class="[
`card_size_${size}`,
`card_theme_${theme}`
]">
<div class="card__image"></div>
<div class="card__title">{{ title }}</div>
<button class="card__button button">Kaufen</button>
</div>
</template>
Innere Elemente erben Kontext, bleiben aber unabhängig.
Wann BEM überspringen
BEM ist für Prototypen oder Landingpages übertrieben: Tailwind oder Utility-Klassen sind schneller. BEM für Langzeitprojekte mit Teams und komplexen UIs.
Wichtige Erkenntnisse
- BEM ergänzt Vue mit strenger Hierarchie, keine Kollisionen mit scoped Styles.
- Modifier gruppieren Zustände und Varianten, Templates werden simpler.
:deep()nur für externe Libs, nicht für interne Hacks.- In großen Projekten beschleunigt BEM Einarbeitung und Refactoring.
- Testen Sie es an einer echten Komponente: Lesbarkeit steigt sofort.
— Editorial Team
Noch keine Kommentare.