Svelte Scoped
Placera genererad CSS för varje Svelte-komponents verktygsstilar direkt i Svelte-komponentens <style>-block istället för i en global CSS-fil.
Denna komponent:
svelte
<div class="mb-1" />transformeras till:
svelte
<div class="uno-ei382o" />
<style>
:global(.uno-ei382o) {
margin-bottom: 0.25rem;
}
</style>När man ska använda
| Användningsfall | Beskrivning | Paket att använda | |
|---|---|---|---|
| Mindre appar | ❌ | Att ha 1 global CSS-fil är mer bekvämt. Använd den vanliga Vite-plugin för Svelte/SvelteKit. | unocss/vite |
| Större appar | ✅ | Svelte Scoped kan hjälpa dig att undvika en ständigt växande global CSS-fil. | @unocss/svelte-scoped/vite |
| Komponentbibliotek | ✅ | Genererade stilar placeras direkt i byggda komponenter utan behov av att använda UnoCSS i en konsumrandes apps bygg-pipeline. | @unocss/svelte-scoped/preprocess |
Hur det fungerar
En vanlig UnoCSS/Tailwind CSS-setup placerar verktygsstilar i en global CSS-fil med korrekt ordning. Däremot distribuerar Svelte Scoped dina stilar över många godtyckligt ordnade Svelte-komponent-CSS-filer. Men det måste hålla verktygsstilarna globala för att tillåta dem att vara kontextmedvetna enligt behov för saker som höger-till-vänster och andra användningsfall som listas nedan. Detta presenterar en utmaning som löses genom att använda Sveltes :global()-wrapper för att välja bort den standard Svelte CSS-hash-metoden och istället använda en hash baserad på filnamn + klassnamn för att kompilera unika klassnamn som kan göras globala utan stilkonflikter.
Användning
Eftersom Svelte Scoped skriver om dina verktygsklassnamn är du begränsad i var du kan skriva dem:
| Stödd syntax | Exempel |
|---|---|
| Klass-attribut | <div class="mb-1" /> |
| Klass-direktiv | <div class:mb-1={condition} /> |
| Klass-direktiv kortform | <div class:logo /> |
| Klass-prop | <Button class="mb-1" /> |
Svelte Scoped är designad för att vara en drop-in-ersättning för ett projekt som använder verktygsstilar. Som sådant stöds också uttryck som finns inom klass-attribut (t.ex. <div class="mb-1 {foo ? 'mr-1' : 'mr-2'}" />) men vi rekommenderar att du använder klass-direktiv syntax framöver. Observera också att om du har använt klassnamn på andra sätt som att placera dem i ett <script>-block eller använda attributify-läge måste du vidta ytterligare steg innan du använder Svelte Scoped. Du kan använda safelist-alternativet och också kolla presets-sektionen nedan för fler tips.
Kontextmedveten
Även om stilar distribueras över dina apps Svelte-komponenter, är de fortfarande globala klasser och kommer att fungera i relation till element som finns utanför deras specifika komponenter. Här är några exempel:
Förälderberoende
Klasser som beror på attribut som finns i en förälderkomponent:
svelte
<div class="dark:mb-2 rtl:right-0"></div>blir till:
svelte
<div class="uno-3hashz"></div>
<style>
:global(.dark .uno-3hashz) {
margin-bottom: 0.5rem;
}
:global([dir="rtl"] .uno-3hashz) {
right: 0rem;
}
</style>Barn som påverkar
Du kan lägga till utrymme mellan 3 barnelement varav vissa är i separata komponenter:
svelte
<div class="space-x-1">
<div>Status: online</div>
<Button>FAQ</Button>
<Button>Login</Button>
</div>blir till:
svelte
<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>Skicka klasser till barnkomponenter
Du kan lägga till en class-prop till en komponent för att tillåta att skicka anpassade klasser varhelst den komponenten konsumeras.
svelte
<Button class="px-2 py-1">Login</Button>blir till:
svelte
<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>Ett enkelt sätt att implementera klassen i en mottagande komponent skulle vara att placera dem på ett element med {$$props.class} som i div class="{$$props.class} foo bar" />.
Apply-direktiv
Du kan använda apply-direktiv inuti dina <style>-block med antingen --at-apply eller @apply eller ett anpassat värde inställt med applyVariables-alternativet.
Svelte Scoped hanterar även korrekt kontextberoende klasser som dark:text-white som det vanliga @unocss/transformer-directives-paketet inte kan hantera korrekt eftersom det inte byggdes specifikt för Svelte-stilblock. Till exempel, med Svelte Scoped kommer denna komponent:
svelte
<div />
<style>
div {
--at-apply: rtl:ml-2;
}
</style>transformeras till:
svelte
<div />
<style>
:global([dir=\\"rtl\\"]) div {
margin-right: 0.5rem;
}
</style>För att rtl:ml-2 ska fungera korrekt, wrapas [dir="rtl"]-selektorn med :global() för att förhindra att Svelte-kompilatorn automatiskt tar bort den eftersom komponenten inte har något element med det attributet. Men div kan inte inkluderas i :global()-wrapparen eftersom den stilen då skulle påverka varje div i din app.
Andra stilblock-direktiv
Att använda theme() stöds också, men @screen stöds INTE.
Vite Plugin
I Svelte eller SvelteKit-appar, injicera genererade stilar direkt i dina Svelte-komponenter, medan du placerar minimala nödvändiga stilar i ett globalt stylesheet. Kolla SvelteKit-exemplet i Stackblitz:
Installera
bash
pnpm add -D unocss @unocss/svelte-scopedbash
yarn add -D unocss @unocss/svelte-scopedbash
npm install -D unocss @unocss/svelte-scopedbash
bun add -D unocss @unocss/svelte-scopedLägg till plugin
Lägg till @unocss/svelte-scoped/vite i din Vite-konfiguration:
ts
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', // se typdefinition för alla inkluderade återställningsalternativ eller hur man skickar in sitt eget
// ...andra Svelte Scoped-alternativ
}),
sveltekit(),
],
})Lägg till konfigurationsfil
Ställ in din uno.config.ts-fil som beskrivs nedan.
Globala stilar
Medan nästan alla stilar placeras i individuella komponenter, finns det fortfarande några som måste placeras i ett globalt stylesheet: preflights, safelist, och en valfri återställning (om du använder injectReset-alternativet).
Lägg till %unocss-svelte-scoped.global%-platshållaren i din <head>-tagg. I Svelte är detta index.html. I SvelteKit kommer detta att vara i app.html före %sveltekit.head%:
html
<head>
<!-- ... -->
<title>SvelteKit med UnoCSS Svelte Scoped</title>
%unocss-svelte-scoped.global%
%sveltekit.head%
</head>Om du använder SvelteKit måste du också lägga till följande i transformPageChunk-hook:en i din src/hooks.server.js-fil:
js
/** @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
}Denna transformation måste vara i en fil vars sökväg inkluderar hooks och server (t.ex. src/hooks.server.js, src/hooks.server.ts) eftersom svelte-scoped kommer att leta i din server hooks-fil för att ersätta unocss_svelte_scoped_global_styles med dina globala stilar. Se till att inte importera denna transformation från en annan fil, som när du använder sequence från @sveltejs/kit/hooks.
I ett vanligt Svelte-projekt kommer Vites transformIndexHtml-hook att göra detta automatiskt.
Svelte Preprocessor
Använd verktygsstilar för att bygga ett komponentbibliotek som inte är beroende av att inkludera en medföljande CSS-fil genom att använda en preprocessor för att placera genererade stilar direkt i byggda komponenter. Kolla SvelteKit Library-exemplet i Stackblitz:
Installera
bash
pnpm add -D unocss @unocss/svelte-scopedbash
yarn add -D unocss @unocss/svelte-scopedbash
npm install -D unocss @unocss/svelte-scopedbash
bun add -D unocss @unocss/svelte-scopedLägg till preprocessor
Lägg till @unocss/svelte-scoped/preprocess i din Svelte-konfiguration:
ts
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-alternativ
}),
],
// annan Svelte-konfiguration
}Kombinera inte klassnamn i utveckling
När du använder Svelte Scoped i en vanlig app, kommer Vite-plugin automatiskt att upptäcka dev vs build. I utveckling kommer klasser att hållas distinkta och hashade på plats för enkelhet att växla på/av i din webbläsares utvecklarverktyg. class="mb-1 mr-1" kommer att bli något som class="_mb-1_9hwi32 _mr-1_84jfy4. I produktion kommer dessa att kompileras till ett enda klassnamn med ditt önskade prefix, uno- som standard, och en hash baserad på filnamn + klassnamn, t.ex. class="uno-84dke3.
Om du vill ha samma beteende när du använder preprocessor måste du manuellt ställa in combine-alternativet baserat på miljö. Ett sätt att göra detta är att installera cross-env och uppdatera ditt dev-script till detta:
"dev": "cross-env NODE_ENV=development vite dev"Justera sedan din svelte.config.js:
diff
+const prod = process.env.NODE_ENV !== 'development'
const config = {
preprocess: [
vitePreprocess(),
UnoCSS({
+ combine: prod,
}),
],
}Lägg till konfigurationsfil
Ställ in din uno.config.ts-fil som beskrivs nedan.
Preflights
När du använder preprocessor har du möjlighet att inkludera preflights i de specifika komponent(er) där de behövs genom att lägga till uno-preflights som ett stilattribut.
html
<style uno-preflights></style>Alla speciella preflights som börjar med en punkt, som .prose :where(a):not(:where(.not-prose, .not-prose *)), kommer att wrapas med :global() för att undvika att automatiskt tas bort av Svelte-kompilatorn.
Att lägga till preflights i individuella komponenter är onödigt om dina klasser inte beror på preflights eller dina byggda komponenter endast konsumeras i appar som redan inkluderar preflights.
Safelist
När du använder preprocessor har du möjlighet att inkludera safelist-klasser i en komponent genom att lägga till uno-safelist som ett stilattribut.
html
<style uno-safelist></style>Dina safelist-stilar kommer att wrapas med :global() för att undvika att automatiskt tas bort av Svelte-kompilatorn.
Konfiguration
Placera dina UnoCSS-inställningar i en uno.config.ts-fil:
ts
import { defineConfig } from 'unocss'
export default defineConfig({
// ...UnoCSS-alternativ
})Extractors stöds inte på grund av skillnaderna i normal UnoCSS global användning och Svelte Scoped användning. Presets och Transformers stöds som beskrivs i följande avsnitt. Se Konfigurationsfil och Konfigurationsreferens för alla andra detaljer.
Presets-stöd
På grund av naturen av att ha några nödvändiga stilar i ett globalt stylesheet och allt annat innehåll i varje komponent där det behövs, måste presets hanteras från fall till fall:
| Preset | Stöds | Anteckningar |
|---|---|---|
| ✅ | Dessa och alla community-plugins, t.ex. unocss-preset-forms, som endast förlitar sig på rules/variants/preflights kommer att fungera. | |
| @unocss/preset-typography | ✅ | På grund av hur denna preset lägger till rulesets till dina preflights måste du lägga till prose-klassen till din safelist när du använder denna preset, annars kommer preflights aldrig att utlösas. Alla andra klasser från denna preset, t.ex. prose-pink, kan vara komponent-scopade. |
| @unocss/preset-rem-to-px | ✅ | Detta och alla presets som det som endast modifierar stilutdata kommer att fungera. |
| @unocss/preset-attributify | - | Preset kommer inte att fungera. Använd istället unplugin-attributify-to-class Vite-plugin (attributifyToClass({ include: [/\.svelte$/]})) före Svelte Scoped Vite-plugin |
| @unocss/preset-tagify | - | Presets som lägger till anpassade extractors kommer inte att fungera. Skapa en preprocessor för att konvertera <text-red>Hi</text-red> till <span class="text-red">Hi</span>, skapa sedan en PR för att lägga till länken här. |
För andra presets, om de inte förlitar sig på traditionell class="..."-användning måste du först förbehandla dessa klassnamn till class="..."-attributet. Om de lägger till presets som typography's .prose-klass måste du placera de klasser som utlöser preset-tilläggen i din safelist.
Transformers-stöd
Transformers stöds för dina CSS-filer (css|postcss|sass|scss|less|stylus|styl). För att använda dem, lägg till transformern i cssFileTransformers-alternativet i din vite.config.ts:
ts
import transformerDirectives from '@unocss/transformer-directives'
export default defineConfig({
plugins: [
UnoCSS({
cssFileTransformers: [transformerDirectives()],
}),
sveltekit(),
],
})INFO
Transformers stöds inte i Svelte-komponenter på grund av hur Svelte Scoped fungerar.
Scopade verktygsklasser frigör kreativitet
Några råd om när du kan vilja använda scopade stilar: Om du har kommit till den punkt i ett stort projects liv när varje gång du använder en klass som .md:max-w-[50vw] som du vet endast används en gång så ryser du när du känner storleken på ditt globala stylesheet bli större och större, då ge detta paket ett försök. Tvekan att använda exakt den klass du behöver hämmar kreativitet. Självklart kan du använda --at-apply: md:max-w-[50vw] i stilblocket men det blir tröttsamt och stilar i kontext är användbara. Dessutom, om du skulle vilja inkludera en stor variation av ikoner i ditt projekt, kommer du att börja känna vikten av att lägga till dem i det globala stylesheetet. När varje komponent bär vikten av sina egna stilar och ikoner kan du fortsätta att utöka ditt projekt utan att behöva analysera kostnadsnyttan av varje nytt tillskott.
Licens
- MIT License © 2022-PRESENT Jacob Bowdoin