خصائص حاوية Flexbox
مقدمة في Flexbox
تخطيط الصندوق المرن في CSS، المعروف عادةً بـ Flexbox، هو نظام تخطيط أحادي البعد مصمم لتوزيع المساحة بين العناصر في حاوية ومحاذاتها بكفاءة، حتى عندما تكون أحجامها غير معروفة أو ديناميكية. قبل Flexbox، اعتمد المطورون على التعويم، والتخطيطات القائمة على الجداول، وحيل inline-block لبناء أنماط واجهة المستخدم الشائعة مثل أشرطة التنقل، والمحتوى المتمركز، والعناصر المتباعدة بالتساوي، وتخطيطات البطاقات المرنة. كانت هذه التقنيات القديمة مرهقة وهشة وغالباً ما تتطلب حلولاً بديلة غير بديهية. تم إنشاء Flexbox خصيصاً لحل هذه المشاكل بمجموعة نظيفة وقابلة للتنبؤ وقوية من الخصائص.
يُسمى Flexbox نظام تخطيط "أحادي البعد" لأنه يتعامل مع التخطيط في اتجاه واحد في كل مرة -- إما كصف (أفقي) أو كعمود (عمودي). هذا يميزه عن CSS Grid، وهو نظام تخطيط ثنائي البعد يتعامل مع الصفوف والأعمدة في وقت واحد. بينما قد يبدو هذا محدوداً، فإن التحكم أحادي البعد هو بالضبط ما تحتاجه للغالبية العظمى من مهام التخطيط: قوائم التنقل، وأشرطة الأدوات، وعناصر التحكم في النماذج، وصفوف البطاقات، وروابط التذييل، وتوسيط المحتوى، وتوزيع المساحة بين العناصر.
في هذا الدرس، سنركز حصرياً على خصائص حاوية Flexbox -- الخصائص التي تطبقها على العنصر الأب الذي يحتوي على عناصر flex. فهم خصائص الحاوية هو أساس إتقان Flexbox. في الدرس التالي، سنغطي خصائص عناصر flex التي تتحكم في الأبناء الفرديين داخل الحاوية.
إنشاء حاوية Flex
لتفعيل Flexbox، تعيّن خاصية display لعنصر حاوية إما إلى flex أو inline-flex. هذا الإعلان الوحيد يحوّل العنصر إلى حاوية flex وجميع أبنائه المباشرين إلى عناصر flex.
display: flex مقابل display: inline-flex
/* حاوية flex على مستوى الكتلة (تأخذ العرض الكامل) */
.container {
display: flex;
}
/* حاوية flex على مستوى السطر (بعرض محتواها فقط) */
.inline-container {
display: inline-flex;
}
/* هيكل HTML */
<div class="container">
<div class="item">عنصر 1</div>
<div class="item">عنصر 2</div>
<div class="item">عنصر 3</div>
</div>
display: flex
عند تعيين display: flex، تصبح الحاوية عنصراً على مستوى الكتلة. تأخذ العرض الكامل المتاح لعنصرها الأب، تماماً مثل <div> العادي. ومع ذلك، أبناؤها الآن عناصر flex ويتم ترتيبها وفقاً لقواعد Flexbox بدلاً من التدفق العادي للمستند. بشكل افتراضي، تُرتب عناصر flex في صف أفقي، ومحاذاة إلى بداية الحاوية، ومحجمة وفقاً لمحتواها.
display: inline-flex
القيمة display: inline-flex تنشئ حاوية flex تتصرف كعنصر سطري خارجياً -- تأخذ فقط العرض الذي تحتاجه عناصر flex الخاصة بها، ويمكن أن يجلس محتوى سطري آخر بجانبها. داخلياً، لا يزال أبناؤها عناصر flex ويتبعون جميع قواعد Flexbox. هذا مفيد عندما تريد أن تجلس حاوية flex بشكل سطري مع نص أو عناصر أخرى، مثل مجموعة أزرار داخل فقرة أو مجموعة وسوم سطرية.
مقارنة flex و inline-flex
<!-- مستوى الكتلة: يأخذ العرض الكامل -->
<div class="flex-container">
<span>أ</span>
<span>ب</span>
<span>ج</span>
</div>
<p>هذه الفقرة تبدأ على سطر جديد.</p>
<!-- مستوى سطري: يجلس سطرياً مع المحتوى المحيط -->
<p>
إليك بعض الوسوم:
<span class="inline-flex-container">
<span class="tag">CSS</span>
<span class="tag">HTML</span>
<span class="tag">JS</span>
</span>
وهي تجلس سطرياً مع النص.
</p>
float و clear ليس لها تأثير على عناصر flex. خاصية vertical-align أيضاً ليس لها تأثير على عناصر flex. ومع ذلك، لا يزال بالإمكان تحديد موقع عناصر flex بشكل مطلق، وفي هذه الحالة تتم إزالتها من تخطيط flex.فهم محاور Flex
يعتمد تخطيط Flexbox على محورين يحددان كيفية ترتيب العناصر ومحاذاتها. فهم هذه المحاور أمر بالغ الأهمية لإتقان Flexbox لأن كل خاصية محاذاة وتوزيع تشير إلى أحد هذه المحاور.
المحور الرئيسي
المحور الرئيسي هو المحور الأساسي الذي تُرتب عليه عناصر flex. بشكل افتراضي، يمتد المحور الرئيسي أفقياً من اليسار إلى اليمين (في اللغات من اليسار إلى اليمين). توضع عناصر flex واحدة تلو الأخرى على هذا المحور. تحدد خاصية flex-direction اتجاه المحور الرئيسي. تُسمى بداية المحور الرئيسي main-start ونهايته تُسمى main-end.
المحور العرضي
المحور العرضي عمودي على المحور الرئيسي. إذا كان المحور الرئيسي أفقياً، فإن المحور العرضي عمودي (والعكس صحيح). يحدد المحور العرضي كيفية محاذاة العناصر في الاتجاه العمودي. تُسمى بداية المحور العرضي cross-start ونهايته تُسمى cross-end.
تصور المحاور
/* الافتراضي: المحور الرئيسي أفقي (صف) */
/*
main-start ───── المحور الرئيسي ────> main-end
│
│ cross-start
│
▼ المحور العرضي
│
│ cross-end
*/
/* عند flex-direction: column */
/*
cross-start ──── المحور العرضي ───> cross-end
│
│ main-start
│
▼ المحور الرئيسي
│
│ main-end
*/
justify-content يعمل دائماً على المحور الرئيسي. align-items و align-content يعملان دائماً على المحور العرضي.flex-direction
تحدد خاصية flex-direction اتجاه المحور الرئيسي، الذي بدوره يحدد الاتجاه الذي توضع فيه عناصر flex داخل الحاوية. تقبل أربع قيم، كل منها تؤسس اتجاهاً مختلفاً للمحور الرئيسي.
جميع قيم flex-direction
/* العناصر تتدفق من اليسار إلى اليمين (الافتراضي) */
.row {
display: flex;
flex-direction: row;
}
/* العناصر تتدفق من اليمين إلى اليسار */
.row-reverse {
display: flex;
flex-direction: row-reverse;
}
/* العناصر تتدفق من الأعلى إلى الأسفل */
.column {
display: flex;
flex-direction: column;
}
/* العناصر تتدفق من الأسفل إلى الأعلى */
.column-reverse {
display: flex;
flex-direction: column-reverse;
}
flex-direction: row (الافتراضي)
هذه هي القيمة الافتراضية. يمتد المحور الرئيسي أفقياً، وتوضع العناصر من اليسار إلى اليمين (في لغات LTR) أو من اليمين إلى اليسار (في لغات RTL مثل العربية). تُرتب العناصر في خط أفقي واحد، كل عنصر يوضع بعد السابق على المحور الرئيسي. يمتد المحور العرضي عمودياً.
flex-direction: row-reverse
لا يزال المحور الرئيسي يمتد أفقياً، لكن الاتجاه معكوس. توضع العناصر من اليمين إلى اليسار (في لغات LTR). هذا لا يطبق مجرد عكس بصري -- يتم تبديل نقطتي main-start و main-end، مما يعني أن خصائص مثل justify-content: flex-start ستدفع العناصر إلى اليمين بدلاً من اليسار. هذا مفيد لعكس الترتيب البصري للعناصر دون تغيير ترتيب HTML المصدري.
flex-direction: column
يمتد المحور الرئيسي عمودياً من الأعلى إلى الأسفل. تُكدس العناصر فوق بعضها البعض، مشابهة لعناصر الكتلة العادية، ولكن مع القوة الكاملة لمحاذاة وتوزيع Flexbox. عند استخدام flex-direction: column، تتحكم خصائص مثل justify-content في التوزيع العمودي، و align-items تتحكم في المحاذاة الأفقية -- عكس اتجاه الصف الافتراضي.
flex-direction: column-reverse
يمتد المحور الرئيسي عمودياً من الأسفل إلى الأعلى. تُكدس العناصر بترتيب معكوس، مع العنصر الأول في الأسفل والعنصر الأخير في الأعلى. هذا مفيد لواجهات الدردشة، والجداول الزمنية المعروضة بشكل معكوس، أو أي تخطيط تريد فيه أن يتدفق المحتوى للأعلى.
مثال عملي: تغييرات الاتجاه
<div class="nav-horizontal">
<a href="#">الرئيسية</a>
<a href="#">حول</a>
<a href="#">الخدمات</a>
<a href="#">اتصل بنا</a>
</div>
<div class="sidebar-vertical">
<a href="#">لوحة التحكم</a>
<a href="#">الإعدادات</a>
<a href="#">الملف الشخصي</a>
<a href="#">تسجيل الخروج</a>
</div>
CSS لأمثلة الاتجاه
.nav-horizontal {
display: flex;
flex-direction: row;
gap: 20px;
padding: 10px 20px;
background: #2c3e50;
}
.nav-horizontal a {
color: white;
text-decoration: none;
padding: 8px 16px;
}
.sidebar-vertical {
display: flex;
flex-direction: column;
width: 200px;
background: #34495e;
}
.sidebar-vertical a {
color: white;
text-decoration: none;
padding: 12px 20px;
border-bottom: 1px solid #4a6785;
}
row-reverse أو column-reverse يغير فقط الترتيب البصري للعناصر، وليس ترتيب المستند. قارئات الشاشة والتنقل بلوحة المفاتيح لا يزالان يتبعان ترتيب HTML المصدري الأصلي. إذا كان الترتيب البصري مهماً للفهم، فإن تغيير ترتيب المصدر عادةً ما يكون نهجاً أفضل من استخدام الاتجاهات المعكوسة، لأنه يضمن الحفاظ على إمكانية الوصول.flex-wrap
بشكل افتراضي، تحاول عناصر flex أن تتسع في سطر واحد. إذا تجاوز العرض المجمع لجميع العناصر عرض الحاوية، ستتقلص العناصر لتتسع (إذا سمحت قيمة flex-shrink الخاصة بها) بدلاً من الالتفاف إلى سطر جديد. تتحكم خاصية flex-wrap فيما إذا كانت عناصر flex مجبرة على سطر واحد أو يمكن أن تلتف إلى أسطر متعددة.
قيم flex-wrap
/* جميع العناصر مجبرة على سطر واحد (الافتراضي) */
.no-wrap {
display: flex;
flex-wrap: nowrap;
}
/* العناصر تلتف إلى أسطر جديدة حسب الحاجة */
.wrap {
display: flex;
flex-wrap: wrap;
}
/* العناصر تلتف بترتيب معكوس */
.wrap-reverse {
display: flex;
flex-wrap: wrap-reverse;
}
flex-wrap: nowrap (الافتراضي)
هذه هي القيمة الافتراضية. توضع جميع عناصر flex على سطر واحد، وستتقلص إذا لزم الأمر لتجنب تجاوز الحاوية. إذا كانت للعناصر عرض أدنى ثابت يمنعها من التقلص بما يكفي، ستتجاوز الحاوية. هذا السلوك مفيد عندما تريد أن تبقى جميع العناصر مرئية في صف أو عمود واحد، مثل شريط التنقل.
flex-wrap: wrap
عند تمكين الالتفاف، ستنتقل عناصر flex التي لا تتسع في السطر الحالي إلى السطر التالي. في تخطيط الصف، هذا يعني أن العناصر تلتف إلى صف جديد أسفل. في تخطيط العمود، تلتف العناصر إلى عمود جديد على اليمين (في LTR). كل سطر جديد من العناصر الملتفة يُسمى خط flex. تتحكم خاصية align-content (التي سنغطيها لاحقاً في هذا الدرس) في كيفية توزيع خطوط flex المتعددة على المحور العرضي.
flex-wrap: wrap-reverse
تعمل مثل wrap، لكن تُضاف الأسطر الجديدة في الاتجاه المعاكس. في تخطيط الصف، تلتف العناصر إلى صف جديد فوق بدلاً من أسفل. هذا مفيد لأنماط تصميم محددة حيث تريد أن تظهر العناصر الأحدث في الأعلى.
مثال عملي: تخطيط بطاقات ملتفة
.card-container {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
.card {
flex: 1 1 300px;
/* flex-grow: 1 -- البطاقات تنمو لملء المساحة
flex-shrink: 1 -- البطاقات يمكن أن تتقلص
flex-basis: 300px -- العرض المثالي 300px */
padding: 20px;
background: var(--bg-white);
border: 1px solid var(--border-light);
border-radius: 8px;
}
/* على حاوية 1000px:
3 بطاقات تتسع في الصف الأول (300px لكل + فجوات)
البطاقات المتبقية تلتف إلى الصف التالي */
flex-wrap: wrap نشطاً وتلتف العناصر إلى أسطر متعددة، ينمو حجم الحاوية العرضي لاستيعاب جميع خطوط flex. كل خط flex يُحجم بشكل مستقل بناءً على أطول عنصر في ذلك الخط. تتحكم خاصية align-content في التباعد بين خطوط flex هذه.اختصار flex-flow
خاصية flex-flow هي اختصار يجمع بين flex-direction و flex-wrap في إعلان واحد. هذا يقلل مقدار CSS الذي تحتاج لكتابته ويسهل رؤية كل من الاتجاه وسلوك الالتفاف بنظرة واحدة.
أمثلة اختصار flex-flow
/* اتجاه صف، بدون التفاف (الافتراضي) */
.default {
flex-flow: row nowrap;
}
/* اتجاه صف مع التفاف */
.row-wrap {
flex-flow: row wrap;
}
/* اتجاه عمود، بدون التفاف */
.column-no-wrap {
flex-flow: column nowrap;
}
/* اتجاه عمود مع التفاف */
.column-wrap {
flex-flow: column wrap;
}
/* صف معكوس مع التفاف */
.row-reverse-wrap {
flex-flow: row-reverse wrap;
}
/* قيمة واحدة: تعيّن الاتجاه، الالتفاف يكون nowrap افتراضياً */
.just-direction {
flex-flow: column;
}
/* قيمة واحدة: تعيّن الالتفاف، الاتجاه يكون row افتراضياً */
.just-wrap {
flex-flow: wrap;
}
justify-content
تتحكم خاصية justify-content في كيفية توزيع عناصر flex على المحور الرئيسي. تحدد ما يحدث للمساحة الإضافية عندما لا تملأ عناصر flex المحور الرئيسي بالكامل للحاوية. هذه واحدة من أكثر خصائص Flexbox استخداماً، وفهم كل قيمها أمر ضروري.
جميع قيم justify-content
/* العناصر مكدسة في بداية المحور الرئيسي (الافتراضي) */
.start {
display: flex;
justify-content: flex-start;
}
/* العناصر مكدسة في نهاية المحور الرئيسي */
.end {
display: flex;
justify-content: flex-end;
}
/* العناصر متمركزة على المحور الرئيسي */
.center {
display: flex;
justify-content: center;
}
/* مساحة متساوية بين العناصر، بدون مساحة عند الحواف */
.between {
display: flex;
justify-content: space-between;
}
/* مساحة متساوية حول كل عنصر */
.around {
display: flex;
justify-content: space-around;
}
/* مساحة متساوية بين وحول العناصر */
.evenly {
display: flex;
justify-content: space-evenly;
}
justify-content: flex-start (الافتراضي)
تُكدس العناصر نحو بداية المحور الرئيسي. في تخطيط صف من اليسار إلى اليمين، تُحاذى العناصر إلى الحافة اليسرى. أي مساحة إضافية تظهر على الجانب الأيمن (نهاية المحور الرئيسي). هذا هو السلوك الافتراضي ويتطابق مع ما تراه عند تعيين display: flex لأول مرة دون تحديد أي محاذاة.
justify-content: flex-end
تُكدس العناصر نحو نهاية المحور الرئيسي. في تخطيط صف من اليسار إلى اليمين، تُحاذى العناصر إلى الحافة اليمنى. أي مساحة إضافية تظهر على الجانب الأيسر. هذا مفيد لدفع عناصر مثل الأزرار أو روابط التنقل إلى الجانب الأيمن من الحاوية دون استخدام حيل margin-left: auto.
justify-content: center
تُتمركز العناصر على المحور الرئيسي. توضع مساحة متساوية على جانبي مجموعة العناصر. هذا أحد أكثر استخدامات Flexbox شيوعاً -- توسيط المحتوى أفقياً (في اتجاه الصف) أو عمودياً (في اتجاه العمود). قبل Flexbox، كان التوسيط الأفقي مباشراً مع margin: 0 auto، لكن التوسيط العمودي كان يتطلب حلولاً معقدة. مع Flexbox، كلاهما سهل.
justify-content: space-between
تُوزع العناصر بالتساوي على المحور الرئيسي. العنصر الأول ملتصق بحافة البداية، والعنصر الأخير ملتصق بحافة النهاية، وتوضع مساحة متساوية بين كل زوج من العناصر المتجاورة. لا توجد مساحة قبل العنصر الأول أو بعد العنصر الأخير. هذا مثالي لأشرطة التنقل حيث تريد أن تنتشر العناصر عبر العرض الكامل مع لمس العنصر الأول والأخير للحواف.
justify-content: space-around
تُوزع العناصر بالتساوي مع مساحة متساوية حول كل عنصر. هذا يعني أن المساحة قبل العنصر الأول وبعد العنصر الأخير هي نصف حجم المساحة بين العناصر المتجاورة. إذا كانت المساحة بين عنصرين متجاورين 20px، فإن المساحة عند كل حافة هي 10px. هذا ينشئ توزيعاً متوازناً بصرياً ولكن بمساحة أقل عند الحواف.
justify-content: space-evenly
تُوزع العناصر بالتساوي مع مساحة متساوية تماماً بين كل زوج من العناصر المتجاورة وبين العناصر وحواف الحاوية. كل فجوة متطابقة. هذا ينتج التباعد الأكثر انتظاماً. إذا كان هناك 60px من المساحة الإضافية الإجمالية و 3 عناصر، كل من الفجوات الأربع (قبل العنصر 1، بين العنصرين 1-2، بين العنصرين 2-3، وبعد العنصر 3) تحصل على 15px بالضبط.
مقارنة بصرية لقيم justify-content
/* افترض 3 عناصر، كل منها 100px عرضاً، في حاوية 500px */
/* 200px من المساحة الإضافية للتوزيع */
/* flex-start: [أ][ب][ج].................. */
/* flex-end: ..................[أ][ب][ج] */
/* center: .........[أ][ب][ج]......... */
/* space-between: [أ]........[ب]........[ج] */
/* space-around: ..[أ]......[ب]......[ج].. */
/* space-evenly: ....[أ]....[ب]....[ج].... */
مثال عملي: شريط تنقل مع justify-content
<nav class="navbar">
<div class="logo">علامتي التجارية</div>
<ul class="nav-links">
<li><a href="#">الرئيسية</a></li>
<li><a href="#">حول</a></li>
<li><a href="#">الخدمات</a></li>
<li><a href="#">اتصل بنا</a></li>
</ul>
</nav>
CSS لشريط التنقل
.navbar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px 30px;
background: #2c3e50;
color: white;
}
.logo {
font-size: 24px;
font-weight: bold;
}
.nav-links {
display: flex;
gap: 25px;
list-style: none;
margin: 0;
padding: 0;
}
.nav-links a {
color: white;
text-decoration: none;
padding: 8px 12px;
border-radius: 4px;
transition: background 0.3s;
}
.nav-links a:hover {
background: rgba(255, 255, 255, 0.1);
}
align-items
بينما يوزع justify-content العناصر على المحور الرئيسي، يتحكم align-items في كيفية محاذاة العناصر على المحور العرضي. في تخطيط صف افتراضي، يمتد المحور العرضي عمودياً، لذا يتحكم align-items في المحاذاة العمودية. في تخطيط العمود، يتحكم في المحاذاة الأفقية.
جميع قيم align-items
/* العناصر تتمدد لملء المحور العرضي (الافتراضي) */
.stretch {
display: flex;
align-items: stretch;
}
/* العناصر محاذاة لبداية المحور العرضي */
.start {
display: flex;
align-items: flex-start;
}
/* العناصر محاذاة لنهاية المحور العرضي */
.end {
display: flex;
align-items: flex-end;
}
/* العناصر متمركزة على المحور العرضي */
.center {
display: flex;
align-items: center;
}
/* العناصر محاذاة بخطوط أساس النص */
.baseline {
display: flex;
align-items: baseline;
}
align-items: stretch (الافتراضي)
هذه هي القيمة الافتراضية. تتمدد عناصر flex لملء المحور العرضي بالكامل للحاوية (طالما ليس لديها ارتفاع أو عرض صريح معيّن على البعد العرضي). في تخطيط الصف، تتمدد جميع العناصر إلى ارتفاع أطول عنصر. في تخطيط العمود، تتمدد العناصر إلى عرض أوسع عنصر. هذا هو سبب ظهور عناصر flex غالباً بارتفاعات متساوية دون أي CSS إضافي -- إنه سلوك align-items: stretch الافتراضي في العمل.
align-items: flex-start
تُحاذى العناصر إلى بداية المحور العرضي. في تخطيط الصف، تُدفع العناصر إلى الأعلى. كل عنصر يكون بارتفاع محتواه فقط -- لا يوجد تمدد. هذا مفيد عندما تريد أن تحافظ العناصر على ارتفاعها الطبيعي بدلاً من التمدد لمطابقة أطول عنصر شقيق.
align-items: flex-end
تُحاذى العناصر إلى نهاية المحور العرضي. في تخطيط الصف، تُدفع العناصر إلى الأسفل. هذا مفيد لمحاذاة عناصر مثل الأسعار أو أزرار الإجراء في أسفل حاوية، خاصة عندما يكون للعناصر الشقيقة ارتفاعات محتوى مختلفة.
align-items: center
تُتمركز العناصر على المحور العرضي. في تخطيط الصف، تُتمركز العناصر عمودياً. بالاقتران مع justify-content: center، يُنشئ هذا نمط "التوسيط المثالي" الشهير الذي كان من الصعب تحقيقه قبل Flexbox.
نمط التوسيط المثالي الشهير
/* توسيط أي شيء أفقياً وعمودياً */
.perfect-center {
display: flex;
justify-content: center; /* توسيط على المحور الرئيسي (أفقي) */
align-items: center; /* توسيط على المحور العرضي (عمودي) */
min-height: 100vh; /* ارتفاع نافذة العرض الكامل */
}
/* الابن سيكون متمركزاً تماماً في نافذة العرض */
.perfect-center .content {
max-width: 600px;
padding: 40px;
background: var(--bg-white);
border-radius: 12px;
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
}
align-items: baseline
تُحاذى العناصر بحيث تصطف خطوط أساس النص الخاصة بها. هذا مفيد بشكل خاص عندما يكون لديك عناصر بأحجام خطوط أو حشوة مختلفة، وتريد أن يجلس النص في كل عنصر على نفس الخط الأفقي. خط الأساس هو الخط غير المرئي الذي "تجلس" عليه معظم الحروف -- أسفل حروف مثل "a"، "b"، "c" ولكن ليس ذيول حروف مثل "g"، "p"، "y".
مثال محاذاة خط الأساس
<div class="baseline-demo">
<div class="small-text">نص صغير</div>
<div class="large-text">نص كبير</div>
<div class="padded-text">نص محشو</div>
</div>
CSS لعرض خط الأساس
.baseline-demo {
display: flex;
align-items: baseline;
gap: 20px;
padding: 20px;
background: #f8f9fa;
border: 2px dashed #ddd;
}
.small-text {
font-size: 14px;
padding: 5px 10px;
background: #3498db;
color: white;
}
.large-text {
font-size: 32px;
padding: 10px 20px;
background: #e74c3c;
color: white;
}
.padded-text {
font-size: 18px;
padding: 30px 15px;
background: #2ecc71;
color: white;
}
/* على الرغم من أحجام الخطوط والحشوة المختلفة،
يتحاذى النص في جميع العناصر الثلاثة على
نفس خط الأساس */
align-items: baseline كلما كان لديك روابط تنقل، أو مسارات تصفح، أو عناصر سطرية بأحجام خطوط مختلفة تحتاج لأن تبدو محاذاة بصرياً. تنتج نتيجة أكثر صقلاً من flex-start أو center في هذه المواقف.align-content
تتحكم خاصية align-content في كيفية توزيع خطوط flex المتعددة على المحور العرضي. تأخذ هذه الخاصية مفعولها فقط عندما يكون flex-wrap معيّناً إلى wrap أو wrap-reverse وتوجد أسطر متعددة من العناصر. إذا كانت جميع العناصر تتسع في سطر واحد، فليس لـ align-content أي تأثير.
فكر في align-content على أنه مكافئ المحور العرضي لـ justify-content. بينما يوزع justify-content العناصر على المحور الرئيسي، يوزع align-content خطوط flex على المحور العرضي. وبينما يحاذي align-items العناصر الفردية داخل خط flex واحد، يحاذي align-content الخطوط نفسها داخل الحاوية.
جميع قيم align-content
/* الخطوط تتمدد لملء المحور العرضي (الافتراضي) */
.stretch {
display: flex;
flex-wrap: wrap;
align-content: stretch;
}
/* الخطوط مكدسة في بداية المحور العرضي */
.start {
display: flex;
flex-wrap: wrap;
align-content: flex-start;
}
/* الخطوط مكدسة في نهاية المحور العرضي */
.end {
display: flex;
flex-wrap: wrap;
align-content: flex-end;
}
/* الخطوط متمركزة على المحور العرضي */
.center {
display: flex;
flex-wrap: wrap;
align-content: center;
}
/* مساحة متساوية بين الخطوط */
.between {
display: flex;
flex-wrap: wrap;
align-content: space-between;
}
/* مساحة متساوية حول كل خط */
.around {
display: flex;
flex-wrap: wrap;
align-content: space-around;
}
/* مساحة متساوية بين وحول الخطوط */
.evenly {
display: flex;
flex-wrap: wrap;
align-content: space-evenly;
}
مثال عملي: align-content مع عناصر ملتفة
.wrapped-grid {
display: flex;
flex-wrap: wrap;
align-content: flex-start;
height: 500px;
gap: 15px;
padding: 15px;
background: #f0f0f0;
}
.wrapped-grid .item {
flex: 0 0 calc(33.333% - 10px);
padding: 20px;
background: var(--bg-white);
border: 1px solid var(--border-light);
border-radius: 8px;
text-align: center;
}
/* مع align-content: flex-start، الصفوف الملتفة
مكدسة في الأعلى، مع مساحة إضافية في الأسفل.
مع align-content: center، ستكون الصفوف
متمركزة عمودياً داخل حاوية 500px. */
align-content عندما تكون العناصر على سطر واحد (بدون التفاف). تذكر: align-content يعمل فقط عندما توجد خطوط flex متعددة. للحاويات ذات السطر الواحد، استخدم align-items بدلاً من ذلك. إذا عيّنت flex-wrap: wrap لكن جميع العناصر تتسع في سطر واحد، فلن يكون لـ align-content أي تأثير مرئي.gap و row-gap و column-gap
خاصية gap (وخصائصها الفرعية row-gap و column-gap) تضيف تباعداً متسقاً بين عناصر flex دون استخدام الهوامش. هذه واحدة من أكثر الإضافات العملية إلى Flexbox، لأنها تزيل المشكلة الشائعة المتمثلة في الحاجة إلى إزالة الهوامش من العنصر الأول أو الأخير في صف.
استخدام gap في Flexbox
/* فجوة موحدة بين جميع العناصر */
.uniform-gap {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
/* فجوات صف وعمود مختلفة */
.different-gaps {
display: flex;
flex-wrap: wrap;
row-gap: 30px;
column-gap: 15px;
}
/* اختصار: row-gap ثم column-gap */
.shorthand-gap {
display: flex;
flex-wrap: wrap;
gap: 30px 15px;
/* row-gap: 30px, column-gap: 15px */
}
/* مقارنة مع نهج الهوامش القديم */
.old-approach .item {
margin: 0 10px 10px 0;
}
/* مشكلة: العنصر الأخير في الصف له هامش يميني غير مرغوب */
/* مشكلة: الصف الأخير له هامش سفلي غير مرغوب */
/* نهج gap -- لا مثل هذه المشاكل! */
.new-approach {
display: flex;
flex-wrap: wrap;
gap: 10px;
}
/* gap تضيف مساحة بين العناصر فقط، وليس عند الحواف أبداً */
مثال عملي: سحابة وسوم مع gap
.tag-cloud {
display: flex;
flex-wrap: wrap;
gap: 8px;
}
.tag {
padding: 6px 14px;
background: var(--bg-light);
border: 1px solid var(--border-light);
border-radius: 20px;
font-size: 14px;
color: var(--text-dark);
transition: all 0.2s;
}
.tag:hover {
background: var(--primary);
color: white;
border-color: var(--primary);
}
gap في Flexbox تتمتع بدعم ممتاز في جميع المتصفحات الحديثة. كانت متاحة في الأصل فقط في CSS Grid، لكن تم توسيعها لاحقاً إلى Flexbox. إذا كنت تحتاج لدعم متصفحات قديمة جداً (Internet Explorer أو إصدارات Safari قبل 14.1)، قد تحتاج لاستخدام نهج الهوامش كبديل احتياطي.حاويات Flex المتداخلة
أحد أقوى جوانب Flexbox هو أن عناصر flex يمكن أن تكون بنفسها حاويات flex. هذا التداخل يسمح لك ببناء تخطيطات معقدة من خلال الجمع بين حاويات flex متعددة، كل منها تتحكم في محاذاة وتوزيع أبنائها بشكل مستقل.
مثال Flexbox متداخل: تخطيط رأس الصفحة
<header class="site-header">
<div class="header-left">
<img src="logo.svg" alt="الشعار" class="logo">
<span class="brand-name">شركتي</span>
</div>
<nav class="header-center">
<a href="#">المنتجات</a>
<a href="#">الأسعار</a>
<a href="#">التوثيق</a>
<a href="#">المدونة</a>
</nav>
<div class="header-right">
<button class="btn-login">تسجيل الدخول</button>
<button class="btn-signup">إنشاء حساب</button>
</div>
</header>
CSS للرأس المتداخل
/* حاوية flex خارجية: توزع ثلاثة أقسام */
.site-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 30px;
background: white;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
}
/* حاوية flex داخلية: الشعار + اسم العلامة التجارية */
.header-left {
display: flex;
align-items: center;
gap: 10px;
}
.logo {
width: 32px;
height: 32px;
}
.brand-name {
font-size: 20px;
font-weight: 700;
color: var(--text-dark);
}
/* حاوية flex داخلية: روابط التنقل */
.header-center {
display: flex;
gap: 30px;
}
.header-center a {
color: var(--text-dark);
text-decoration: none;
font-weight: 500;
padding: 8px 0;
position: relative;
}
.header-center a::after {
content: "";
position: absolute;
bottom: 0;
left: 0;
width: 0;
height: 2px;
background: var(--primary);
transition: width 0.3s;
}
.header-center a:hover::after {
width: 100%;
}
/* حاوية flex داخلية: أزرار المصادقة */
.header-right {
display: flex;
align-items: center;
gap: 12px;
}
.btn-login {
padding: 8px 20px;
background: transparent;
border: 1px solid var(--border-light);
border-radius: 6px;
cursor: pointer;
}
.btn-signup {
padding: 8px 20px;
background: var(--primary);
color: white;
border: none;
border-radius: 6px;
cursor: pointer;
}
أمثلة عملية شاملة
مثال 1: تخطيط الكأس المقدسة
تخطيط صفحة كلاسيكي بثلاثة أعمدة
<div class="page-layout">
<header class="page-header">الرأس</header>
<div class="page-body">
<aside class="sidebar-left">الشريط الجانبي الأيسر</aside>
<main class="main-content">المحتوى الرئيسي</main>
<aside class="sidebar-right">الشريط الجانبي الأيمن</aside>
</div>
<footer class="page-footer">التذييل</footer>
</div>
CSS لتخطيط الكأس المقدسة
.page-layout {
display: flex;
flex-direction: column;
min-height: 100vh;
}
.page-header, .page-footer {
padding: 20px;
background: #2c3e50;
color: white;
text-align: center;
}
.page-body {
display: flex;
flex: 1;
}
.sidebar-left {
flex: 0 0 200px;
padding: 20px;
background: #ecf0f1;
}
.main-content {
flex: 1;
padding: 20px;
}
.sidebar-right {
flex: 0 0 250px;
padding: 20px;
background: #ecf0f1;
}
/* متجاوب: تكديس على الهاتف */
@media (max-width: 768px) {
.page-body {
flex-direction: column;
}
.sidebar-left,
.sidebar-right {
flex: none;
}
}
مثال 2: بطاقة تسجيل دخول متمركزة
توسيط مثالي مع Flexbox
.login-page {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 20px;
}
.login-card {
display: flex;
flex-direction: column;
gap: 20px;
width: 100%;
max-width: 400px;
padding: 40px;
background: white;
border-radius: 16px;
box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
}
.login-card h2 {
text-align: center;
margin: 0;
color: var(--text-dark);
}
.login-card input {
padding: 12px 16px;
border: 1px solid var(--border-light);
border-radius: 8px;
font-size: 16px;
}
.login-card button {
padding: 14px;
background: var(--primary);
color: white;
border: none;
border-radius: 8px;
font-size: 16px;
cursor: pointer;
}
.login-card .links {
display: flex;
justify-content: space-between;
font-size: 14px;
}
مثال 3: شبكة ميزات مع التفاف
بطاقات ميزات متجاوبة
.features {
display: flex;
flex-wrap: wrap;
gap: 24px;
padding: 40px 20px;
}
.feature-card {
flex: 1 1 280px;
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
padding: 30px 20px;
background: var(--bg-white);
border-radius: 12px;
border: 1px solid var(--border-light);
transition: transform 0.3s, box-shadow 0.3s;
}
.feature-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
}
.feature-icon {
width: 60px;
height: 60px;
display: flex;
justify-content: center;
align-items: center;
background: var(--primary-light);
border-radius: 50%;
margin-bottom: 16px;
font-size: 28px;
}
.feature-card h3 {
margin: 0 0 10px;
color: var(--text-dark);
}
.feature-card p {
margin: 0;
color: var(--text-light);
line-height: 1.6;
}
مثال 4: تذييل بأقسام متعددة
تخطيط تذييل مرن
.site-footer {
display: flex;
flex-wrap: wrap;
gap: 40px;
padding: 60px 40px 40px;
background: #1a1a2e;
color: #ccc;
}
.footer-section {
flex: 1 1 200px;
}
.footer-section h4 {
color: white;
margin-bottom: 20px;
font-size: 18px;
}
.footer-section ul {
list-style: none;
padding: 0;
margin: 0;
}
.footer-section li {
margin-bottom: 10px;
}
.footer-section a {
color: #999;
text-decoration: none;
transition: color 0.2s;
}
.footer-section a:hover {
color: white;
}
.footer-bottom {
display: flex;
justify-content: space-between;
align-items: center;
flex-wrap: wrap;
gap: 20px;
width: 100%;
padding-top: 30px;
border-top: 1px solid #333;
margin-top: 20px;
}
.social-links {
display: flex;
gap: 15px;
}
@media (max-width: 600px) {
.site-footer {
padding: 40px 20px 20px;
}
.footer-bottom {
justify-content: center;
text-align: center;
}
}
justify-content: space-between على الحاوية الخارجية وحاويات flex متداخلة لمجموعة الأزرار. اجعله متجاوباً: على الهاتف، بدّل إلى flex-direction: column مع عناصر متمركزة ومفهوم قائمة الهامبرغر (يمكنك استخدام تبديل خانة اختيار). تأكد من أن روابط التنقل لها تباعد متساوٍ باستخدام خاصية gap.flex: 1 1 250px). داخل كل بطاقة، استخدم تخطيط عمود flex متداخل لدفع السعر وزر "أضف إلى السلة" إلى الأسفل، بغض النظر عن كمية نص الوصف في البطاقة. استخدم align-items و justify-content لتوسيط صورة المنتج. اختبر بأعداد مختلفة من البطاقات (1، 2، 3، 5، 7) وتأكد من أن التخطيط يبدو جيداً في جميع الحالات.justify-content: space-between للشعار والتنقل. القسم الأوسط يجب أن يستخدم حاوية flex صف مع شريط جانبي بعرض ثابت ومنطقة رئيسية مرنة. التذييل يجب أن يحتوي على أربعة أعمدة تلتف على الشاشات الأصغر. استخدم align-items و justify-content و flex-wrap و flex-direction و gap وحاويات flex متداخلة. اجعل التخطيط بالكامل متجاوباً مع نقطتي توقف على الأقل (جهاز لوحي وهاتف).الملخص
Flexbox هو نظام تخطيط أحادي البعد يوفر أدوات قوية لتوزيع المساحة ومحاذاة العناصر داخل حاوية. بتعيين display: flex أو display: inline-flex، تنشئ حاوية flex يصبح أبناؤها المباشرون عناصر flex. تتحكم خاصية flex-direction في اتجاه المحور الرئيسي (row، row-reverse، column، column-reverse)، و flex-wrap تحدد ما إذا كان يمكن للعناصر أن تلتف إلى أسطر متعددة. اختصار flex-flow يجمع كليهما. توزع خاصية justify-content العناصر على المحور الرئيسي مع خيارات مثل flex-start و flex-end و center و space-between و space-around و space-evenly. تحاذي خاصية align-items العناصر على المحور العرضي مع خيارات تشمل stretch و flex-start و flex-end و center و baseline. تتحكم خاصية align-content في توزيع خطوط flex المتعددة عند تمكين الالتفاف. توفر خاصية gap تباعداً نظيفاً بين العناصر دون تعقيدات الهوامش. بتداخل حاويات flex، يمكنك بناء تخطيطات متطورة مرنة وقابلة للصيانة. فهم خصائص الحاوية هذه هو أساس Flexbox -- في الدرس التالي، سنستكشف خصائص العناصر التي تمنحك مزيداً من التحكم في أبناء flex الفرديين.