Skip to content

Svelte Scoped

ضع CSS المُنشأ لأنماط الأداة لكل مكون Svelte مباشرة في كتلة <style> لمكون Svelte بدلاً من ملف CSS عام.

هذا المكون:

svelte
<div class="mb-1" />

يتم تحويله إلى:

svelte
<div class="uno-ei382o" />

<style>
  :global(.uno-ei382o) {
    margin-bottom: 0.25rem;
  }
</style>

متى تستخدم

حالة الاستخدامالوصفالحزمة للاستخدام
تطبيقات أصغروجود ملف CSS عام واحد أكثر ملاءمة. استخدم مكون Vite العادي لـ Svelte/SvelteKit.unocss/vite
تطبيقات أكبريمكن أن يساعدك Svelte Scoped في تجنب ملف CSS عام ينمو باستمرار.@unocss/svelte-scoped/vite
مكتبة المكوناتيتم وضع الأنماط المُنشأة مباشرة في المكونات المبنية دون الحاجة إلى استخدام UnoCSS في خط أنابيب بناء التطبيق المستهلك.@unocss/svelte-scoped/preprocess

كيف يعمل

يضع إعداد UnoCSS/Tailwind CSS العادي أنماط الأداة في ملف CSS عام مع ترتيب مناسب. على النقيض من ذلك، يوزع Svelte Scoped أنماطك عبر العديد من ملفات CSS لمكونات Svelte المرتبة بشكل تعسفي. ومع ذلك، يجب أن يحافظ على أنماط الأداة عامة للسماح لها بأن تكون واعية بالسياق حسب الحاجة لأشياء مثل من اليمين إلى اليسار وحالات الاستخدام الأخرى المدرجة أدناه. هذا يمثل تحدياً يتم حله باستخدام غلاف :global() الخاص بـ Svelte للانسحاب من طريقة تجزئة CSS الافتراضية لـ Svelte واستخدام تجزئة تعتمد على اسم الملف + اسم (أسماء) الفئة بدلاً من ذلك لتجميع أسماء فئات فريدة يمكن جعلها عامة دون تعارضات الأنماط.

الاستخدام

نظراً لأن Svelte Scoped يعيد كتابة أسماء فئات الأداة الخاصة بك، فأنت محدود في المكان الذي يمكنك كتابتها فيه:

الصيغة المدعومةمثال
سمة Class<div class="mb-1" />
توجيه Class<div class:mb-1={condition} />
اختصار توجيه Class<div class:logo />
خاصية Class<Button class="mb-1" />

تم تصميم Svelte Scoped ليكون بديلاً مباشراً لمشروع يستخدم أنماط الأداة. على هذا النحو، التعبيرات الموجودة داخل سمات الفئة مدعومة أيضاً (على سبيل المثال <div class="mb-1 {foo ? 'mr-1' : 'mr-2'}" />) لكن نوصي باستخدام صيغة توجيه الفئة للمضي قدماً. لاحظ أيضاً أنه إذا كنت قد استخدمت أسماء الفئات بطرق أخرى مثل وضعها في كتلة <script> أو استخدام وضع attributify فستحتاج إلى اتخاذ خطوات إضافية قبل استخدام Svelte Scoped. يمكنك استخدام خيار safelist وأيضاً التحقق من قسم الإعدادات المسبقة أدناه للحصول على المزيد من النصائح.

واعي بالسياق

على الرغم من أن الأنماط موزعة عبر مكونات Svelte في تطبيقك، إلا أنها لا تزال فئات عامة وستعمل فيما يتعلق بالعناصر الموجودة خارج مكوناتها المحددة. فيما يلي بعض الأمثلة:

يعتمد على الوالد

الفئات التي تعتمد على السمات الموجودة في مكون الوالد:

svelte
<div class="dark:mb-2 rtl:right-0"></div>

تتحول إلى:

svelte
<div class="uno-3hashz"></div>

<style>
  :global(.dark .uno-3hashz) {
    margin-bottom: 0.5rem;
  }
  :global([dir="rtl"] .uno-3hashz) {
    right: 0rem;
  }
</style>

تأثير الأطفال

يمكنك إضافة مسافة بين 3 عناصر أطفال بعضها في مكونات منفصلة:

