تصميم المواقع

تعلم CSS من الصفر

CSS يقرر كيف يبدو ما بناه HTML: اللون والتباعد والحجم وموضع كل عنصر. ولكل قاعدة فيه ثلاثة أجزاء: محدد يقول أي عنصر، وخاصية تقول ماذا، وقيمة.

  • الدرس 3 من 12
  • مبتدئ
  • مجاني، دون تسجيل

كيف يصل نمط إلى عنصر

العنصر
  1. 1

    خاصية style على الوسم نفسه

    أقرب طبقة إلى العنصر وأصعب ما يمكن تغييره لاحقا.

  2. 2

    قاعدتك بصنف أو معرف

    كلما كان المحدد أدق زاد وزنه. والمعرف أثقلها، ولهذا قلّل استعماله.

  3. 3

    قاعدتك باسم الوسم

    أخف قواعدك، ومع ذلك تسبق افتراض المتصفح.

  4. 4

    افتراض المتصفح

    عناوين كبيرة وروابط زرقاء وقوائم بنقاط. هنا عُرِّف كل شيء قبل مجيئك.

  5. 5

    قيمة موروثة من الأب

    أضعف طبقة. لون على body لا يصل إلى الروابط، لأن للمتصفح قاعدة مباشرة عليها.

important يبعثر ترتيب الطبقات، ولهذا هو الملاذ الأخير. والوراثة أبعد طبقة: أي قاعدة مباشرة، حتى قاعدة المتصفح، تسبقها.

آخر مراجعة: تُراجع الحقائق وأسماء الأدوات في هذا الدرس مقابل مصادرها في هذا التاريخ.

ماذا يتحكم فيه CSS وكيف يصل إلى الصفحة؟

يفعل مهمة واحدة: يقرر كيف يبدو ما بناه HTML. وCSS اختصار لصفحات الأنماط المتتالية، وأصغر وحدة فيه قاعدة:

p {
  color: #333;
  line-height: 1.9;
}

هناك ثلاث طرق لربطه، ونستعمل واحدة عمليا. يمكنك كتابة خاصية style على الوسم نفسه، أو وضع القواعد داخل وسم style في head، أو حفظ كل شيء في ملف منفصل تناديه بسطر واحد:

<link rel="stylesheet" href="style.css">

اختر الثالثة واترك الأخريين للاستثناءات. والسبب ليس ذوقا: الملف المنفصل يُنزَّل مرة واحدة ويأخذه المتصفح من ذاكرته في الصفحة التالية، ويوم يتغير لون الأزرار تغيّر موضعا واحدا لا خمسين.

وشيء واحد يربك كل مبتدئ. قبل أن تكتب سطرا واحدا من CSS، للصفحة أنماط بالفعل: العنوان كبير وعريض، والروابط زرقاء تحتها خط، والقوائم لها نقاط. المتصفح يضعها بصفحة أنماطه الداخلية، وما تكتبه أنت إعادة كتابة لها.

المحددات: أن تخبر المتصفح أي عنصر

اكتب اسم وسم فتحصل على كل تلك الوسوم. واكتب نقطة واسم صنف فتحصل على العناصر الحاملة لذلك الصنف وحدها، واكتب مربعا ومعرفا فتحصل على عنصر واحد فريد.

