<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Frontend on kenji.blog</title><link>http://kenji.blog/ar/categories/frontend/</link><description>Recent content in Frontend on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>ar</language><copyright>kenjinote</copyright><lastBuildDate>Sat, 12 Sep 2026 12:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/ar/categories/frontend/index.xml" rel="self" type="application/rss+xml"/><item><title>نقاط تصميم CSS لدعم الوضع الداكن في المدونات</title><link>http://kenji.blog/ar/p/dark-mode-css-design-patterns/</link><pubDate>Sat, 12 Sep 2026 12:00:00 +0900</pubDate><guid>http://kenji.blog/ar/p/dark-mode-css-design-patterns/</guid><description>&lt;img src="http://kenji.blog/p/dark-mode-css-design-patterns/img/eyecatch.jpg" alt="Featured image of post نقاط تصميم CSS لدعم الوضع الداكن في المدونات" />&lt;p>في تطوير الويب الحديث، تحول دعم الوضع الداكن (Dark Mode) من مجرد &amp;ldquo;ميزة إضافية جيدة&amp;rdquo; (Nice to have) إلى &amp;ldquo;متطلب أساسي&amp;rdquo; (Must have) لتحسين تجربة المستخدم (UX). خاصة في الوسائط التي تفترض قراءة النصوص لفترات طويلة مثل المدونات ومواقع الوثائق، حيث يقلل من إجهاد عين المستخدم ويحافظ على استهلاك بطارية الجهاز، لذا فإن أهمية دعم الوضع الداكن عالية جدًا.&lt;/p>
&lt;p>في هذه المقالة، سنشرح بتعمق شديد من منظور مهندس الواجهة الأمامية التحديات التقنية التي لا مفر منها لدعم الوضع الداكن في المدونات، ونقاط تصميم CSS ذات القابلية العالية للصيانة. سنغطي كل شيء بدءًا من استخدام المتغيرات المخصصة (CSS Custom Properties)، والتحكم المتقدم عبر JavaScript والتكامل مع SSR لمنع FOUC (Flash of Unstyled Content)، وتصميم الألوان لضمان إمكانية الوصول (WCAG 2.1 AAA) (بما في ذلك RGB و HSL وأحدث OKLCH)، وحتى أمثلة عملية للأكواد باستخدام Tailwind CSS.&lt;/p>
&lt;hr>
&lt;h2 id="1-أساسيات-تصميم-السمات-باستخدام-متغيرات-css-css-custom-properties">1. أساسيات تصميم السمات باستخدام متغيرات CSS (CSS Custom Properties)
&lt;/h2>&lt;p>النهج الأكثر قياسية وقوة حاليًا لتنفيذ الوضع الداكن هو استخدام &lt;strong>متغيرات CSS المخصصة (CSS Custom Properties)&lt;/strong>. على عكس متغيرات معالجات CSS مثل Sass (مثلاً &lt;code>$color&lt;/code>) التي يتم حلها بشكل ثابت أثناء الترجمة (compile)، يتم حل متغيرات CSS والكتابة فوقها ديناميكيًا في وقت التشغيل (runtime) للمتصفح. يتيح ذلك تغيير ألوان الصفحة بالكامل فورًا بمجرد تبديل الفئة (class) عبر JavaScript.&lt;/p>
&lt;h3 id="11-تعريف-سمة-الألوان-الأساسية">1.1 تعريف سمة الألوان الأساسية
&lt;/h3>&lt;p>أولاً، نستخدم الفئة الزائفة &lt;code>:root&lt;/code> لتعريف لوحة ألوان الوضع الفاتح (الافتراضي). ثم النمط التصميمي الشائع هو الكتابة فوق تلك المتغيرات عند إضافة سمة مثل &lt;code>[data-theme='dark']&lt;/code> (أو فئة &lt;code>.dark&lt;/code>).&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-css" data-lang="css">&lt;span class="line">&lt;span class="cl">&lt;span class="c">/* تعريف متغيرات الوضع الفاتح (الافتراضي) */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">:&lt;/span>&lt;span class="nd">root&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-bg-primary&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#ffffff&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-bg-secondary&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#f3f4f6&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-text-primary&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#111827&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-text-secondary&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#4b5563&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-accent&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#3b82f6&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-border&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#e5e7eb&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">/* الكتابة فوق المتغيرات في الوضع الداكن */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>&lt;span class="nt">data-theme&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;dark&amp;#39;&lt;/span>&lt;span class="o">]&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-bg-primary&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#111827&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-bg-secondary&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#1f2937&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-text-primary&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#f9fafb&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-text-secondary&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#9ca3af&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-accent&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#60a5fa&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-border&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#374151&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">/* التطبيق الفعلي */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">body&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">background-color&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nf">var&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">--&lt;/span>&lt;span class="kc">color&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">bg&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">primary&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">color&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nf">var&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">--&lt;/span>&lt;span class="kc">color&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="kc">text&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">primary&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">transition&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="k">background-color&lt;/span> &lt;span class="mf">0.3&lt;/span>&lt;span class="kt">s&lt;/span> &lt;span class="kc">ease&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kc">color&lt;/span> &lt;span class="mf">0.3&lt;/span>&lt;span class="kt">s&lt;/span> &lt;span class="kc">ease&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nt">a&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">color&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nf">var&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">--&lt;/span>&lt;span class="kc">color&lt;/span>&lt;span class="o">-&lt;/span>&lt;span class="n">accent&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>بهذه الطريقة، من خلال الفصل التام بين التخطيط والطباعة من جهة وتحديد الألوان (السمة) من جهة أخرى، تتحسن قابلية صيانة CSS بشكل كبير.&lt;/p>
&lt;h3 id="12-الاستفادة-من-media-prefers-color-scheme-dark">1.2 الاستفادة من @media (prefers-color-scheme: dark)
&lt;/h3>&lt;p>إذا تم تعيين الوضع الداكن على مستوى نظام التشغيل، فمن المستحسن من منظور تجربة المستخدم تطبيق السمة الداكنة تلقائيًا منذ الزيارة الأولى للموقع. الاستعلام الإعلامي (media query) &lt;code>@media (prefers-color-scheme: dark)&lt;/code> يحقق ذلك.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-css" data-lang="css">&lt;span class="line">&lt;span class="cl">&lt;span class="c">/* حل بديل عندما يكون إعداد بيئة نظام التشغيل هو الوضع الداكن */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">@&lt;/span>&lt;span class="k">media&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="nt">prefers-color-scheme&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="nt">dark&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">:&lt;/span>&lt;span class="nd">root&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="nd">not&lt;/span>&lt;span class="o">([&lt;/span>&lt;span class="nt">data-theme&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;light&amp;#39;&lt;/span>&lt;span class="o">])&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-bg-primary&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#111827&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-bg-secondary&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#1f2937&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-text-primary&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#f9fafb&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-text-secondary&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#9ca3af&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-accent&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#60a5fa&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--color-border&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mh">#374151&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>في هذا التدوين، طالما أن المستخدم لم يختر الوضع الفاتح صراحةً (&lt;code>data-theme='light'&lt;/code>)، فسيتم احترام إعداد الوضع الداكن لنظام التشغيل والكتابة فوق المتغيرات.&lt;/p>
&lt;hr>
&lt;h2 id="2-فهم-مساحات-الألوان-وإمكانية-الوصول-wcag-21-aaa">2. فهم مساحات الألوان وإمكانية الوصول (WCAG 2.1 AAA)
&lt;/h2>&lt;p>في تصميم ألوان الوضع الداكن، لا يكفي مجرد &amp;ldquo;جعل الخلفية سوداء والنص أبيض&amp;rdquo;. إذا كان التباين قويًا جدًا، فسيؤدي ذلك إلى توهج (halation) ويجعل القراءة أصعب، وإذا كان منخفضًا جدًا، فستتأثر الرؤية. تحدد إرشادات إمكانية الوصول لمحتوى الويب (WCAG) بدقة نسبة التباين المطلوبة لضمان الرؤية الواضحة.&lt;/p>
&lt;h3 id="21-معادلة-حساب-نسبة-التباين-في-wcag">2.1 معادلة حساب نسبة التباين في WCAG
&lt;/h3>&lt;p>تُعرف نسبة التباين (Contrast Ratio) $CR$ في WCAG باستخدام الإضاءة النسبية (Relative Luminance) للون الخلفية ولون المقدمة على النحو التالي:&lt;/p>
$$CR = \frac{L_{lighter} + 0.05}{L_{darker} + 0.05}$$&lt;p>حيث أن $L_{lighter}$ هو الإضاءة النسبية للون الأفتح، و $L_{darker}$ هو الإضاءة النسبية للون الأغمق (نطاق القيم من 0.0 إلى 1.0). لتحقيق مستوى AAA في WCAG 2.1، يلزم نسبة تباين تبلغ &lt;strong>7:1 أو أكثر&lt;/strong> للنصوص العادية، و &lt;strong>4.5:1 أو أكثر&lt;/strong> للنصوص الكبيرة.&lt;/p>
&lt;p>تُحسب الإضاءة النسبية $L$ من قيم RGB في مساحة ألوان sRGB باستخدام المعادلة المعقدة التالية:&lt;/p>
$$L = 0.2126 \times R + 0.7152 \times G + 0.0722 \times B$$&lt;p>كل مكون ($R, G, B$) يستخدم القيمة المُطبعة (normalized value) عن طريق قسمة القيمة الأصلية ذات الـ 8 بت ($R_{sRGB}$) على 255، ويقوم بالتحويل التالي لفك تصحيح جاما:&lt;/p>
$$
R, G, B =
\begin{cases}
\frac{C_{sRGB}}{12.92} &amp; \text{if } C_{sRGB} \le 0.03928 \\
\left( \frac{C_{sRGB} + 0.055}{1.055} \right)^{2.4} &amp; \text{otherwise}
\end{cases}
$$&lt;p>من الصعب إجراء هذه الحسابات يدويًا، ولكن باستخدام أدوات تصميم الألوان، يمكنك تلقائيًا تحديد الألوان التي تلبي نسبة تباين 7:1 ($CR \ge 7.0$).&lt;/p>
&lt;h3 id="22-hsl-مقابل-rgb-مقابل-oklch">2.2 HSL مقابل RGB مقابل OKLCH
&lt;/h3>&lt;p>عند إنشاء لوحات الألوان، كانت RGB و HSL هي السائدة في الماضي. ولكن هذه النماذج بها عيوب كبيرة فيما يتعلق بـ &amp;ldquo;التوحيد الإدراكي&amp;rdquo; (perceptual uniformity).&lt;/p>
&lt;ul>
&lt;li>&lt;strong>RGB&lt;/strong>: هي ألوان الضوء الأساسية الآلية، ومن الصعب على البشر إجراء تعديلات بديهية مثل &amp;ldquo;جعله أفتح&amp;rdquo; أو &amp;ldquo;جعله أغمق&amp;rdquo;.&lt;/li>
&lt;li>&lt;strong>HSL&lt;/strong>: تستخدم تدرج اللون (Hue)، والتشبع (Saturation)، والإضاءة (Lightness)، لكن &amp;ldquo;الإضاءة (L)&amp;rdquo; في HSL لا تتطابق مع السطوع الإدراكي للعين البشرية. على سبيل المثال، الأصفر النقي والأزرق النقي بإضاءة 50% في HSL لهما نفس السطوع عدديًا، ولكن الأصفر يبدو أكثر سطوعًا للعين البشرية بشكل هائل.&lt;/li>
&lt;li>&lt;strong>OKLCH&lt;/strong>: هي أحدث مساحة ألوان تم تقديمها في CSS Color Module Level 4. وتتكون من الإضاءة الإدراكية (Lightness)، والتشبع (Chroma)، وتدرج اللون (Hue)، وهي &lt;strong>تتطابق تمامًا مع الخصائص البصرية البشرية (موحدة إدراكيًا)&lt;/strong>.&lt;/li>
&lt;/ul>
&lt;p>باستخدام OKLCH، يمكنك الحفاظ على نفس الإضاءة الإدراكية (Lightness) حتى لو قمت بتغيير تدرج اللون (Hue)، مما يجعل إنشاء لوحات ألوان الوضع الداكن قابلة للتنبؤ وآمنة للغاية.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-css" data-lang="css">&lt;span class="line">&lt;span class="cl">&lt;span class="c">/* مثال على تعريف متغيرات CSS باستخدام OKLCH */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">:&lt;/span>&lt;span class="nd">root&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">/* في الوضع الفاتح، تكون الإضاءة الأساسية عالية والتشبع منخفض */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--bg-base&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nf">oklch&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">0.98&lt;/span> &lt;span class="mf">0.01&lt;/span> &lt;span class="mi">250&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--text-base&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nf">oklch&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">0.25&lt;/span> &lt;span class="mf">0.02&lt;/span> &lt;span class="mi">250&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--primary-brand&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nf">oklch&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">0.65&lt;/span> &lt;span class="mf">0.15&lt;/span> &lt;span class="mi">250&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>&lt;span class="nt">data-theme&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;dark&amp;#34;&lt;/span>&lt;span class="o">]&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">/* في الوضع الداكن، بمجرد عكس الإضاءة يسهل الحفاظ على التباين الإدراكي */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--bg-base&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nf">oklch&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">0.20&lt;/span> &lt;span class="mf">0.02&lt;/span> &lt;span class="mi">250&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--text-base&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nf">oklch&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">0.95&lt;/span> &lt;span class="mf">0.01&lt;/span> &lt;span class="mi">250&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">--primary-brand&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nf">oklch&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">0.75&lt;/span> &lt;span class="mf">0.15&lt;/span> &lt;span class="mi">250&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c">/* جعله أفتح قليلاً للوضع الداكن لضمان الرؤية */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>من خلال تبني OKLCH بهذه الطريقة، يمكنك ببساطة بناء منطق يضمن نسبة تباين متسقة (بمستوى WCAG AAA) عبر سمات متعددة.&lt;/p>
&lt;hr>
&lt;h2 id="3-منع-fouc-وميض-المحتوى-غير-المنسق-و-ssr-hydration">3. منع FOUC (وميض المحتوى غير المنسق) و SSR Hydration
&lt;/h2>&lt;p>المشكلة الأكبر التي تزعج المطورين عند دعم الوضع الداكن هي مشكلة وميض الشاشة المعروفة باسم &lt;strong>FOUC (Flash of Unstyled Content)&lt;/strong>.&lt;/p>
&lt;h3 id="31-فخ-تبديل-السمات-عبر-client-side-js">3.1 فخ تبديل السمات عبر Client-Side JS
&lt;/h3>&lt;p>في SPA مثل React أو Vue (أو المواقع الثابتة عبر SSG)، من الشائع حفظ إعدادات المستخدم في &lt;code>localStorage&lt;/code> وقراءتها بواسطة JavaScript لتبديل السمة. ومع ذلك، إذا تم هذا الإجراء في &lt;code>useEffect&lt;/code> في React، فستحدث المشكلات التالية:&lt;/p>
&lt;ol>
&lt;li>يقوم المتصفح بعرض HTML/CSS في الوضع الفاتح.&lt;/li>
&lt;li>يتم تحميل حزمة JS وتنفيذها.&lt;/li>
&lt;li>يقرأ إعداد &lt;code>dark&lt;/code> من &lt;code>localStorage&lt;/code>.&lt;/li>
&lt;li>تتم إضافة فئة &lt;code>dark&lt;/code> إلى HTML، وتصبح الشاشة داكنة فجأة (وميض).&lt;/li>
&lt;/ol>
&lt;h3 id="32-الحل-المثالي-لمنع-fouc-استخدام-ملفات-تعريف-الارتباط-cookies-و-ssr">3.2 الحل المثالي لمنع FOUC: استخدام ملفات تعريف الارتباط (Cookies) و SSR
&lt;/h3>&lt;p>أفضل ممارسة لمنع FOUC تمامًا ومنع أخطاء الـ hydration هي &lt;strong>حفظ إعدادات سمة المستخدم في &lt;code>document.cookie&lt;/code>، وإرجاع HTML مع الفئة المناسبة المُضافة بالفعل أثناء مرحلة العرض من جانب الخادم (SSR)&lt;/strong>.&lt;/p>
&lt;p>يوضح مخطط التسلسل التالي التدفق المثالي لتهيئة السمة باستخدام ملفات تعريف الارتباط.&lt;/p>
&lt;pre class="mermaid">
sequenceDiagram
participant User as &amp;#34;المستخدم&amp;#34;
participant Browser as &amp;#34;متصفح نظام التشغيل&amp;#34;
participant Server as &amp;#34;خادم SSR&amp;#34;
participant DOM as &amp;#34;عميل DOM&amp;#34;
User-&amp;gt;&amp;gt;Browser: &amp;#34;طلب الصفحة&amp;#34;
Browser-&amp;gt;&amp;gt;Server: &amp;#34;طلب GET مع ملف تعريف الارتباط (theme=dark)&amp;#34;
Server--&amp;gt;&amp;gt;Browser: &amp;#34;إرجاع HTML مع &amp;lt;html data-theme=&amp;#39;dark&amp;#39;&amp;gt;&amp;#34;
Browser-&amp;gt;&amp;gt;DOM: &amp;#34;عرض HTML الأولي (بدون FOUC)&amp;#34;
DOM-&amp;gt;&amp;gt;DOM: &amp;#34;تنفيذ نص الـ Hydration&amp;#34;
alt &amp;#34;لا يوجد ملف تعريف ارتباط (الزيارة الأولى)&amp;#34;
DOM-&amp;gt;&amp;gt;Browser: &amp;#34;التحقق من prefers-color-scheme لنظام التشغيل&amp;#34;
Browser--&amp;gt;&amp;gt;DOM: &amp;#34;نتيجة matchMedia (مثلاً dark)&amp;#34;
DOM-&amp;gt;&amp;gt;DOM: &amp;#34;تعيين data-theme=&amp;#39;dark&amp;#39; عبر نص برمجي حاجز مضمن&amp;#34;
end
&lt;/pre>
&lt;h3 id="33-خط-الدفاع-عبر-النصوص-البرمجية-المضمنة-للمواقع-الثابتة-التي-لا-تستخدم-cookies">3.3 خط الدفاع عبر النصوص البرمجية المضمنة (للمواقع الثابتة التي لا تستخدم Cookies)
&lt;/h3>&lt;p>في حالة المدونات التي تستخدم SSG (توليد المواقع الثابتة) فقط حيث يكون SSR غير ممكن (مثل Hugo أو Gatsby أو التصدير الثابت لـ Astro)، من الضروري وضع نص JavaScript مضمن يُنفذ بشكل يحظر العرض (blocking) داخل وسم &lt;code>&amp;lt;head&amp;gt;&lt;/code> لإضافة الفئة قبل رسم DOM مباشرةً.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-html" data-lang="html">&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!-- يوضع في نهاية &amp;lt;head&amp;gt; --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">script&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="kd">function&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">try&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">var&lt;/span> &lt;span class="nx">localTheme&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">localStorage&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">getItem&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;theme&amp;#39;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">var&lt;/span> &lt;span class="nx">osTheme&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">window&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">matchMedia&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;(prefers-color-scheme: dark)&amp;#39;&lt;/span>&lt;span class="p">).&lt;/span>&lt;span class="nx">matches&lt;/span> &lt;span class="o">?&lt;/span> &lt;span class="s1">&amp;#39;dark&amp;#39;&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;light&amp;#39;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">var&lt;/span> &lt;span class="nx">theme&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nx">localTheme&lt;/span> &lt;span class="o">||&lt;/span> &lt;span class="nx">osTheme&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">document&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">documentElement&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">setAttribute&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;data-theme&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nx">theme&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span> &lt;span class="k">catch&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nx">e&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">})();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">script&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>هذا النص الصغير يحظر عرض المتصفح ويُنفذ على الفور، لذلك بحلول وقت رسم الشاشة، تكون سمة &lt;code>data-theme&lt;/code> قد تم تعيينها بالفعل، مما يمنع وميض الشاشة (FOUC) بشكل كامل.&lt;/p>
&lt;hr>
&lt;h2 id="4-أساليب-التنفيذ-باستخدام-tailwind-css-و-raw-scsscss">4. أساليب التنفيذ باستخدام Tailwind CSS و Raw SCSS/CSS
&lt;/h2>&lt;p>عند دمج الوضع الداكن في مشاريع فعلية، يجب فهم أسلوب كل أداة.&lt;/p>
&lt;h3 id="41-الوضع-الداكن-في-tailwind-css">4.1 الوضع الداكن في Tailwind CSS
&lt;/h3>&lt;p>يوفر Tailwind CSS بشكل افتراضي متغير &lt;code>dark:&lt;/code>، مما يجعل تنفيذ الوضع الداكن أمرًا سهلاً للغاية. يمكنك تعيين خاصية &lt;code>darkMode&lt;/code> في ملف الإعدادات (&lt;code>tailwind.config.js&lt;/code>).&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-javascript" data-lang="javascript">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// tailwind.config.js
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="nx">module&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="nx">exports&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// &amp;#39;media&amp;#39; (يعتمد على إعداد نظام التشغيل) أو &amp;#39;class&amp;#39; (يمكن تبديله يدويًا)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="nx">darkMode&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;class&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">theme&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">extend&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">colors&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="cm">/* توسيع لوحة ألوان Tailwind باستخدام متغيرات CSS */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">primary&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;rgb(var(--color-primary) / &amp;lt;alpha-value&amp;gt;)&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nx">background&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="s1">&amp;#39;rgb(var(--color-background) / &amp;lt;alpha-value&amp;gt;)&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>في جانب HTML، ما عليك سوى إضافة الفئات كما يلي.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-html" data-lang="html">&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">div&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;bg-white dark:bg-gray-900 text-gray-900 dark:text-gray-100&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">h1&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;text-2xl font-bold&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>مرحبا بالعالم&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">h1&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">p&lt;/span> &lt;span class="na">class&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;mt-2&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>يجعل Tailwind الوضع الداكن سهلاً بشكل لا يصدق.&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">p&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">div&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>ومع ذلك، كتابة &lt;code>dark:bg-xxx&lt;/code> على كل عنصر يمكن أن يتسبب في تضخم المكونات. بالنسبة للمدونات والتطبيقات واسعة النطاق، يُوصى بتصميم هجين (تصميم الألوان الدلالية) &lt;strong>يعتمد على متغيرات CSS، ويشير Tailwind إلى تلك المتغيرات&lt;/strong>.&lt;/p>
&lt;p>فيما يلي مخطط فئة يوضح وراثة متغيرات CSS وطبقة التطبيق.&lt;/p>
&lt;pre class="mermaid">
classDiagram
class GlobalCSSVariables {
&amp;#34;--color-brand-500&amp;#34;
&amp;#34;--color-gray-900&amp;#34;
}
class SemanticVariables {
&amp;#34;--bg-primary&amp;#34;
&amp;#34;--text-base&amp;#34;
&amp;#34;--accent&amp;#34;
}
class TailwindConfig {
&amp;#34;theme.colors.background&amp;#34;
&amp;#34;theme.colors.primary&amp;#34;
}
class UIComponents {
&amp;#34;class=&amp;#39;bg-background text-primary&amp;#39;&amp;#34;
}
GlobalCSSVariables &amp;lt;|-- SemanticVariables : &amp;#34;:root &amp;amp; .dark&amp;#34;
SemanticVariables &amp;lt;|-- TailwindConfig : &amp;#34;tailwind.config.js&amp;#34;
TailwindConfig &amp;lt;.. UIComponents : &amp;#34;تطبيق فئات المنفعة&amp;#34;
&lt;/pre>
&lt;h3 id="42-التنفيذ-باستخدام-raw-scsscss-الاستفادة-من-mixin">4.2 التنفيذ باستخدام Raw SCSS/CSS (الاستفادة من Mixin)
&lt;/h3>&lt;p>في المشاريع التي لا تستخدم Tailwind وتكتب SCSS بشكل مخصص، نستخدم &lt;code>@mixin&lt;/code> لتغليف أنماط الوضع الداكن.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-scss" data-lang="scss">&lt;span class="line">&lt;span class="cl">&lt;span class="cm">/* تعريف SCSS Mixin */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">@mixin&lt;/span>&lt;span class="nf"> dark-mode&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="cm">/* يدعم كلاً من سمة [data-theme=&amp;#39;dark&amp;#39;] أو إعدادات نظام التشغيل */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">[&lt;/span>&lt;span class="nt">data-theme&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;dark&amp;#39;&lt;/span>&lt;span class="o">]&lt;/span> &lt;span class="k">&amp;amp;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">@content&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">@media&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">prefers-color-scheme&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="ni">dark&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nd">:root:not&lt;/span>&lt;span class="o">([&lt;/span>&lt;span class="nt">data-theme&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;light&amp;#39;&lt;/span>&lt;span class="o">])&lt;/span> &lt;span class="k">&amp;amp;&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">@content&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cm">/* مثال الاستخدام */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nc">.card&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">background-color&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="mh">#ffffff&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">color&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="mh">#333333&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">border&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="kt">px&lt;/span> &lt;span class="ni">solid&lt;/span> &lt;span class="mh">#eeeeee&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">@include&lt;/span>&lt;span class="nd"> dark-mode&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">background-color&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="mh">#1a202c&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">color&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="mh">#e2e8f0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="na">border-color&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="mh">#2d3748&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>هذه الطريقة بديهية، ولكن نظرًا لأن حجم ملف CSS النهائي يميل إلى التضخم (يتم تكرار media query لكل محدد)، فإن الاتجاه الحالي هو الانتقال إلى تصميم يتمحور حول متغيرات CSS (Custom Properties).&lt;/p>
&lt;hr>
&lt;h2 id="5-تحسين-الوضع-الداكن-للصور-image-و-svg">5. تحسين الوضع الداكن للصور (Image) و SVG
&lt;/h2>&lt;p>حتى لو اكتمل تصميم ألوان النصوص والخلفية، إذا ظلت الصور والأيقونات (SVG) الموضوعة كمحتوى في وضعها الفاتح، فستبدو ساطعة للغاية وبارزة بشكل مزعج في الوضع الداكن. يعد تحسين هذه العناصر أيضًا أمرًا بالغ الأهمية.&lt;/p>
&lt;h3 id="51-فلتر-css-لتقليل-إضاءة-الصور">5.1 فلتر CSS لتقليل إضاءة الصور
&lt;/h3>&lt;p>الصور النقطية مثل الصور الفوتوغرافية يمكن أن تكون ساطعة جدًا إذا تم عرضها كما هي في الوضع الداكن. باستخدام خاصية &lt;code>filter&lt;/code> في CSS، يمكنك تقليل الإضاءة (brightness) والتباين (contrast) قليلاً، مما يسمح لها بالاندماج بشكل طبيعي في واجهة المستخدم للسمة الداكنة.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-css" data-lang="css">&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>&lt;span class="nt">data-theme&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;dark&amp;#39;&lt;/span>&lt;span class="o">]&lt;/span> &lt;span class="nt">img&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="nd">not&lt;/span>&lt;span class="o">([&lt;/span>&lt;span class="nt">src&lt;/span>&lt;span class="o">*=&lt;/span>&lt;span class="s2">&amp;#34;.svg&amp;#34;&lt;/span>&lt;span class="o">])&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">/* تقليل الإضاءة وزيادة التباين قليلاً */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">filter&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">brightness&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">0.8&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="nb">contrast&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">1.1&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">transition&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="k">filter&lt;/span> &lt;span class="mf">0.3&lt;/span>&lt;span class="kt">s&lt;/span> &lt;span class="kc">ease&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="o">[&lt;/span>&lt;span class="nt">data-theme&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s1">&amp;#39;dark&amp;#39;&lt;/span>&lt;span class="o">]&lt;/span> &lt;span class="nt">img&lt;/span>&lt;span class="p">:&lt;/span>&lt;span class="nd">hover&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">/* استعادة السطوع الأصلي عند التمرير (إذا كان المستخدم يريد رؤية التفاصيل) */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">filter&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">brightness&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="nb">contrast&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="52-عرض-الصور-باستخدام-وسم-picture">5.2 عرض الصور باستخدام وسم &lt;code>&amp;lt;picture&amp;gt;&lt;/code>
&lt;/h3>&lt;p>لا يمكن التعامل مع صور الشعارات أو الرسوم التوضيحية (مثل صور JPEG ذات الخلفية البيضاء الثابتة) باستخدام الفلاتر فقط. في هذه الحالة، الحل الصحيح هو استخدام عنصر &lt;code>&amp;lt;picture&amp;gt;&lt;/code> في HTML مع استعلامات الوسائط (media queries) لتبديل وعرض ملف صورة مختلف للوضع الداكن.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-html" data-lang="html">&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">picture&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">&amp;lt;!-- عرض هذا للمستخدمين ذوي إعداد نظام التشغيل للوضع الداكن --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">source&lt;/span> &lt;span class="na">srcset&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;/img/logo-dark.png&amp;#34;&lt;/span> &lt;span class="na">media&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;(prefers-color-scheme: dark)&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c">&amp;lt;!-- الافتراضي (الوضع الفاتح) --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">img&lt;/span> &lt;span class="na">src&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;/img/logo-light.png&amp;#34;&lt;/span> &lt;span class="na">alt&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;شعار الموقع&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">picture&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>※ ومع ذلك، لا ترتبط هذه الطريقة بالتبديل اليدوي من خلال أشياء مثل &lt;code>localStorage&lt;/code> (إنها تعتمد فقط على إعداد نظام التشغيل). إذا قمت بتنفيذ التبديل اليدوي، فستحتاج إما إلى إعادة كتابة الـ &lt;code>src&lt;/code> للصور ديناميكيًا باستخدام JS، أو تبديل &lt;code>display: none&lt;/code> باستخدام فئات CSS.&lt;/p>
&lt;h3 id="53-دعم-currentcolor-في-أيقونات-svg">5.3 دعم &lt;code>currentColor&lt;/code> في أيقونات SVG
&lt;/h3>&lt;p>بالنسبة لرسومات SVG المضمنة المستخدمة كأيقونات وغيرها، فإن أذكى طريقة هي ربط لون التعبئة بلون النص الخاص بالعنصر الأصل. حدد &lt;code>currentColor&lt;/code> في سمة &lt;code>fill&lt;/code> أو &lt;code>stroke&lt;/code> الخاصة بـ SVG.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-html" data-lang="html">&lt;span class="line">&lt;span class="cl">&lt;span class="c">&amp;lt;!-- يتم تطبيق قيمة خاصية color في CSS (مثل var(--text-primary)) تلقائيًا --&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">svg&lt;/span> &lt;span class="na">viewBox&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;0 0 24 24&amp;#34;&lt;/span> &lt;span class="na">fill&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;currentColor&amp;#34;&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">&amp;lt;&lt;/span>&lt;span class="nt">path&lt;/span> &lt;span class="na">d&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s">&amp;#34;M12 2L2 22h20L12 2z&amp;#34;&lt;/span> &lt;span class="p">/&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">&amp;lt;/&lt;/span>&lt;span class="nt">svg&lt;/span>&lt;span class="p">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>من خلال هذا، عند التبديل إلى الوضع الداكن ويصبح لون نص العنصر الأصل أبيض، ستتغير أيقونة SVG تلقائيًا أيضًا إلى اللون الأبيض.&lt;/p>
&lt;hr>
&lt;h2 id="6-الخلاصة-نحو-تصميم-مستدام-للوضع-الداكن">6. الخلاصة: نحو تصميم مستدام للوضع الداكن
&lt;/h2>&lt;p>لتنفيذ وضع داكن عالي الجودة في المدونات وتطبيقات الويب، لا غنى عن تصميم CSS يغطي النقاط التالية:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>استخدام CSS Custom Properties&lt;/strong>: تجنب الترميز الثابت (hardcoding) للألوان، وقم بتجريدها إلى أسماء متغيرات دلالية (مثل: &lt;code>--bg-primary&lt;/code>).&lt;/li>
&lt;li>&lt;strong>اعتماد مساحة الألوان OKLCH&lt;/strong>: صمم منطقيًا نسبة تباين عالية الوصول (7:1 أو أكثر) تلبي معايير WCAG 2.1 AAA ضمن مساحة ألوان موحدة إدراكيًا.&lt;/li>
&lt;li>&lt;strong>تنفيذ تدابير FOUC بصرامة&lt;/strong>: تخلص تمامًا من وميض الشاشة عند التحميل الأولي من خلال التنسيق بين SSR وملفات تعريف الارتباط (Cookies)، أو باستخدام نصوص برمجية حاجبة مضمنة داخل &lt;code>&amp;lt;head&amp;gt;&lt;/code>.&lt;/li>
&lt;li>&lt;strong>تحسين الوسائط والأصول&lt;/strong>: استخدم &lt;code>filter: brightness()&lt;/code> و &lt;code>currentColor&lt;/code> وعلامات &lt;code>&amp;lt;picture&amp;gt;&lt;/code> لمزامنة العناصر بخلاف النصوص مع السمة الداكنة.&lt;/li>
&lt;/ol>
&lt;p>هذا الاهتمام الدقيق بالتفاصيل الذي يتجاوز مجرد &amp;ldquo;عكس الألوان&amp;rdquo; هو ما يصنع الفارق في تجربة المستخدم، وهو شرط أساسي لمدونة حديثة توفر تجربة قراءة ممتازة ومريحة للعين وتحظى بتقدير طويل الأمد. نأمل أن يستخدم المطورون الذين يخططون لإضافة الوضع الداكن أنماط التصميم المذكورة في هذه المقالة كمرجع.&lt;/p></description></item></channel></rss>