svelte
<div class="space-x-1">
  <div>Status: online</div>
  <Button>FAQ</Button>
  <Button>Login</Button>
</div>

تتحول إلى:

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>

تمرير الفئات إلى مكونات الأطفال

يمكنك إضافة خاصية class إلى مكون للسماح بتمرير فئات مخصصة أينما يتم استهلاك هذا المكون.

svelte
<Button class="px-2 py-1">Login</Button>

تتحول إلى:

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>

طريقة سهلة لتنفيذ الفئة في مكون مستقبل ستكون وضعها على عنصر باستخدام {$$props.class} كما في div class="{$$props.class} foo bar" />.

توجيهات Apply

يمكنك استخدام توجيهات apply داخل كتل <style> الخاصة بك مع --at-apply أو @apply أو قيمة مخصصة تم تعيينها باستخدام خيار applyVariables.

يتعامل Svelte Scoped بشكل صحيح حتى مع الفئات المعتمدة على السياق مثل dark:text-white التي لا يمكن لحزمة @unocss/transformer-directives العادية التعامل معها بشكل صحيح لأنها لم يتم بناؤها خصيصاً لكتل نمط Svelte. على سبيل المثال، مع Svelte Scoped هذا المكون:

svelte
<div />

<style>
  div {
    --at-apply: rtl:ml-2;
  }
</style>

سيتم تحويله إلى:

svelte
<div />

<style>
  :global([dir=\\"rtl\\"]) div {
    margin-right: 0.5rem;
  }
</style>

لكي يعمل rtl:ml-2 بشكل صحيح، يتم لف محدد [dir="rtl"] بـ :global() لمنع مترجم Svelte من إزالته تلقائياً لأن المكون لا يحتوي على عنصر بهذه السمة. ومع ذلك، لا يمكن تضمين div في غلاف :global() لأن هذا النمط سيؤثر بعد ذلك على كل div في تطبيقك.

توجيهات كتلة النمط الأخرى

استخدام theme() مدعوم أيضاً، لكن @screen غير مدعوم.

مكون Vite الإضافي

في تطبيقات Svelte أو SvelteKit، احقن الأنماط المُنشأة مباشرة في مكونات Svelte الخاصة بك، مع وضع الحد الأدنى من الأنماط الضرورية في ورقة الأنماط العامة. تحقق من مثال SvelteKit في Stackblitz:

Open in StackBlitz

التثبيت

bash
pnpm add -D unocss @unocss/svelte-scoped
bash
yarn add -D unocss @unocss/svelte-scoped
bash
npm install -D unocss @unocss/svelte-scoped
bash
bun add -D unocss @unocss/svelte-scoped

إضافة المكون الإضافي

أضف @unocss/svelte-scoped/vite إلى تكوين Vite الخاص بك:

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', // راجع تعريف النوع لجميع خيارات الإعادة المضمّنة أو كيفية تمرير الخاصة بك
      // ...خيارات Svelte Scoped الأخرى
    }),
    sveltekit(),
  ],
})

إضافة ملف التكوين

قم بإعداد ملف uno.config.ts الخاص بك كما هو موضح أدناه.

الأنماط العامة

بينما يتم وضع جميع الأنماط تقريباً في مكونات فردية، لا يزال هناك عدد قليل يجب وضعه في ورقة الأنماط العامة: preflights و safelist وإعادة اختيارية (إذا كنت تستخدم خيار injectReset).

أضف العنصر النائب %unocss-svelte-scoped.global% إلى علامة <head> الخاصة بك. في Svelte هذا هو index.html. في SvelteKit سيكون هذا في app.html قبل %sveltekit.head%:

html
<head>
  <!-- ... -->
  <title>SvelteKit using UnoCSS Svelte Scoped</title>
  %unocss-svelte-scoped.global%
  %sveltekit.head%
</head>

إذا كنت تستخدم SvelteKit، يجب عليك أيضاً إضافة ما يلي إلى خطاف transformPageChunk في ملف src/hooks.server.js الخاص بك:

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
}

يجب أن يكون هذا التحويل في ملف يحتوي مساره على hooks و server (على سبيل المثال src/hooks.server.js، src/hooks.server.ts) لأن svelte-scoped سيبحث في ملف خطافات الخادم الخاص بك لاستبدال unocss_svelte_scoped_global_styles بالأنماط العامة الخاصة بك. تأكد من عدم استيراد هذا التحويل من ملف آخر، مثل عند استخدام sequence من @sveltejs/kit/hooks.