a         { color: #0b5; }         /* كل رابط */
.btn      { border-radius: 12px; } /* أي شيء بـclass="btn" */
#header   { position: sticky; }    /* العنصر ذو id="header" */
.card p   { margin-block: 0; }     /* كل p داخل .card */
a:hover   { text-decoration: underline; }

عمليا اكتب الأصناف دائما تقريبا. فالمعرف فريد في الصفحة ومفيد للروابط ولجافاسكريبت، لكنه في التنسيق يجلب وزنا، ويجبرك لاحقا على جلب وزن أكبر لتتجاوزه. وهذا هو الطريق الذي ينتهي عند important.

وهناك محدد يُدرَّس أقل وهو حيوي لمستخدم لوحة المفاتيح. فـhover لا يعني شيئا إلا للفأرة؛ ومن يتنقل في الصفحة بـTab عليه أن يرى أي عنصر يقف عليه الآن:

.btn:focus-visible {
  outline: 2px solid #0b5;
  outline-offset: 2px;
}

إن أزلت حلقة المتصفح الافتراضية بـoutline: none ولم تضع شيئا مكانها، فقد أعميت الصفحة على مستخدم لوحة المفاتيح. وهذا من المواضع القليلة التي يضر فيها سطر CSS واحد بإتاحة الوصول مباشرة.

لماذا لا يُطبَّق النمط الذي كتبته؟

الجواب القصير: قاعدتك طُبِّقت، لكن قاعدة أخرى سبقتها. فالمتصفح يسأل لكل خاصية في كل عنصر ثلاثة أسئلة بالترتيب. أي القواعد تستهدف هذا العنصر أصلا، وأيها أكثر تحديدا، وإن تساوى التحديد فأيها جاء لاحقا في الملف.

الشكل في أعلى الصفحة هو هذه الطبقات، من الأقرب إلى العنصر نحو الخارج. فـstyle على الوسم نفسه هو الأقرب، ولهذا هو أصعب ما يمكن تغييره لاحقا، وافتراض المتصفح هو الأبعد. وأكثر موضع يقع فيه سوء الفهم هو الطبقة الخارجية: الوراثة.

تضع لونا على body وتتوقع أن تأخذه الروابط أيضا. لا تأخذه. فللمتصفح قاعدة مباشرة على وسم a، وأي قاعدة مباشرة، حتى قاعدة المتصفح نفسه، تسبق قيمة موروثة من الأب. الوراثة أضعف الطبقات لا أقواها.

أما الحل فيستغرق عشر ثوان. بدل التخمين، انقر بالزر الأيمن على العنصر واختر الفحص وافتح لسان Computed. هناك تُكتب القيمة النهائية لكل خاصية، وبتوسيع أحدها ترى القاعدة الفائزة باسم ملفها ورقم سطرها، والقواعد الخاسرة مشطوبة. ولا بديل عن هذا بالتخمين.

ثم important، الكلمة التي تكسر هذا الترتيب. اكتبها مرة وسيضطر كل قاعدة لاحقة أن تكتبها بدورها لتفوز، ومن ثَم يمضي ملفك بالوزن لا بالمنطق. وقاعدتنا بسيطة: إن لم يعمل دون important فالمحدد خاطئ. والاستثناء الحقيقي الوحيد هو تنسيق شفرة لم تكتبها ولا تصل إليها.

كل عنصر صندوق

كل شيء على الصفحة مستطيل، حتى الحرف الواحد. ولهذا المستطيل أربع طبقات: المحتوى نفسه، وpadding وهو المسافة الداخلية حتى الإطار، وborder وهو الخط حوله، وmargin وهو المسافة الخارجية حتى بقية العناصر. وكل عمل التباعد في CSS هو هذه الأربعة.

وهناك قرار افتراضي يغيّره الجميع تقريبا ويشرحه القليلون. فافتراضيا يكون الرقم الذي تكتبه في width حجم المحتوى وحده، لذا فالعنصر بعرض مئة بالمئة ومعه padding يخرج عن موضعه. وسطر واحد يحل هذا نهائيا:

*, *::before, *::after { box-sizing: border-box; }

مع border-box يشمل رقم العرض الحشو والحد أيضا، وهو ما توقعته من البداية. ضع هذا السطر في أول كل ملف CSS ثم لا تفكر فيه.

وسلوك آخر يفاجئ الجميع مرة واحدة. المسافة الرأسية بين عنصرين متتاليين لا تُجمع؛ بل يفوز الأكبر منهما. ويسمى هذا دمج الهوامش، ويحدث للهوامش الرأسية فقط، لا للحشو ولا داخل flex وgrid. وهو أحد أسباب لجوء التخطيطات الحديثة إلى gap بدل الهامش.

التخطيط: متى flexbox ومتى grid؟

لـflexbox محور واحد ولـgrid محوران، وهذا الفرق يحسم معظم القرارات. بـflex ترصّ بضعة أشياء في صف أو عمود وتدع كلا منها يأخذ حجمه من محتواه. وبـgrid ترسم البنية أولا، فتعرّف الأعمدة والصفوف بنفسك، ثم يجلس المحتوى داخلها.

.toolbar {
  display: flex;
  align-items: center;
  gap: 12px;
}

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 16px;
}

