CSS Flexbox: دليل شامل للتخطيط المرن والمحاذاة المتقدمة
دليل تخصصي من علاء عامر – مطور ومصمم مواقع وتطبيقات محترف
Flexbox هو نظام تخطيط قوي يحل مشاكل التخطيط التقليدية. تعلم كيفية إنشاء تخطيطات مرنة ومتجاوبة بسهولة.
1️⃣ مفاهيم Flexbox الأساسية
إنشاء Flex Container
.flex-container {
display: flex; /* تحويل العنصر إلى flex container */
/* أو للعناصر السطرية */
display: inline-flex;
}
/* العناصر الفرعية تصبح flex items تلقائياً */
.flex-item {
/* لا حاجة لتحديد display للعناصر الفرعية */
}
المحاور في Flexbox
.flex-axes-demo {
display: flex;
/* المحور الرئيسي (Main Axis) */
/* - افتراضياً: أفقي من اليمين لليسار */
/* - يمكن تغييره بـ flex-direction */
/* المحور المتقاطع (Cross Axis) */
/* - عمودي على المحور الرئيسي */
/* - عمودي بشكل افتراضي */
}
2️⃣ اتجاه العناصر (Flex Direction)
.direction-examples {
display: flex;
/* الاتجاهات المختلفة */
flex-direction: row; /* أفقي - يمين لليسار (افتراضي) */
flex-direction: row-reverse; /* أفقي معكوس - يسار لليمين */
flex-direction: column; /* عمودي - أعلى لأسفل */
flex-direction: column-reverse; /* عمودي معكوس - أسفل لأعلى */
}
/* تخطيط بطاقات عمودي */
.card-column {
display: flex;
flex-direction: column;
width: 300px;
background: white;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
.card-header {
padding: 20px;
background: #007bff;
color: white;
}
.card-body {
flex: 1; /* يأخذ المساحة المتبقية */
padding: 20px;
}
.card-footer {
padding: 15px 20px;
background: #f8f9fa;
}
3️⃣ التفاف العناصر (Flex Wrap)
.wrap-examples {
display: flex;
/* أنواع التفاف */
flex-wrap: nowrap; /* عدم التفاف (افتراضي) */
flex-wrap: wrap; /* التفاف للسطر التالي */
flex-wrap: wrap-reverse; /* التفاف معكوس */
/* اختصار للاتجاه والتفاف معاً */
flex-flow: row wrap; /* flex-direction + flex-wrap */
flex-flow: column nowrap;
}
/* شبكة متجاوبة باستخدام flex-wrap */
.responsive-grid {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
.grid-item {
flex: 1 1 300px; /* تنمو وتتقلص، بحد أدنى 300px */
min-width: 300px;
padding: 20px;
background: #f8f9fa;
border-radius: 8px;
}
4️⃣ المحاذاة على المحور الرئيسي (Justify Content)
.justify-examples {
display: flex;
/* أنواع المحاذاة الأفقية */
justify-content: flex-start; /* البداية (افتراضي) */
justify-content: flex-end; /* النهاية */
justify-content: center; /* الوسط */
justify-content: space-between; /* مسافات متساوية بين العناصر */
justify-content: space-around; /* مسافات حول العناصر */
justify-content: space-evenly; /* مسافات متساوية تماماً */
}
/* تطبيقات عملية */
.header-nav {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px 20px;
background: white;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.nav-links {
display: flex;
gap: 20px;
list-style: none;
}
.nav-actions {
display: flex;
gap: 10px;
}
/* توسيط المحتوى */
.center-content {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
5️⃣ المحاذاة على المحور المتقاطع (Align Items)
.align-examples {
display: flex;
height: 200px; /* ارتفاع محدد لرؤية التأثير */
/* أنواع المحاذاة العمودية */
align-items: stretch; /* تمدد (افتراضي) */
align-items: flex-start; /* البداية (الأعلى) */
align-items: flex-end; /* النهاية (الأسفل) */
align-items: center; /* الوسط */
align-items: baseline; /* خط القاعدة */
}
/* محاذاة عنصر واحد فقط */
.special-item {
align-self: flex-end; /* يتجاوز إعداد الحاوي */
}
/* تخطيط مرن للبطاقات */
.feature-cards {
display: flex;
gap: 20px;
align-items: stretch; /* جميع البطاقات بنفس الارتفاع */
}
.feature-card {
flex: 1;
padding: 30px 20px;
background: white;
border-radius: 12px;
text-align: center;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
6️⃣ التحكم في العناصر الفردية
Flex Grow, Shrink, Basis
.flex-item-control {
/* نمو العنصر */
flex-grow: 1; /* ينمو ليملأ المساحة المتاحة */
flex-grow: 2; /* ينمو بضعف سرعة العناصر الأخرى */
/* تقلص العنصر */
flex-shrink: 1; /* يتقلص عند الحاجة (افتراضي) */
flex-shrink: 0; /* لا يتقلص أبداً */
/* الحجم الأساسي */
flex-basis: auto; /* حسب المحتوى (افتراضي) */
flex-basis: 200px; /* حجم ثابت */
flex-basis: 30%; /* نسبة من الحاوي */
/* اختصار شامل */
flex: 1; /* flex: 1 1 0% */
flex: 0 0 200px; /* حجم ثابت 200px */
flex: 1 0 auto; /* ينمو فقط، لا يتقلص */
}
/* أمثلة عملية */
.layout-sidebar {
display: flex;
min-height: 100vh;
}
.sidebar {
flex: 0 0 250px; /* عرض ثابت 250px */
background: #f8f9fa;
padding: 20px;
}
.main-content {
flex: 1; /* يأخذ باقي المساحة */
padding: 20px;
}
.aside {
flex: 0 0 200px; /* عرض ثابت 200px */
background: #f8f9fa;
padding: 20px;
}
7️⃣ Gap - المسافات بين العناصر
.gap-examples {
display: flex;
/* مسافة شاملة */
gap: 20px;
/* مسافات مختلفة للصفوف والأعمدة */
row-gap: 15px;
column-gap: 25px;
/* أو استخدام الاختصار */
gap: 15px 25px; /* row-gap column-gap */
}
/* بديل لـ gap في المتصفحات القديمة */
.legacy-spacing {
display: flex;
margin: -10px; /* هامش سالب */
}
.legacy-spacing > * {
margin: 10px; /* هامش موجب لكل عنصر */
}
8️⃣ مشروع عملي: واجهة تطبيق مرنة
<!DOCTYPE html>
<html lang="ar" dir="rtl">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>واجهة تطبيق مرنة</title>
<link rel="stylesheet" href="flexbox-app.css" />
</head>
<body>
<!-- الرأس -->
<header class="app-header">
<div class="logo">
<h1>تطبيقي</h1>
</div>
<nav class="main-nav">
<a href="#" class="nav-link">الرئيسية</a>
<a href="#" class="nav-link">المنتجات</a>
<a href="#" class="nav-link">الخدمات</a>
<a href="#" class="nav-link">تواصل</a>
</nav>
<div class="header-actions">
<button class="search-btn">بحث</button>
<button class="profile-btn">الملف</button>
</div>
</header>
<!-- المحتوى الرئيسي -->
<main class="app-main">
<!-- الشريط الجانبي -->
<aside class="sidebar">
<div class="sidebar-section">
<h3>الفئات</h3>
<ul class="sidebar-menu">
<li><a href="#">تقنية</a></li>
<li><a href="#">تصميم</a></li>
<li><a href="#">تطوير</a></li>
<li><a href="#">تسويق</a></li>
</ul>
</div>
</aside>
<!-- المحتوى -->
<section class="content">
<div class="content-header">
<h2>المحتوى الرئيسي</h2>
<div class="content-actions">
<button class="filter-btn">تصفية</button>
<button class="sort-btn">ترتيب</button>
</div>
</div>
<!-- شبكة البطاقات -->
<div class="cards-grid">
<div class="card">
<div class="card-image">
<div class="placeholder-image">صورة</div>
</div>
<div class="card-content">
<h3>عنوان البطاقة</h3>
<p>وصف قصير للمحتوى</p>
</div>
<div class="card-actions">
<button class="btn-primary">عرض</button>
<button class="btn-secondary">حفظ</button>
</div>
</div>
<!-- تكرار البطاقات -->
<div class="card">
<div class="card-image">
<div class="placeholder-image">صورة</div>
</div>
<div class="card-content">
<h3>عنوان آخر</h3>
<p>وصف مختلف للمحتوى</p>
</div>
<div class="card-actions">
<button class="btn-primary">عرض</button>
<button class="btn-secondary">حفظ</button>
</div>
</div>
</div>
</section>
</main>
<!-- الذيل -->
<footer class="app-footer">
<div class="footer-content">
<div class="footer-section">
<h4>عن الموقع</h4>
<p>معلومات عن التطبيق</p>
</div>
<div class="footer-section">
<h4>روابط مفيدة</h4>
<ul>
<li><a href="#">المساعدة</a></li>
<li><a href="#">الدعم</a></li>
</ul>
</div>
</div>
<div class="footer-bottom">
<p>© 2025 جميع الحقوق محفوظة</p>
</div>
</footer>
</body>
</html>
/* flexbox-app.css */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: "Cairo", Arial, sans-serif;
line-height: 1.6;
color: #333;
background: #f5f5f5;
}
/* الرأس */
.app-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px 20px;
background: white;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
position: sticky;
top: 0;
z-index: 100;
}
.logo h1 {
color: #007bff;
font-size: 1.5rem;
}
.main-nav {
display: flex;
gap: 25px;
}
.nav-link {
text-decoration: none;
color: #333;
font-weight: 500;
transition: color 0.3s ease;
}
.nav-link:hover {
color: #007bff;
}
.header-actions {
display: flex;
gap: 10px;
}
.search-btn,
.profile-btn {
padding: 8px 15px;
border: 1px solid #ddd;
background: white;
border-radius: 6px;
cursor: pointer;
transition: all 0.3s ease;
}
.search-btn:hover,
.profile-btn:hover {
background: #f8f9fa;
}
/* المحتوى الرئيسي */
.app-main {
display: flex;
min-height: calc(100vh - 140px);
gap: 20px;
padding: 20px;
}
/* الشريط الجانبي */
.sidebar {
flex: 0 0 250px;
background: white;
border-radius: 8px;
padding: 20px;
height: fit-content;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.sidebar-section h3 {
margin-bottom: 15px;
color: #333;
font-size: 1.1rem;
}
.sidebar-menu {
list-style: none;
}
.sidebar-menu li {
margin-bottom: 8px;
}
.sidebar-menu a {
text-decoration: none;
color: #666;
display: block;
padding: 8px 12px;
border-radius: 4px;
transition: background 0.3s ease;
}
.sidebar-menu a:hover {
background: #f8f9fa;
color: #007bff;
}
/* المحتوى */
.content {
flex: 1;
background: white;
border-radius: 8px;
padding: 30px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.content-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30px;
padding-bottom: 15px;
border-bottom: 1px solid #eee;
}
.content-actions {
display: flex;
gap: 10px;
}
.filter-btn,
.sort-btn {
padding: 8px 15px;
border: 1px solid #007bff;
background: transparent;
color: #007bff;
border-radius: 6px;
cursor: pointer;
transition: all 0.3s ease;
}
.filter-btn:hover,
.sort-btn:hover {
background: #007bff;
color: white;
}
/* شبكة البطاقات */
.cards-grid {
display: flex;
flex-wrap: wrap;
gap: 20px;
}
.card {
flex: 1 1 300px;
min-width: 300px;
background: #f9f9f9;
border-radius: 12px;
overflow: hidden;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
transition: transform 0.3s ease;
display: flex;
flex-direction: column;
}
.card:hover {
transform: translateY(-5px);
}
.card-image {
height: 200px;
background: #e9ecef;
display: flex;
align-items: center;
justify-content: center;
}
.placeholder-image {
color: #6c757d;
font-weight: 500;
}
.card-content {
flex: 1;
padding: 20px;
}
.card-content h3 {
margin-bottom: 10px;
color: #333;
}
.card-content p {
color: #666;
line-height: 1.5;
}
.card-actions {
display: flex;
justify-content: space-between;
padding: 15px 20px;
background: white;
gap: 10px;
}
.btn-primary,
.btn-secondary {
flex: 1;
padding: 10px;
border: none;
border-radius: 6px;
cursor: pointer;
font-weight: 500;
transition: all 0.3s ease;
}
.btn-primary {
background: #007bff;
color: white;
}
.btn-primary:hover {
background: #0056b3;
}
.btn-secondary {
background: #f8f9fa;
color: #333;
border: 1px solid #ddd;
}
.btn-secondary:hover {
background: #e9ecef;
}
/* الذيل */
.app-footer {
background: #333;
color: white;
margin-top: 40px;
}
.footer-content {
display: flex;
justify-content: space-between;
padding: 40px 20px;
max-width: 1200px;
margin: 0 auto;
}
.footer-section h4 {
margin-bottom: 15px;
color: #007bff;
}
.footer-section ul {
list-style: none;
}
.footer-section li {
margin-bottom: 8px;
}
.footer-section a {
color: #ccc;
text-decoration: none;
transition: color 0.3s ease;
}
.footer-section a:hover {
color: white;
}
.footer-bottom {
text-align: center;
padding: 20px;
border-top: 1px solid #555;
color: #ccc;
}
/* التصميم المتجاوب */
@media (max-width: 768px) {
.app-header {
flex-direction: column;
gap: 15px;
padding: 15px;
}
.main-nav {
order: 3;
width: 100%;
justify-content: center;
}
.app-main {
flex-direction: column;
}
.sidebar {
flex: none;
}
.cards-grid {
flex-direction: column;
}
.card {
min-width: auto;
}
.footer-content {
flex-direction: column;
gap: 30px;
}
}
الخلاصة
في هذا الدرس تعلمنا:
✅ مفاهيم Flexbox الأساسية والمحاور ✅ اتجاه العناصر والتفاف ✅ المحاذاة على المحورين ✅ التحكم في العناصر الفردية ✅ استخدام Gap للمسافات ✅ مشروع عملي شامل
في الدرس القادم سندرس CSS Grid لإتقان التخطيطات الشبكية المعقدة.