في مشروع Svelte العادي، سيقوم خطاف transformIndexHtml الخاص بـ Vite بذلك تلقائياً.

معالج Svelte المسبق

استخدم أنماط الأداة لبناء مكتبة مكونات لا تعتمد على تضمين ملف CSS مصاحب باستخدام معالج مسبق لوضع الأنماط المُنشأة مباشرة في المكونات المبنية. تحقق من مثال SvelteKit Library في Stackblitz:

Open in StackBlitz

التثبيت

bash
pnpm add -D unocss @unocss/svelte-scoped
bash
yarn add -D unocss @unocss/svelte-scoped
bash
npm install -D unocss @unocss/svelte-scoped
bash
bun add -D unocss @unocss/svelte-scoped

إضافة المعالج المسبق

أضف @unocss/svelte-scoped/preprocess إلى تكوين Svelte الخاص بك:

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({
      // ... خيارات المعالج المسبق
    }),
  ],
  // تكوين Svelte الآخر
}

لا تجمع أسماء الفئات في التطوير

عند استخدام Svelte Scoped في تطبيق عادي، سيكتشف مكون Vite الإضافي تلقائياً dev مقابل build. في التطوير، سيتم الحفاظ على الفئات متميزة ومجزأة في مكانها لسهولة التبديل تشغيل/إيقاف في أدوات مطور المتصفح. class="mb-1 mr-1" سيتحول إلى شيء مثل class="_mb-1_9hwi32 _mr-1_84jfy4. في الإنتاج، سيتم تجميعها في اسم فئة واحد باستخدام البادئة المطلوبة، uno- افتراضياً، وتجزئة تعتمد على اسم الملف + أسماء الفئات، على سبيل المثال class="uno-84dke3.

إذا كنت تريد نفس السلوك عند استخدام المعالج المسبق، يجب عليك تعيين خيار combine يدوياً بناءً على البيئة. إحدى الطرق للقيام بذلك هي تثبيت cross-env وتحديث سكريبت dev الخاص بك إلى هذا:

"dev": "cross-env NODE_ENV=development vite dev"

ثم اضبط svelte.config.js الخاص بك:

diff
+const prod = process.env.NODE_ENV !== 'development'
const config = {
  preprocess: [
    vitePreprocess(),
    UnoCSS({
+      combine: prod,
    }),
  ],
}

إضافة ملف التكوين

قم بإعداد ملف uno.config.ts الخاص بك كما هو موضح أدناه.

Preflights

عند استخدام المعالج المسبق لديك خيار تضمين preflights في المكون (المكونات) المحددة حيث تكون مطلوبة عن طريق إضافة uno-preflights كسمة نمط.

html
<style uno-preflights></style>

أي preflights خاصة تبدأ بفترة، مثل .prose :where(a):not(:where(.not-prose, .not-prose *))، سيتم لفها بـ :global() لتجنب إزالتها تلقائياً بواسطة مترجم Svelte.

إضافة preflights في مكونات فردية غير ضرورية إذا كانت فئاتك لا تعتمد على preflights أو كانت المكونات المبنية الخاصة بك مستهلكة فقط في التطبيقات التي تتضمن بالفعل preflights.

Safelist

عند استخدام المعالج المسبق لديك خيار تضمين فئات safelist في مكون عن طريق إضافة uno-safelist كسمة نمط.

html
<style uno-safelist></style>

سيتم لف أنماط safelist الخاصة بك بـ :global() لتجنب إزالتها تلقائياً بواسطة مترجم Svelte.

التكوين

ضع إعدادات UnoCSS الخاصة بك في ملف uno.config.ts:

ts
import { defineConfig } from 'unocss'

export default defineConfig({
  // ...خيارات UnoCSS
})

المستخرجون غير مدعومين بسبب الاختلافات في الاستخدام العام العادي لـ UnoCSS واستخدام Svelte Scoped. الإعدادات المسبقة والمحولون مدعومون كما هو موضح في الأقسام التالية. راجع ملف التكوين و مرجع التكوين لجميع التفاصيل الأخرى.

