أساسيات الواجهة الأمامية
CSS Box Model: كل ما يهم فعليا
دليل بصري كامل لـ CSS box model — content وpadding وborder وmargin وbox-sizing وانهيار الـ margins والخصائص المنطقية، مع الأخطاء التي تظهر في التخطيطات الحقيقية.
كل عنصر في الصفحة هو صندوق مستطيل. التخطيط، المسافات، المحاذاة، ومعظم مشاكل "لماذا يوجد فرق 8px هنا؟" ترجع كلها إلى شيء واحد: كيف يُقاس هذا الصندوق. الـ box model هو قواعد هذا القياس، وعندما تصبح واضحة في ذهنك، يتوقف تخطيط CSS عن أن يكون تخمينا.
الـ box model يجيب على سؤال واحد: عندما تضبط
widthوheightوpaddingوborderوmargin، ما حجم العنصر فعليا، وأين سيقف العنصر التالي؟
الطبقات الأربع
كل صندوق مبني من أربع طبقات متداخلة، من الداخل إلى الخارج: content وpadding وborder وmargin.
- Content — حيث يعيش النص والصور والعناصر الأبناء. حجمه يحدده
width/height(ونسخmin-/max-). - Padding — مسافة شفافة داخل الـ border، وتأخذ نفس خلفية العنصر.
- Border — حافة مرئية (أو غير مرئية) لها عرض ونمط ولون.
- Margin — مسافة شفافة خارج الـ border تفصل الصندوق عن جيرانه، وليس لها خلفية أبدا.
الخاصية التي تُربك الجميع: box-sizing
هذا هو السؤال الذي يسبب أكبر قدر من الالتباس: هل width: 200px تعني أن المحتوى عرضه 200px، أم أن الصندوق كله عرضه 200px؟ الإجابة تعتمد على box-sizing.
content-box(الافتراضي):widthتحدد المحتوى فقط. الـ padding والـ border يُضافان فوقها، فيصبح الصندوق الظاهر أعرض من الرقم الذي كتبته.border-box:widthتحدد المحتوى + الـ padding + الـ border معا. الرقم الذي تكتبه هو العرض الحقيقي على الشاشة، والمحتوى يتقلص ليفسح المكان.
ولهذا تبدأ معظم المشاريع بهذا الـ reset:
*,
*::before,
*::after {
box-sizing: border-box;
}
مع border-box، فإن width: 50% مع padding: 20px يبقى داخل نصف الحاوية — بدون حسابات overflow في رأسك. اعتبر هذا الـ reset قاعدة افتراضية، لا خيارا.
Content: العرض والارتفاع وحدودهما
تتحكم في منطقة المحتوى:
width/height— قياسات صريحة. القيمةauto(الافتراضية) تجعل عناصر الـ block تملأ عرض الحاوية وتتقلص حول ارتفاع محتواها.min-width/min-height— حد أدنى لا ينزل الصندوق تحته.max-width/max-height— حد أقصى. وmax-width: 100%هي الحماية الكلاسيكية التي تمنع الصور والبطاقات من تجاوز الشاشات الصغيرة.
النسب المئوية على width تكون نسبة إلى عرض الحاوية. أما النسب على height فلا تعمل إلا إذا كان للأب ارتفاع محدد — وإلا تتحول إلى auto. هذه القاعدة وحدها تفسر معظم مشاكل "لماذا لا يفعل height: 100% شيئا".
Padding: المسافة الداخلية
الـ padding يضيف مساحة بين المحتوى والـ border، ويحمل خلفية العنصر.
.card {
padding: 24px; /* الجهات الأربع */
padding: 16px 24px; /* أعلى/أسفل | يمين/يسار */
padding: 8px 16px 12px; /* أعلى | يمين-يسار | أسفل */
padding: 8px 16px 12px 4px;/* أعلى | يمين | أسفل | يسار (باتجاه عقارب الساعة) */
}
أمران يُنسيان غالبا:
- الـ padding لا يمكن أن يكون سالبا.
- النسبة المئوية في الـ padding تكون نسبة إلى عرض الحاوية — حتى
padding-top. هذه الخاصية كانت الحيلة خلف صناديق النسبة القديمة (استخدمaspect-ratioالآن بدلا منها).
Border: الحافة المرئية
.box {
border: 2px solid #111; /* العرض | النمط | اللون */
border-bottom: 1px solid #ddd; /* جهة واحدة */
border-radius: 12px; /* تدوير صندوق الـ border */
}
في content-box يُحسب عرض الـ border ضمن الحجم الكلي للعنصر؛ وفي border-box يأكل من المحتوى. أما outline فيبدو مشابها لكنه ليس جزءا من الـ box model — يُرسم فوق العنصر ولا يؤثر على التخطيط، ولهذا بالضبط هو الأداة الصحيحة لـ focus rings.
Margin: المسافة الخارجية
الـ margin يفصل الصندوق عن جيرانه. وعلى عكس الـ padding يمكن أن يكون سالبا، وله سلوكان خاصان.
.block {
margin: 0 auto; /* auto الأفقي = توسيط صندوق بعرض ثابت */
margin-top: -8px; /* الهوامش السالبة تقرّب الجيران أو تتداخل معهم */
}
margin: auto هي طريقة توسيط الـ block أفقيا: أعطه width وهوامش auto يمين ويسار. (الـ margin العمودي بقيمة auto لا يفعل شيئا في التدفق العادي — لكنه يوسّط داخل flex وgrid.)
انهيار الـ Margins — الفخ الكلاسيكي
عندما يلتقي هامشان عموديان في التدفق العادي، فإنهما لا يُجمعان — بل ينهاران إلى القيمة الأكبر فقط.
يحدث الانهيار بين الأشقاء المتجاورين، وبين الأب وأول/آخر ابن له. وهو عمودي فقط — الهوامش الأفقية لا تنهار أبدا — ولا يحدث داخل حاويات flex أو grid. تكسر الانهيار بوضع شيء بين الهامشين: padding أو border أو formatting context جديد (display: flex، overflow: hidden، إلخ). وهذا هو السبب الحقيقي لتفضيل التخطيطات الحديثة لـ gap في flex/grid: فالـ gap لا ينهار أبدا، فتصبح المسافات متوقعة.
صناديق Block وInline وInline-Block
الـ box model ينطبق على كل عنصر، لكن display يغير أي الأجزاء يسري مفعولها:
| Display | يحترم width/height | الهامش/الحشو العمودي يدفع التخطيط |
|---|---|---|
block | نعم | نعم |
inline | لا (يتحجّم حسب المحتوى) | الـ padding/border يظهران لكن لا يحركان السطور المحيطة؛ والهوامش أفقية فقط |
inline-block | نعم | نعم |
هذا الجدول يفسر لماذا width على <span> "لا يفعل شيئا" حتى تجعله inline-block أو block.
الخصائص المنطقية (ولماذا تهم هنا)
الخصائص الفيزيائية مثل margin-left تفترض الاتجاه من اليسار لليمين. وفي صفحة عربية (RTL) يكون "اليسار" هو الجهة الخاطئة. أما الخصائص المنطقية فتتبع اتجاه القراءة:
/* فيزيائية — تنكسر في RTL */
margin-left: 16px;
padding-right: 8px;
/* منطقية — صحيحة في LTR وRTL معا */
margin-inline-start: 16px;
padding-inline-end: 8px;
inline-start/inline-endتقابل اليسار/اليمين في LTR وتنعكس تلقائيا في RTL.block-start/block-endتقابل الأعلى/الأسفل.- وهناك اختصارات أيضا:
margin-inlineوpadding-blockوinset-inline.
لأي واجهة تُطلق في أكثر من اتجاه، تزيل الخصائص المنطقية فئة كاملة من أخطاء الانعكاس.
فحص الصندوق في DevTools
افتح فاحص العناصر وانظر إلى مخطط الـ box model في تبويب Computed. يرسم الطبقات الأربع بالضبط — المحتوى في المنتصف، ثم padding ثم border ثم margin — بالقيم الحقيقية بالبكسل. وعندما تكون المسافة "خاطئة بشكل غامض"، يخبرك هذا المخطط في ثوان هل السبب padding أم margin أم margin منهار.
أخطاء شائعة
- نسيان reset الـ
box-sizing: border-boxثم محاربة الـ overflow الناتج عن الـ padding. - توقّع عمل
height: 100%بينما الأب بلا ارتفاع محدد. - إضافة هوامش عمودية والاندهاش من انهيارها بدل جمعها.
- استخدام
width/heightعلى عناصر inline والتساؤل لماذا لا يتغير شيء. - اللجوء إلى
marginلتوزيع أبناء flex/grid بينماgapأنظف وبلا انهيار. - استخدام
margin-left/rightفي موقع ثنائي الاتجاه بدل المنطقيةinline-start/inline-end.
النموذج الذهني الذي تحتفظ به
الصندوق هو content ← padding ← border ← margin، يُقاس وفق box-sizing. اضبط border-box عالميا ليكون الرقم الذي تكتبه هو الرقم الذي تحصل عليه. استخدم gap والخصائص المنطقية للمسافات، والجأ إلى مخطط الصندوق في DevTools عند وجود خلل، وستختفي معظم ألغاز التخطيط.