Komponentenbibliotheken und CSS
Bisher hat jede Komponente des Kurses ihr eigenes CSS mitgebracht. Vue bietet dafür in Single File Components mehrere Wege, Stile auf eine Komponente zu beschränken. Wer Formulare, Tabellen, Menüs und Dialoge nicht selbst gestalten will, greift zu einer Bibliothek mit fertigen Komponenten oder zu einem CSS-Framework.
In deinem Projekt
Abschnitt betitelt „In deinem Projekt“Eine Bibliothek spart Zeit bei Elementen, die schwierig gut zu bauen sind, etwa ein Datumsfeld, eine sortierbare Tabelle oder ein zugängliches Menü. Dafür bringt sie ihr eigenes Aussehen, zusätzliche Grösse im Build und eine Abhängigkeit, die du später kaum mehr los wirst. Prüf vor der Wahl, ob sie zu deiner Version von Vue passt, gepflegt wird und beschreibt, wie sie mit Tastatur und Screenreader umgeht. Für ein kleines Projekt reicht oft eigenes CSS mit scoped.
Ein kleines Beispiel
Abschnitt betitelt „Ein kleines Beispiel“Mit <style scoped> gibt Vue allen Elementen der Komponente ein eigenes Attribut und hängt es an die Selektoren. Die Regeln wirken so nur in dieser Komponente. Das äusserste Element einer Kindkomponente bekommt das Attribut der Elternkomponente auch, darum erreicht .card .price den Preis. Ein Element weiter innen im Kind erreichst du nur mit :deep(). Der Absatz unter der Karte hat dieselbe Klasse price, bleibt aber normal, weil er nicht in der Karte steht.
App.vue
<script setup>import PriceTag from './PriceTag.vue'</script>
<template> <article class="card"> <h2>Bohrmaschine</h2> <PriceTag :deposit="20" /> </article> <p class="price">Dieser Absatz ist kein Teil der Karte und bleibt normal.</p></template>
<style scoped>.card { max-width: 16rem; padding: 0.75rem; border: 1px solid #c8c8c8; border-radius: 0.5rem;}
h2 { margin: 0 0 0.5rem;}
/* The root element of a child also carries the attribute of this component, so this rule reaches it */.card .price { font-weight: 700;}
/* An element inside the child is only reached through :deep() */.card :deep(.currency) { color: #2e7d32;}</style>PriceTag.vue
<script setup>defineProps({ deposit: { type: Number, required: true },})</script>
<template> <span class="price"><span class="currency">CHF</span> {{ deposit }} Pfand</span></template>v-bind() im CSS verbindet einen Wert mit dem Zustand der Komponente. Vue setzt ihn als CSS-Variable und ändert ihn, sobald sich der Zustand ändert.
<script setup>import { computed, ref } from 'vue'
const available = ref(true)const color = computed(() => (available.value ? '#2e7d32' : '#b71c1c'))</script>
<template> <p class="badge">{{ available ? 'Da' : 'Ausgeliehen' }}</p> <button type="button" @click="available = !available">Status wechseln</button></template>
<style scoped>.badge { display: inline-block; padding: 0.125rem 0.5rem; border-radius: 1rem; color: #fff; /* v-bind() ties the colour to the reactive value and updates it */ background: v-bind(color);}</style><style module> macht aus jeder Klasse einen eindeutigen Namen, den das Template über $style holt. Der Playground unterstützt CSS-Module nicht, in einem Projekt mit Vite funktioniert die Komponente wie gezeigt.
<script setup>defineProps({ available: { type: Boolean, required: true },})</script>
<template> <span :class="[$style.badge, available ? $style.in : $style.out]">{{ available ? 'Da' : 'Ausgeliehen' }}</span></template>
<style module>/* The module turns every class into a unique name, $style returns it by its name in the CSS */.badge { display: inline-block; padding: 0.125rem 0.5rem; border-radius: 1rem; color: #fff;}
.in { background: #2e7d32;}
.out { background: #b71c1c;}</style>Die bekannten Bibliotheken für Vue 3 unterscheiden sich vor allem im Aussehen. Vuetify folgt Material Design, Quasar bringt über 120 Komponenten und eigene Werkzeuge für den Build mit, Element Plus und Naive UI haben eine eigene Gestaltung. Reka UI, früher Radix Vue, liefert Komponenten ohne Stil, die nur Verhalten und Zugänglichkeit mitbringen. Diese Bibliotheken stehen unter der MIT-Lizenz. PrimeVue braucht ab Version 5 einen Lizenzschlüssel und steht unter einer eigenen Lizenz, unter MIT steht noch PrimeVue 4. Lies vor der Wahl die Lizenz und die Seite zur Barrierefreiheit, nicht jede Bibliothek hat eine.
Tailwind CSS geht einen anderen Weg. Statt fertiger Komponenten schreibst du kleine Klassen wie flex oder p-4 direkt ins Template. Mit Vite bindest du es über das Plugin @tailwindcss/vite und die Zeile @import "tailwindcss"; im CSS ein. Tailwind sucht die Klassen als Text in deinen Dateien, ein Klassenname, den der Code erst zur Laufzeit zusammensetzt, bekommt deshalb kein CSS. Ausserdem entfernt Tailwind die Aufzählungszeichen von Listen, und VoiceOver kündigt solche Listen nicht mehr als Listen an, ausser sie tragen role="list".
Offizielle Links
Abschnitt betitelt „Offizielle Links“Texte und Abbildungen stehen unter CC BY-SA 4.0, der Code unter der MIT-Lizenz und die Daten des Kurses unter CC0 1.0. Die Schrift der Abbildungen ist Kalam unter der SIL Open Font License 1.1. Die Quellen liegen auf GitHub.