Svelte Scoped
Posiziona il CSS generato per gli stili utility di ogni componente Svelte direttamente nel blocco <style> del componente Svelte invece che in un file CSS globale.
Questo componente:
<div class="mb-1" />viene trasformato in:
<div class="uno-ei382o" />
<style>
:global(.uno-ei382o) {
margin-bottom: 0.25rem;
}
</style>Quando usare
| Caso d'uso | Descrizione | Pacchetto da usare | |
|---|---|---|---|
| App più piccole | ❌ | Avere 1 file CSS globale è più conveniente. Usa il plugin Vite regolare per Svelte/SvelteKit. | unocss/vite |
| App più grandi | ✅ | Svelte Scoped può aiutarti a evitare un file CSS globale in continua crescita. | @unocss/svelte-scoped/vite |
| Libreria di componenti | ✅ | Gli stili generati vengono posizionati direttamente nei componenti costruiti senza la necessità di usare UnoCSS nella pipeline di build di un'app che li consuma. | @unocss/svelte-scoped/preprocess |
Come funziona
Un setup UnoCSS/Tailwind CSS regolare posiziona gli stili utility in un file CSS globale con ordinamento corretto. Al contrario, Svelte Scoped distribuisce i tuoi stili su molti file CSS di componenti Svelte ordinati arbitrariamente. Tuttavia, deve mantenere gli stili utility globali per permettere loro di essere consapevoli del contesto come necessario per cose come right-to-left e altri casi d'uso elencati sotto. Questo presenta una sfida che viene risolta usando il wrapper :global() di Svelte per rinunciare al metodo di hashing CSS predefinito di Svelte e invece usare un hash basato su nome file + nome/i classe per compilare nomi di classe unici che possono essere resi globali senza conflitti di stile.
Utilizzo
Poiché Svelte Scoped riscrive i nomi delle tue classi utility, sei limitato su dove puoi scriverli:
| Sintassi supportata | Esempio |
|---|---|
| Attributo class | <div class="mb-1" /> |
| Direttiva class | <div class:mb-1={condition} /> |
| Direttiva class abbreviata | <div class:logo /> |
| Prop class | <Button class="mb-1" /> |
Svelte Scoped è progettato per essere un sostituto drop-in per un progetto che usa stili utility. Come tale, le espressioni trovate all'interno degli attributi class sono anche supportate (ad esempio <div class="mb-1 {foo ? 'mr-1' : 'mr-2'}" />) ma ti consigliamo di usare la sintassi della direttiva class in futuro. Nota anche che se hai usato nomi di classe in altri modi come posizionarli in un blocco <script> o usare la modalità attributify allora dovrai prendere passi aggiuntivi prima di usare Svelte Scoped. Puoi utilizzare l'opzione safelist e anche controllare la sezione preset sotto per più suggerimenti.
Consapevole del contesto
Anche se gli stili sono distribuiti tra i componenti Svelte della tua app, sono ancora classi globali e funzioneranno in relazione agli elementi trovati al di fuori dei loro componenti specifici. Ecco alcuni esempi:
Dipendente dal genitore
Classi che dipendono da attributi trovati in un componente genitore:
<div class="dark:mb-2 rtl:right-0"></div>diventano:
<div class="uno-3hashz"></div>
<style>
:global(.dark .uno-3hashz) {
margin-bottom: 0.5rem;
}
:global([dir="rtl"] .uno-3hashz) {
right: 0rem;
}
</style>Influenzare i figli
Puoi aggiungere spazio tra 3 elementi figli di cui alcuni sono in componenti separati:
<div class="space-x-1">
<div>Status: online</div>
<Button>FAQ</Button>
<Button>Login</Button>
</div>diventa:
<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>Passare classi ai componenti figli
Puoi aggiungere una prop class a un componente per permettere di passare classi personalizzate ovunque quel componente venga consumato.
<Button class="px-2 py-1">Login</Button>diventa:
<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>Un modo facile per implementare la classe in un componente ricevente sarebbe posizionarle su un elemento usando {$$props.class} come in div class="{$$props.class} foo bar" />.
Direttive apply
Puoi usare direttive apply all'interno dei tuoi blocchi <style> con --at-apply o @apply o un valore personalizzato impostato usando l'opzione applyVariables.
Svelte Scoped gestisce anche correttamente classi dipendenti dal contesto come dark:text-white che il pacchetto regolare @unocss/transformer-directives non può gestire correttamente perché non è stato costruito specificamente per i blocchi di stile Svelte. Ad esempio, con Svelte Scoped questo componente:
<div />
<style>
div {
--at-apply: rtl:ml-2;
}
</style>verrà trasformato in:
<div />
<style>
:global([dir=\\"rtl\\"]) div {
margin-right: 0.5rem;
}
</style>Affinché rtl:ml-2 funzioni correttamente, il selettore [dir="rtl"] è avvolto con :global() per impedire al compilatore Svelte di rimuoverlo automaticamente poiché il componente non ha elementi con quell'attributo. Tuttavia, div non può essere incluso nel wrapper :global() perché quello stile influenzerebbe poi ogni div nella tua app.
Altre direttive del blocco style
L'uso di theme() è anche supportato, ma @screen non lo è.
Plugin Vite
Nelle app Svelte o SvelteKit, inietta gli stili generati direttamente nei tuoi componenti Svelte, mentre posiziona gli stili minimi necessari in un foglio di stile globale. Controlla l'esempio SvelteKit in Stackblitz:
Installazione
pnpm add -D unocss @unocss/svelte-scopedyarn add -D unocss @unocss/svelte-scopednpm install -D unocss @unocss/svelte-scopedbun add -D unocss @unocss/svelte-scopedAggiungi plugin
Aggiungi @unocss/svelte-scoped/vite alla tua configurazione Vite:
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', // vedi definizione tipo per tutte le opzioni reset incluse o come passare le tue
// ...altre opzioni Svelte Scoped
}),
sveltekit(),
],
})Aggiungi file di configurazione
Configura il tuo file uno.config.ts come descritto sotto.
Stili globali
Mentre quasi tutti gli stili sono posizionati in componenti individuali, ce ne sono ancora alcuni che devono essere posizionati in un foglio di stile globale: preflights, safelist e un reset opzionale (se usi l'opzione injectReset).
Aggiungi il placeholder %unocss-svelte-scoped.global% nel tuo tag <head>. In Svelte questo è index.html. In SvelteKit questo sarà in app.html prima di %sveltekit.head%:
<head>
<!-- ... -->
<title>SvelteKit using UnoCSS Svelte Scoped</title>
%unocss-svelte-scoped.global%
%sveltekit.head%
</head>Se usi SvelteKit, devi anche aggiungere quanto segue all'hook transformPageChunk nel tuo file src/hooks.server.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
}Questa trasformazione deve essere in un file il cui percorso include hooks e server (ad esempio src/hooks.server.js, src/hooks.server.ts) poiché svelte-scoped cercherà nel tuo file server hooks per sostituire unocss_svelte_scoped_global_styles con i tuoi stili globali. Assicurati di non importare questa trasformazione da un altro file, come quando usi sequence da @sveltejs/kit/hooks.
In un progetto Svelte regolare, l'hook transformIndexHtml di Vite farà questo automaticamente.
Preprocessor Svelte
Usa stili utility per costruire una libreria di componenti che non dipende dall'includere un file CSS compagno usando un preprocessor per posizionare gli stili generati direttamente nei componenti costruiti. Controlla l'esempio SvelteKit Library in Stackblitz:
Installazione
pnpm add -D unocss @unocss/svelte-scopedyarn add -D unocss @unocss/svelte-scopednpm install -D unocss @unocss/svelte-scopedbun add -D unocss @unocss/svelte-scopedAggiungi preprocessor
Aggiungi @unocss/svelte-scoped/preprocess alla tua configurazione Svelte:
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({
// ... opzioni preprocessor
}),
],
// altre configurazioni Svelte
}Non combinare nomi di classe in sviluppo
Quando usi Svelte Scoped in un'app normale, il plugin Vite rileverà automaticamente dev vs build. In sviluppo, le classi saranno mantenute distinte e hashate sul posto per facilitare l'attivazione/disattivazione negli strumenti per sviluppatori del browser. class="mb-1 mr-1" diventerà qualcosa come class="_mb-1_9hwi32 _mr-1_84jfy4. In produzione, queste verranno compilate in un singolo nome di classe usando il tuo prefisso desiderato, uno- per impostazione predefinita, e un hash basato sul nome file + nomi classe, ad esempio class="uno-84dke3.
Se vuoi questo stesso comportamento quando usi il preprocessor, devi impostare manualmente l'opzione combine in base all'ambiente. Un modo per farlo è installare cross-env e aggiornare il tuo script dev a questo:
"dev": "cross-env NODE_ENV=development vite dev"Poi regola il tuo svelte.config.js:
+const prod = process.env.NODE_ENV !== 'development'
const config = {
preprocess: [
vitePreprocess(),
UnoCSS({
+ combine: prod,
}),
],
}Aggiungi file di configurazione
Configura il tuo file uno.config.ts come descritto sotto.
Preflights
Quando usi il preprocessor hai l'opzione di includere preflights nel/i componente/i specifico/i dove sono necessari aggiungendo uno-preflights come attributo style.
<style uno-preflights></style>Qualsiasi preflight speciale che inizia con un punto, come .prose :where(a):not(:where(.not-prose, .not-prose *)), sarà avvolto con :global() per evitare di essere automaticamente rimosso dal compilatore Svelte.
Aggiungere preflights in componenti individuali è inutile se le tue classi non dipendono da preflights o i tuoi componenti costruiti vengono consumati solo in app che includono già preflights.
Safelist
Quando usi il preprocessor hai l'opzione di includere classi safelist in un componente aggiungendo uno-safelist come attributo style.
<style uno-safelist></style>I tuoi stili safelist saranno avvolti con :global() per evitare di essere automaticamente rimossi dal compilatore Svelte.
Configurazione
Posiziona le tue impostazioni UnoCSS in un file uno.config.ts:
import { defineConfig } from 'unocss'
export default defineConfig({
// ...opzioni UnoCSS
})Gli estrattori non sono supportati a causa delle differenze nell'uso globale normale di UnoCSS e nell'uso Svelte Scoped. I preset e i trasformatori sono supportati come descritto nelle sezioni seguenti. Vedi File di Configurazione e Riferimento Config per tutti gli altri dettagli.
Supporto preset
A causa della natura di avere alcuni stili necessari in un foglio di stile globale e tutto il resto contenuto in ogni componente dove necessario, i preset devono essere gestiti caso per caso:
| Preset | Supportato | Note |
|---|---|---|
| ✅ | Questi e tutti i plugin della comunità, ad esempio unocss-preset-forms, che si basano solo su regole/varianti/preflights funzioneranno. | |
| @unocss/preset-typography | ✅ | A causa di come questo preset aggiunge ruleset ai tuoi preflights devi aggiungere la classe prose alla tua safelist quando usi questo preset, altrimenti i preflights non verranno mai attivati. Tutte le altre classi da questo preset, ad esempio prose-pink, possono essere component scoped. |
| @unocss/preset-rem-to-px | ✅ | Questo e tutti i preset come questo che modificano solo l'output dello stile funzioneranno. |
| @unocss/preset-attributify | - | Il preset non funzionerà. Invece usa il plugin Vite unplugin-attributify-to-class (attributifyToClass({ include: [/\.svelte$/]})) prima del plugin Vite Svelte Scoped |
| @unocss/preset-tagify | - | I preset che aggiungono estrattori personalizzati non funzioneranno. Crea un preprocessor per convertire <text-red>Hi</text-red> in <span class="text-red">Hi</span>, poi crea un PR per aggiungere il link qui. |
Per altri preset, se non si basano sull'uso tradizionale di class="..." dovrai prima preprocessare quei nomi di classe nell'attributo class="...". Se aggiungono preset come la classe .prose di typography allora dovrai posizionare le classi che attivano le aggiunte del preset nella tua safelist.
Supporto trasformatori
I trasformatori sono supportati per i tuoi file CSS (css|postcss|sass|scss|less|stylus|styl). Per usarli, aggiungi il trasformatore nell'opzione cssFileTransformers nella tua vite.config.ts:
import transformerDirectives from '@unocss/transformer-directives'
export default defineConfig({
plugins: [
UnoCSS({
cssFileTransformers: [transformerDirectives()],
}),
sveltekit(),
],
})INFO
I trasformatori non sono supportati nei componenti Svelte a causa di come funziona Svelte Scoped.
Le classi utility scoped liberano la creatività
Alcuni consigli su quando potresti voler usare stili scoped: Se sei arrivato al punto nella vita di un grande progetto quando ogni volta che usi una classe come .md:max-w-[50vw] che sai essere usata solo una volta rabbrividisci mentre senti la dimensione del tuo foglio di stile globale diventare sempre più grande, allora prova questo pacchetto. L'esitazione nell'usare esattamente la classe di cui hai bisogno inibisce la creatività. Certo, potresti usare --at-apply: md:max-w-[50vw] nel blocco style ma diventa noioso e gli stili nel contesto sono utili. Inoltre, se vorresti includere una grande varietà di icone nel tuo progetto, inizierai a sentire il peso di aggiungerle al foglio di stile globale. Quando ogni componente porta il peso dei propri stili e icone puoi continuare ad espandere il tuo progetto senza dover analizzare il rapporto costo-beneficio di ogni nuova aggiunta.
Licenza
- MIT License © 2022-PRESENT Jacob Bowdoin