والقاعدة الثانية تستحق أن تحفظها. تقول إن كل عمود لا يقل عن ٢٢٠ بكسل وإن الأعمدة تتقاسم ما تبقى من مساحة، ويحسب المتصفح بنفسه كم عمودا يتسع عند كل عرض. شبكة متجاوبة دون أي media query.

وليسا متنافسين، واختيار أحدهما لا يعني التخلي عن الآخر. عمليا يُرسم هيكل الصفحة بـgrid ويجلس صف flex داخل كل خانة. والقاعدة التقريبية: إن استطعت أن تقول «هذه الأشياء القليلة بجوار بعضها» فـflex، وإن قلت «هذا الجدول من الخانات» فـgrid.

flexbox وgrid: أداتان لنوعين من المسائل

إحداهما ترصّ المحتوى على محور واحد، والأخرى تعرّف بنية على محورين.

flexbox، محور واحد

  • صف واحد أو عمود واحد، وحجم كل عنصر من محتواه
  • لشريط أدوات أو قائمة أو صف أزرار أو أيقونة بجوار نص
  • حين لا تعرف كم عنصرا سيأتي وتريدها بجوار بعضها فقط
  • مع wrap ينتقل إلى السطر التالي، لكن الأعمدة لا تبقى محاذية

grid، محوران

  • أنت تعرّف الأعمدة والصفوف ويجلس المحتوى داخلها
  • لهيكل الصفحة وشبكة البطاقات وكل موضع تهم فيه المحاذاة الرأسية
  • مع repeat وminmax يختار عدد الأعمدة عند أي عرض دون media query
  • مبالغة لصف بسيط، حيث flex أقصر وأسهل قراءة

في صفحة حقيقية تعملان معا: الهيكل بـgrid وصف flex داخل كل خانة. واختيار إحداهما ليس تخليا عن الأخرى.

لماذا يحتاج موقع عربي إلى margin-inline-start لا margin-left

لأن margin-left ليس الموضع نفسه في العربية كما في الإنجليزية. فالخصائص الفيزيائية تفكر بيسار الشاشة ويمينها، والخصائص المنطقية تفكر ببداية السطر ونهايته. وmargin-inline-start يعني المسافة من حيث يبدأ السطر؛ يقرؤها المتصفح يمينا في العربية والفارسية ويسارا في الإنجليزية، وأنت لا تفعل شيئا.

والترجمة ليست صعبة:

فيزيائيمنطقيماذا يفعل في اليمين إلى اليسار
margin-leftmargin-inline-startمسافة من بداية السطر، وهي اليمين في العربية
padding-rightpadding-inline-endمسافة داخلية من نهاية السطر، وهي اليسار في العربية
left: 0inset-inline-start: 0الالتصاق بالحافة التي يبدأ منها السطر
border-leftborder-inline-startالخط بجوار العنصر، دائما في جهة البداية
text-align: lefttext-align: startمحاذاة النص لبداية السطر، صحيحة في اللغتين
width وheightinline-size وblock-sizeالحجم بامتداد السطر وعموديا عليه

واختباره يستغرق عشر ثوان ولا يعلّمه أحد: في أدوات المطور، على وسم html، غيّر قيمة dir من rtl إلى ltr وانظر إلى الصفحة نفسها. وكل ما لم ينتقل أو التصق بالحافة الخاطئة فهو خاصية فيزيائية بقيت. وعلى موقعنا نفسه هذا الفحص جزء من مراجعة كل قالب جديد.

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