دعم الإعدادات المسبقة

نظراً لطبيعة وجود بعض الأنماط الضرورية في ورقة الأنماط العامة وكل شيء آخر موجود في كل مكون حيث يكون مطلوباً، تحتاج الإعدادات المسبقة إلى معالجتها على أساس كل حالة:

الإعداد المسبقمدعومملاحظات
@unocss/preset-uno، @unocss/preset-mini، @unocss/preset-wind3، @unocss/preset-icons، @unocss/web-fontsهذه وجميع المكونات الإضافية المجتمعية، على سبيل المثال unocss-preset-forms، التي تعتمد فقط على rules/variants/preflights ستعمل.
@unocss/preset-typographyنظراً لكيفية إضافة هذا الإعداد المسبق لمجموعات القواعد إلى preflights الخاصة بك يجب عليك إضافة فئة prose إلى safelist عند استخدام هذا الإعداد المسبق، وإلا فلن يتم تشغيل preflights أبداً. جميع الفئات الأخرى من هذا الإعداد المسبق، على سبيل المثال prose-pink، يمكن أن تكون محددة نطاق المكون.
@unocss/preset-rem-to-pxهذا وجميع الإعدادات المسبقة المشابهة التي تعدل فقط إخراج النمط ستعمل.
@unocss/preset-attributify-لن يعمل الإعداد المسبق. بدلاً من ذلك استخدم مكون unplugin-attributify-to-class Vite الإضافي (attributifyToClass({ include: [/\.svelte$/]})) قبل مكون Svelte Scoped Vite الإضافي
@unocss/preset-tagify-الإعدادات المسبقة التي تضيف مستخرجين مخصصين لن تعمل. قم بإنشاء معالج مسبق لتحويل <text-red>Hi</text-red> إلى <span class="text-red">Hi</span>، ثم قم بإنشاء PR لإضافة الرابط هنا.

للإعدادات المسبقة الأخرى، إذا لم تعتمد على استخدام class="..." التقليدي فستحتاج أولاً إلى معالجة مسبقة لأسماء الفئات تلك في سمة class="...". إذا كانت تضيف إعدادات مسبقة مثل فئة .prose الخاصة بالطباعة فستحتاج إلى وضع الفئات التي تسبب إضافات الإعداد المسبق في safelist الخاصة بك.

دعم المحولون

المحولون مدعومون لملفات CSS الخاصة بك (css|postcss|sass|scss|less|stylus|styl). لاستخدامها، أضف المحول إلى خيار cssFileTransformers في vite.config.ts الخاص بك:

ts
import transformerDirectives from '@unocss/transformer-directives'

export default defineConfig({
  plugins: [
    UnoCSS({
      cssFileTransformers: [transformerDirectives()],
    }),
    sveltekit(),
  ],
})

INFO

المحولون غير مدعومين في مكونات Svelte بسبب كيفية عمل Svelte Scoped.

فئات الأداة المحددة النطاق تطلق الإبداع

بعض النصائح حول متى قد ترغب في استخدام الأنماط المحددة النطاق: إذا وصلت إلى النقطة في حياة مشروع كبير عندما تستخدم في كل مرة فئة مثل .md:max-w-[50vw] التي تعرف أنها مستخدمة مرة واحدة فقط تشعر بالانزعاج لأنك تشعر بحجم ورقة الأنماط العامة الخاصة بك تصبح أكبر وأكبر، ثم جرب هذه الحزمة. التردد في استخدام الفئة التي تحتاجها بالضبط يمنع الإبداع. بالتأكيد، يمكنك استخدام --at-apply: md:max-w-[50vw] في كتلة النمط لكن ذلك يصبح مملاً والأنماط في السياق مفيدة. علاوة على ذلك، إذا كنت ترغب في تضمين مجموعة كبيرة ومتنوعة من الأيقونات في مشروعك، ستبدأ في الشعور بوزن إضافتها إلى ورقة الأنماط العامة. عندما يتحمل كل مكون وزن أنماطه وأيقوناته الخاصة يمكنك الاستمرار في توسيع مشروعك دون الحاجة إلى تحليل تكلفة فائدة كل إضافة جديدة.

الترخيص

Released under the MIT License.