Svelte Scoped
Platziert generiertes CSS für die Utility-Styles jeder Svelte-Komponente direkt in den <style> Block der Svelte-Komponente, anstatt in einer globalen CSS-Datei.
Diese Komponente:
<div class="mb-1" />wird transformiert zu:
<div class="uno-ei382o" />
<style>
:global(.uno-ei382o) {
margin-bottom: 0.25rem;
}
</style>Wann zu verwenden
| Anwendungsfall | Beschreibung | Zu verwendendes Paket | |
|---|---|---|---|
| Kleinere Apps | ❌ | Eine globale CSS-Datei ist bequemer. Verwenden Sie das reguläre Vite Plugin für Svelte/SvelteKit. | unocss/vite |
| Größere Apps | ✅ | Svelte Scoped kann Ihnen helfen, eine ständig wachsende globale CSS-Datei zu vermeiden. | @unocss/svelte-scoped/vite |
| Komponentenbibliothek | ✅ | Generierte Styles werden direkt in gebaute Komponenten platziert, ohne dass UnoCSS in der Build-Pipeline einer konsumierenden App verwendet werden muss. | @unocss/svelte-scoped/preprocess |
Wie es funktioniert
Ein reguläres UnoCSS/Tailwind CSS Setup platziert Utility-Styles in einer globalen CSS-Datei mit ordnungsgemäßer Reihenfolge. Im Gegensatz dazu verteilt Svelte Scoped Ihre Styles über viele willkürlich geordnete Svelte-Komponenten-CSS-Dateien. Es muss jedoch die Utility-Styles global halten, damit sie kontextbewusst sein können, wie für Dinge wie rechts-nach-links und andere Anwendungsfälle, die unten aufgeführt sind. Dies stellt eine Herausforderung dar, die gelöst wird, indem Sveltes :global() Wrapper verwendet wird, um sich von der Standard-Svelte-CSS-Hashing-Methode abzumelden und stattdessen einen Hash basierend auf Dateiname + Klassenname(n) zu verwenden, um eindeutige Klassennamen zu kompilieren, die global gemacht werden können, ohne Style-Konflikte.
Verwendung
Da Svelte Scoped Ihre Utility-Klassennamen umschreibt, sind Sie in der Lage, wo Sie sie schreiben können, eingeschränkt:
| Unterstützte Syntax | Beispiel |
|---|---|
| Klassen-Attribut | <div class="mb-1" /> |
| Klassen-Direktive | <div class:mb-1={condition} /> |
| Klassen-Direktive-Kurzform | <div class:logo /> |
| Klassen-Prop | <Button class="mb-1" /> |
Svelte Scoped ist darauf ausgelegt, ein Drop-in-Ersatz für ein Projekt zu sein, das Utility-Styles verwendet. Als solches werden auch Ausdrücke innerhalb von Klassen-Attributen unterstützt (z. B. <div class="mb-1 {foo ? 'mr-1' : 'mr-2'}" />), aber wir empfehlen Ihnen, die Klassen-Direktiven-Syntax zu verwenden. Beachten Sie auch, dass wenn Sie Klassennamen auf andere Weise verwendet haben, wie z. B. sie in einen <script> Block zu platzieren oder den Attributify-Modus zu verwenden, müssen Sie zusätzliche Schritte unternehmen, bevor Sie Svelte Scoped verwenden. Sie können die safelist Option verwenden und auch den Abschnitt Presets unten für weitere Tipps überprüfen.
Kontextbewusst
Obwohl Styles über Ihre App-Svelte-Komponenten verteilt sind, sind sie immer noch globale Klassen und funktionieren in Beziehung zu Elementen, die außerhalb ihrer spezifischen Komponenten gefunden werden. Hier sind einige Beispiele:
Elternabhängig
Klassen, die von Attributen abhängen, die in einer Elternkomponente gefunden werden:
<div class="dark:mb-2 rtl:right-0"></div>werden zu:
<div class="uno-3hashz"></div>
<style>
:global(.dark .uno-3hashz) {
margin-bottom: 0.5rem;
}
:global([dir="rtl"] .uno-3hashz) {
right: 0rem;
}
</style>Kinder beeinflussen
Sie können Abstand zwischen 3 Kindelementen hinzufügen, von denen einige in separaten Komponenten sind:
<div class="space-x-1">
<div>Status: online</div>
<Button>FAQ</Button>
<Button>Login</Button>
</div>wird zu:
<div class="uno-7haszz">
<div>Status: online</div>
<Button>FAQ</Button>
<Button>Login</Button>
</div>
<style>
:global(.uno-7haszz > :not([hidden]) ~ :not([hidden])) {
--un-space-x-reverse: 0;
margin-left: calc(0.25rem * calc(1 - var(--un-space-x-reverse)));
margin-right: calc(0.25rem * var(--un-space-x-reverse));
}
</style>Klassen an Kindkomponenten übergeben
Sie können eine class Prop zu einer Komponente hinzufügen, um das Übergeben benutzerdefinierter Klassen zu ermöglichen, wo immer diese Komponente verwendet wird.
<Button class="px-2 py-1">Login</Button>wird zu:
<Button class="uno-4hshza">Login</Button>
<style>
:global(.uno-4hshza) {
padding-left:0.5rem;
padding-right:0.5rem;
padding-top:0.25rem;
padding-bottom:0.25rem;
}
</style>Eine einfache Möglichkeit, die Klasse in einer empfangenden Komponente zu implementieren, wäre, sie auf ein Element zu platzieren, indem Sie {$$props.class} verwenden, wie in div class="{$$props.class} foo bar" />.
Apply-Direktiven
Sie können Apply-Direktiven innerhalb Ihrer <style> Blöcke mit entweder --at-apply oder @apply oder einem benutzerdefinierten Wert verwenden, der mit der applyVariables Option gesetzt wird.
Svelte Scoped behandelt sogar ordnungsgemäß kontextabhängige Klassen wie dark:text-white, die das reguläre @unocss/transformer-directives Paket nicht ordnungsgemäß behandeln kann, weil es nicht speziell für Svelte-Style-Blöcke gebaut wurde. Zum Beispiel wird mit Svelte Scoped diese Komponente:
<div />
<style>
div {
--at-apply: rtl:ml-2;
}
</style>transformiert zu:
<div />
<style>
:global([dir=\\"rtl\\"]) div {
margin-right: 0.5rem;
}
</style>Damit rtl:ml-2 ordnungsgemäß funktioniert, wird der [dir="rtl"] Selektor mit :global() umwickelt, um zu verhindern, dass der Svelte-Compiler ihn automatisch entfernt, da die Komponente kein Element mit diesem Attribut hat. div kann jedoch nicht in den :global() Wrapper eingeschlossen werden, da dieser Style dann jedes div in Ihrer App beeinflussen würde.
Andere Style-Block-Direktiven
Die Verwendung von theme() wird ebenfalls unterstützt, aber @screen wird nicht unterstützt.
Vite Plugin
In Svelte oder SvelteKit Apps injizieren Sie generierte Styles direkt in Ihre Svelte-Komponenten, während Sie die minimal notwendigen Styles in ein globales Stylesheet platzieren. Schauen Sie sich das SvelteKit Beispiel in Stackblitz an:
Installation
pnpm add -D unocss @unocss/svelte-scopedyarn add -D unocss @unocss/svelte-scopednpm install -D unocss @unocss/svelte-scopedbun add -D unocss @unocss/svelte-scopedPlugin hinzufügen
Fügen Sie @unocss/svelte-scoped/vite zu Ihrer Vite-Konfiguration hinzu:
import { sveltekit } from '@sveltejs/kit/vite'
import UnoCSS from '@unocss/svelte-scoped/vite'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [
UnoCSS({
// injectReset: '@unocss/reset/normalize.css', // siehe Typdefinition für alle enthaltenen Reset-Optionen oder wie Sie Ihre eigenen übergeben
// ...andere Svelte Scoped Optionen
}),
sveltekit(),
],
})Konfigurationsdatei hinzufügen
Richten Sie Ihre uno.config.ts Datei wie unten beschrieben ein.
Globale Styles
Während fast alle Styles in einzelne Komponenten platziert werden, gibt es immer noch einige, die in ein globales Stylesheet platziert werden müssen: Preflights, Safelist und ein optionales Reset (wenn Sie die injectReset Option verwenden).
Fügen Sie den %unocss-svelte-scoped.global% Platzhalter in Ihr <head> Tag ein. In Svelte ist dies index.html. In SvelteKit wird dies in app.html vor %sveltekit.head% sein:
<head>
<!-- ... -->
<title>SvelteKit using UnoCSS Svelte Scoped</title>
%unocss-svelte-scoped.global%
%sveltekit.head%
</head>Wenn Sie SvelteKit verwenden, müssen Sie auch Folgendes zum transformPageChunk Hook in Ihrer src/hooks.server.js Datei hinzufügen:
/** @type {import('@sveltejs/kit').Handle} */
export async function handle({ event, resolve }) {
const response = await resolve(event, {
transformPageChunk: ({ html }) =>
html.replace(
'%unocss-svelte-scoped.global%',
'unocss_svelte_scoped_global_styles'
),
})
return response
}Diese Transformation muss in einer Datei sein, deren Pfad hooks und server enthält (z. B. src/hooks.server.js, src/hooks.server.ts), da svelte-scoped in Ihrer Server-Hooks-Datei nach unocss_svelte_scoped_global_styles suchen wird, um es durch Ihre globalen Styles zu ersetzen. Stellen Sie sicher, dass Sie diese Transformation nicht aus einer anderen Datei importieren, wie z. B. bei Verwendung von sequence von @sveltejs/kit/hooks.
In einem regulären Svelte-Projekt wird Vites transformIndexHtml Hook dies automatisch tun.
Svelte Preprocessor
Verwenden Sie Utility-Styles, um eine Komponentenbibliothek zu erstellen, die nicht davon abhängt, eine Begleit-CSS-Datei einzuschließen, indem Sie einen Preprocessor verwenden, um generierte Styles direkt in gebaute Komponenten zu platzieren. Schauen Sie sich das SvelteKit Library Beispiel in Stackblitz an:
Installation
pnpm add -D unocss @unocss/svelte-scopedyarn add -D unocss @unocss/svelte-scopednpm install -D unocss @unocss/svelte-scopedbun add -D unocss @unocss/svelte-scopedPreprocessor hinzufügen
Fügen Sie @unocss/svelte-scoped/preprocess zu Ihrer Svelte-Konfiguration hinzu:
import adapter from '@sveltejs/adapter-auto'
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'
import UnoCSS from '@unocss/svelte-scoped/preprocess'
const config = {
preprocess: [
vitePreprocess(),
UnoCSS({
// ... Preprocessor-Optionen
}),
],
// andere Svelte-Konfiguration
}Klassennamen in der Entwicklung nicht kombinieren
Wenn Sie Svelte Scoped in einer normalen App verwenden, erkennt das Vite Plugin automatisch dev vs build. In der Entwicklung werden Klassen getrennt gehalten und an Ort und Stelle gehasht, um das Ein-/Ausschalten in den Entwicklertools Ihres Browsers zu erleichtern. class="mb-1 mr-1" wird zu etwas wie class="_mb-1_9hwi32 _mr-1_84jfy4. In der Produktion werden diese in einen einzelnen Klassennamen kompiliert, der Ihr gewünschtes Präfix verwendet, standardmäßig uno-, und einen Hash basierend auf Dateiname + Klassennamen, z. B. class="uno-84dke3.
Wenn Sie dasselbe Verhalten beim Verwenden des Preprocessors möchten, müssen Sie die combine Option basierend auf der Umgebung manuell setzen. Eine Möglichkeit, dies zu tun, ist die Installation von cross-env und die Aktualisierung Ihres Dev-Skripts auf:
"dev": "cross-env NODE_ENV=development vite dev"Dann passen Sie Ihre svelte.config.js an:
+const prod = process.env.NODE_ENV !== 'development'
const config = {
preprocess: [
vitePreprocess(),
UnoCSS({
+ combine: prod,
}),
],
}Konfigurationsdatei hinzufügen
Richten Sie Ihre uno.config.ts Datei wie unten beschrieben ein.
Preflights
Wenn Sie den Preprocessor verwenden, haben Sie die Option, Preflights in die spezifische(n) Komponente(n) einzuschließen, wo sie benötigt werden, indem Sie uno-preflights als Style-Attribut hinzufügen.
<style uno-preflights></style>Alle speziellen Preflights, die mit einem Punkt beginnen, wie .prose :where(a):not(:where(.not-prose, .not-prose *)), werden mit :global() umwickelt, um zu vermeiden, dass sie automatisch vom Svelte-Compiler entfernt werden.
Das Hinzufügen von Preflights zu einzelnen Komponenten ist unnötig, wenn Ihre Klassen nicht von Preflights abhängen oder Ihre gebauten Komponenten nur in Apps verwendet werden, die bereits Preflights enthalten.
Safelist
Wenn Sie den Preprocessor verwenden, haben Sie die Option, Safelist-Klassen in einer Komponente einzuschließen, indem Sie uno-safelist als Style-Attribut hinzufügen.
<style uno-safelist></style>Ihre Safelist-Styles werden mit :global() umwickelt, um zu vermeiden, dass sie automatisch vom Svelte-Compiler entfernt werden.
Konfiguration
Platzieren Sie Ihre UnoCSS-Einstellungen in einer uno.config.ts Datei:
import { defineConfig } from 'unocss'
export default defineConfig({
// ...UnoCSS Optionen
})Extractors werden aufgrund der Unterschiede in der normalen UnoCSS-Global-Verwendung und der Svelte Scoped-Verwendung nicht unterstützt. Presets und Transformer werden wie in den folgenden Abschnitten beschrieben unterstützt. Siehe Konfigurationsdatei und Konfigurationsreferenz für alle anderen Details.
Preset-Unterstützung
Aufgrund der Natur, einige notwendige Styles in einem globalen Stylesheet und alles andere in jeder Komponente enthalten zu haben, wo benötigt, müssen Presets von Fall zu Fall behandelt werden:
| Preset | Unterstützt | Hinweise |
|---|---|---|
| ✅ | Diese und alle Community-Plugins, z. B. unocss-preset-forms, die nur auf Regeln/Varianten/Preflights angewiesen sind, funktionieren. | |
| @unocss/preset-typography | ✅ | Aufgrund der Art, wie dieses Preset Rulesets zu Ihren Preflights hinzufügt, müssen Sie die prose Klasse zu Ihrer Safelist hinzufügen, wenn Sie dieses Preset verwenden, andernfalls werden die Preflights niemals ausgelöst. Alle anderen Klassen aus diesem Preset, z. B. prose-pink, können komponenten-scoped sein. |
| @unocss/preset-rem-to-px | ✅ | Dies und alle Presets wie es, die nur die Style-Ausgabe modifizieren, funktionieren. |
| @unocss/preset-attributify | - | Preset funktioniert nicht. Verwenden Sie stattdessen das unplugin-attributify-to-class Vite Plugin (attributifyToClass({ include: [/\.svelte$/]})) vor dem Svelte Scoped Vite Plugin |
| @unocss/preset-tagify | - | Presets, die benutzerdefinierte Extractors hinzufügen, funktionieren nicht. Erstellen Sie einen Preprocessor, um <text-red>Hi</text-red> zu <span class="text-red">Hi</span> zu konvertieren, dann erstellen Sie einen PR, um den Link hier hinzuzufügen. |
Für andere Presets, wenn sie nicht auf traditionelle class="..." Verwendung angewiesen sind, müssen Sie diese Klassennamen zuerst in das class="..." Attribut vorverarbeiten. Wenn sie Presets wie die .prose Klasse von Typografie hinzufügen, müssen Sie die Klassen, die die Preset-Hinzufügungen auslösen, in Ihre Safelist platzieren.
Transformer-Unterstützung
Transformer werden für Ihre CSS-Dateien (css|postcss|sass|scss|less|stylus|styl) unterstützt. Um sie zu verwenden, fügen Sie den Transformer in die cssFileTransformers Option in Ihrer vite.config.ts hinzu:
import transformerDirectives from '@unocss/transformer-directives'
export default defineConfig({
plugins: [
UnoCSS({
cssFileTransformers: [transformerDirectives()],
}),
sveltekit(),
],
})INFO
Transformer werden in Svelte-Komponenten aufgrund der Art, wie Svelte Scoped funktioniert, nicht unterstützt.
Scoped Utility-Klassen entfesseln Kreativität
Einige Ratschläge, wann Sie möglicherweise scoped Styles verwenden möchten: Wenn Sie in einem großen Projekt an den Punkt gekommen sind, an dem jedes Mal, wenn Sie eine Klasse wie .md:max-w-[50vw] verwenden, die Sie wissen, dass sie nur einmal verwendet wird, Sie zusammenzucken, wenn Sie das Gefühl haben, dass Ihre globale Stylesheet-Größe immer größer wird, dann probieren Sie dieses Paket aus. Zögern, genau die Klasse zu verwenden, die Sie benötigen, hemmt Kreativität. Sicher, Sie könnten --at-apply: md:max-w-[50vw] im Style-Block verwenden, aber das wird mühsam und Styles im Kontext sind nützlich. Darüber hinaus, wenn Sie eine große Vielfalt von Icons in Ihr Projekt einbeziehen möchten, werden Sie beginnen, das Gewicht zu spüren, sie zum globalen Stylesheet hinzuzufügen. Wenn jede Komponente das Gewicht ihrer eigenen Styles und Icons trägt, können Sie Ihr Projekt weiter ausbauen, ohne die Kosten-Nutzen-Analyse jeder neuen Ergänzung analysieren zu müssen.
Lizenz
- MIT License © 2022-PRESENT Jacob Bowdoin