البطاقة نفسها، بخصائص فيزيائية وبخصائص منطقية

ورقة مراجعة تخطيط بأربع لغاتCSS

بخصائص منطقية

  • ملف CSS واحد للغات الأربع دون نسخة منفصلة من اليمين إلى اليسار
  • إضافة لغة جديدة لا تحتاج عمل CSS
  • الأيقونة بجوار النص تبقى دائما في الجهة الصحيحة
  • اختباره تغيير خاصية dir واحدة في أدوات المطور

بخصائص فيزيائية

  • اللغة الثانية تحتاج ملفا ثانيا أو قواعد معكوسة
  • كلما أضاف أحدهم margin-left جديدا انكسر الأمر هناك من جديد
  • الأخطاء صامتة: لا شيء ينكسر، لكنه يقع في المكان الخطأ
  • وعلى موقع بلغة واحدة لا يحدث أي من هذا

لا يظهر هذا الفرق إلا حين يكون للموقع أكثر من اتجاه. وعلى موقع بلغة واحدة من اليسار إلى اليمين لا تكسر الخصائص الفيزيائية شيئا.

متغيرات CSS: عرّفها مرة واستعملها في كل مكان

متغير CSS اسم يحمل قيمة. واسمه التقني خاصية مخصصة، يبدأ بشرطتين ويُقرأ بـvar:

:root {
  --brand: #0b5;
  --gap: 16px;
}

.btn {
  background: var(--brand);
  padding: var(--gap);
}

وما يُقال أقل هو أن هذا المتغير يُورَّث كأي قيمة أخرى. أعد تعريف الاسم نفسه على عنصر واحد، فيرى كل ما بداخله القيمة الجديدة وتبقى بقية الصفحة كما هي:

.card--warn { --brand: #d97706; }

الآن صار كل زر داخل تلك البطاقة برتقاليا دون تغيير سطر واحد من قاعدة .btn. والسمة الداكنة تُبنى على هذه الفكرة بالضبط: كتلة واحدة تعيد تعريف أسماء قليلة، لا ملف CSS ثان.

وحدّه: هذا ليس متغيرا بالمعنى البرمجي. فالحساب به لا يجري إلا داخل calc، ولا يمكنك استعماله في شرط media query. وإن كنت تريد الحلقات والشروط والدوال فأنت متجه إلى أدوات مثل Sass، وهذا كل عملها، ومخرجاتها في النهاية هذا CSS البسيط نفسه.

المسار السريع مع الذكاء الاصطناعي

النماذج اللغوية جيدة في «ابنِ لي هذا التخطيط»، لأن تلك المهمة ترجمة آلية لوصف إلى flex وgrid. وحيث تقصر هو بالضبط حيث يتعثر المبتدئ: معرفة لماذا لم يُطبَّق نمط. فذلك يستلزم أن ترى صفحتك، وهي لا تراها. لذا للمسار السريع نصفان: سلّم التخطيط واحتفظ بالتتالي. ويكفي للنصف الأول نموذج سريع ورخيص؛ واختيارنا الحالي في <a class="text-link" href="/ar/ai/">قسم الذكاء الاصطناعي</a>.

  1. اعزل الكتلة التي بها المشكلة وخذ HTML الحقيقي الخاص بها. ووصف الصفحة بدل لصق الترميز هو أكبر سبب منفرد لجواب لا صلة له.
  2. شغّل الوصفة أدناه. وإن كانت لديك متغيرات ألوان وتباعد، فاذكرها هناك كي لا يخترع النموذج أسماء جديدة.
  3. ضع المخرجات واختبر الاتجاهين: غيّر قيمة dir على وسم html في أدوات المطور وانظر إلى الصفحة نفسها.
  4. إن لم يُطبَّق نمط فلا تعد إلى المحادثة. افتح لسان Computed: فيه القاعدة الفائزة ومن أي ملف وأي سطر جاءت.

وصفة جاهزة للنسخ

الدور: من يكتب CSS حديثا بلا إطار عمل.

ما أريده:
القسم: {اسم القسم}
الترميز الحالي: {ضع HTML هنا}
السلوك المطلوب: {مثلا ثلاث بطاقات بجوار بعضها، ومتراكبة على الهاتف}
الاتجاه: من اليمين إلى اليسار (العربية)، والشفرة نفسها يجب أن تصح من اليسار إلى اليمين

قواعد المخرجات:
- أعطِ CSS فقط. لا تغيّر الترميز؛ وإن لزم إضافة صنف فقل أولا أين ولماذا.
- كل التباعد والاتجاه بخصائص منطقية: margin-inline وpadding-inline وinset-inline-start وtext-align: start. ولا تكتب left وright فيزيائيين.
- خذ الألوان والتباعد من هذه المتغيرات: {اذكر متغيراتك الموجودة}. ولا تخترع متغيرا جديدا دون ذكر السبب.
- تخطيط بمحور واحد بـflex وبمحورين بـgrid. واكتب سطرا واحدا: أيهما اخترت ولماذا.
- ممنوع important. وإن لم يعمل دونه فالمحدد خاطئ؛ قل ذلك بدلا منه.
- لا عروض ثابتة بالبكسل إلا لشيء ثابت فعلا، كأيقونة.
- كل ما له حالة hover يجب أن تكون له حالة focus-visible أيضا.

وبعد الشفرة، قل في ثلاثة أسطر ما الذي ينتقل في الاتجاه من اليسار إلى اليمين وأين ترددت.

قبل أن تثق بالناتج: شيئان عليك فحصهما بنفسك. الأول الاتجاه: لا أداة آلية تخبرك أن الصفحة وقعت خطأ في المرآة، بل عيناك وحدهما. والثاني التتالي: اسأل نموذجا لماذا لم يُطبَّق نمطك فتحصل على شيء يشبه الجواب لكنه تخمين، لأنه لم يرَ صفحتك. وذلك السؤال يُجاب في مكان آخر: لسان Computed في متصفحك.

الذكاء الاصطناعي في هذا العمل

في CSS للذكاء الاصطناعي موضع واضح، وخارجه يفقد فائدته سريعا. ثلاثة أمور يسرّعها فعلا: تحويل وصف تخطيط إلى flex وgrid، وشرح مقطع CSS غير مألوف سطرا سطرا، وتحويل ملف مليء بـleft وright إلى نسخته المنطقية. واثنان لا نسلّمهما: قرار شكل الصفحة، ومعرفة لماذا لم تُطبَّق قاعدة.

أدوات تساعد فعلا

  • Claude جيد في شرح ملف CSS سطرا سطرا وفي إعادة كتابة الخصائص الفيزيائية إلى منطقية. وإيران ليست في قائمة الدول المدعومة لدى أنثروبيك؛ قرأنا ذلك في صفحة أنثروبيك نفسها.
  • Gemini يكفي لبناء تخطيط من وصف وللأسئلة الأساسية، ويتعامل مع الفارسية جيدا. وصفحة غوغل نفسها تقول إن تطبيق جيميناي يعمل في أكثر من مئتين وثلاثين دولة ومنطقة، وإيران ليست في تلك القائمة.
  • Claude Code مفيد حين يلزم تغيير ملف كامل لا مقطعا، لأنه يعمل في محررك وطرفيتك ويرى الملف. يُثبَّت مجانا لكنه يحتاج اشتراك أنثروبيك، وإيران ليست في قائمة الدول المدعومة.

اين ينقلب ضدك

هنا خطران محددان وكلاهما صامت. الأول الاتجاه: لا يعرف النموذج أن صفحتك من اليمين إلى اليسار إلا أن تقول، فإن لم تطلب ذلك في الأمر فلا شيء يمنع margin-left، وتأتي المخرجات صحيحة بالإنجليزية معكوسة بالعربية. ولهذا تطلب الوصفة أعلاه الخصائص المنطقية صراحة؛ ومجموعتها الكاملة موثقة في MDN. والثاني التتالي: لا يرى النموذج صفحتك، فأي جواب عن سبب عدم تطبيق نمط هو تخمين، والتخمينات التي تنجح صدفة ترفع وزن المحدد أو تضيف important. وكلاهما ينجح مرة ويجعل التغيير التالي أصعب. وموقفنا: التخطيط بالنموذج والتتالي بالمتصفح. ولمعرفة كيفية الدفع لكل أداة من إيران، انظر دليل الشراء.

المصادر: MDN: CSS logical properties and values MDN: Handling conflicts, the cascade and specificity Anthropic: supported countries Google: where Gemini Apps are available

حدود هذه النصيحة

CSS يبني مظهر صفحة واحدة لا موقعا. فالمحتوى والبنية عمل HTML، والسلوك عمل جافاسكريبت، وفتح الصفحة على الإنترنت عمل الاستضافة والنطاق. ونقطة تُقال أقل: إن كنت ستطلق موقعك على ووردبريس بقالب جاهز، فقد يكون كل ما تحتاجه من CSS عشرين سطرا، والتعمق في grid ليس مسارك السريع. هذا الدرس مكتوب لمن يريد أن يتحكم بالمظهر بنفسه أو أن يفهم ما يفعله قالبه. وقاعدة الخصائص المنطقية مشروطة بالقدر نفسه: على موقع بلغة واحدة من اليسار إلى اليمين إلى الأبد، الالتزام بها عادة حسنة لا تنقذ شيئا.

من عملنا نحن

هذا الموقع نفسه مثالنا ويمكن فحصه. ملف الأنماط الرئيسي في rgb.ir نحو مئة وثلاثين كيلوبايت ويخدم لغات الموقع الأربع معا: الفارسية والعربية من اليمين إلى اليسار، والإنجليزية والتركية من اليسار إلى اليمين، دون أي ملف rtl منفصل في القالب. ويوم مراجعة هذا الدرس، استعمل ذلك الملف الخصائص المنطقية في سبعين موضعا ولم يكن فيه أي margin-left ولا padding-right ولا حتى left وright مجردين؛ ولا text-align: left ولا float. وصراحة لازمة: بقيت أربعة أسطر margin-left في ملف الأشكال، وبقيت عمدا، لأن أربعتها حيلة توسيط واحدة قيمتها متناظرة، ولا يحمل left فيها معنى اتجاه أصلا. والقاعدة أن الخصائص المنطقية تلزم حيث يكون للتخطيط بداية ونهاية، لا في كل موضع تظهر فيه كلمة left.

اسئلة متابعة حقيقية

أتعلم HTML أولا أم أبدأ بـCSS مباشرة؟

HTML أولا، لكن ليس حتى تتقنه. فمحدد CSS يشير إلى عناصر وأصناف، وحتى تعرف ما الوسوم الأساسية ستكون نصف قواعدك بلا هدف. بعد ظهر واحد من HTML يكفي ليصير CSS ذا معنى.

هل أذهب مباشرة إلى Bootstrap أو Tailwind؟

ليس في الأسبوع الأول. فإطار العمل يخفي خلف طبقة من الأصناف التتالي الذي لم تتعلمه بعد، ويوم لا يستقر شيء في مكانه لا تملك أداة لفهمه. وبعد أن تفهم المحددات والتتالي وgrid، يصير اختيار إطار عمل قرارا مشروعا للمشروع لا اختصارا.

لماذا يتفكك موقعي على الهاتف؟

غالبا أحد أمرين: وسم viewport غائب من head، أو كتبت في موضع ما عرضا ثابتا بالبكسل أكبر من شاشة الهاتف. الأول سطر واحد شُرح في درس HTML من هذا المسار، والثاني عادة width كان ينبغي أن يكون max-width. والتصميم المتجاوب هو الدرس التالي في هذا المسار.