الوحدة 2 · تخطيط يصمد
Flexbox بالتفصيل
18 دقراءة 4 دبيئة تجريب الكود
الدرس في لمحة
توقّع كيف يحدّد flexbox أحجام العناصر من flex-basis والنموّ والتقلّص، وعالج فخّ الفيضان الناتج عن min-width: auto، وابنِ صفوفًا تلتفّ دون media queries.
- 1كيف يقرّر flexbox الأحجام
- 2فخّ min-width: auto
- 3الدفع بالـ margins التلقائية
- 4الالتفاف دون media queries
- 5دورك الآن
لا فيديو هنا، بل الشيء الحقيقي: درس مكتوب وأمثلة قابلة للتشغيل واختبار وتدريب.
صف الجلسة في جدول Waypoint ثلاثة أشياء على خط واحد: الوقت والعنوان وزر الحفظ. يبدو جيدًا إلى أن يجدول فريق المحتوى جلسة بعنوان «Shipping Accessible Design Systems Across Twelve Product Teams Without Losing Your Mind»، فينزلق زر الحفظ خارج حافة البطاقة. لا شيء في الـ CSS يذكر أيّ عرض، فمن أين جاء الفيضان؟
جاء من flexbox وهو يفعل بالضبط ما تقوله خوارزميته. وحين تعرف الخوارزمية، يستغرق إصلاح هذا الخطأ ثلاثين ثانية.
كيف يقرّر flexbox الأحجام
يحدّد flexbox أحجام العناصر على امتداد المحور الرئيسي على مرحلتين:
- الحجم المبدئي (hypothetical size). يبدأ كل عنصر من
flex-basisالخاصة به. ومع القيمة الافتراضيةautoيكون هذا هوwidthإن كان مضبوطًا، وإلا فعرض محتواه. - توزيع الفرق. تقارن الحاوية مجموع الأسس (مع الفجوات) بحجمها هي. إن بقيت مساحة، تتقاسمها العناصر التي لها
flex-growبنسبة معاملات نموّها. وإن لم تكفِ المساحة، تتنازل العناصر التي لهاflex-shrinkعن جزء منها، بوزن هو معامل التقلّص مضروبًا في الأساس، فتتقلّص العناصر الكبيرة أكثر.
الاختصار flex يضبط القيم الثلاث معًا، وكلماته المفتاحية تستحق الحفظ لأن سلوكها مختلف جدًا:
| الاختصار | يتوسّع إلى | استخدمه لـ |
|---|---|---|
flex: 1 |
1 1 0% |
أعمدة متساوية أيًّا كان المحتوى |
flex: auto |
1 1 auto |
الحفاظ على حجم المحتوى وتقاسم الفائض فقط |
flex: none |
0 0 auto |
عدم النموّ أو التقلّص أبدًا (الأيقونات والأزرار) |
flex: 0 0 5rem |
أساس ثابت | عمود بعرض محدّد بدقّة |
فخّ min-width: auto
لنعد إلى العنوان الهارب. له white-space: nowrap، فعرض محتواه هو الجملة كاملة، ربما 700px. والصف عرضه 400px. التقلّص يُفترض أن يحلّ المشكلة، فلماذا لا يحلّها؟
لأن عناصر flex تأتي افتراضيًا بـ min-width: auto، وهي تعني في عنصر flex «لا أصغر من حجم محتواي الأدنى (min-content)». والتقلّص يتوقّف عند هذا الحدّ. العنوان غير القابل للكسر لا يستطيع التقلّص تحت عرضه الكامل، فيفيض ويجرّ الزر معه.
.session-row {
display: flex;
align-items: center;
gap: 12px;
}
.session-row .time { flex: 0 0 5rem; }
.session-row .title {
flex: 1;
min-width: 0; /* allow shrinking below content size */
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.session-row .save { flex: none; }min-width: 0 تزيل الحدّ الأدنى، وخصائص الفيضان الثلاث تحوّل النص المقصوص إلى علامة حذف (…) مرتّبة. والفخّ نفسه يظهر مع الروابط الطويلة وكتل الكود وحاويات flex أو grid المتداخلة، لذا هذا إصلاح ستكتبه مرات كثيرة.
الدفع بالـ margins التلقائية
رأس صفحة Waypoint يحمل الشعار ومبدّل الأيام ورابط «Get tickets» الذي مكانه الطرف البعيد. justify-content: space-between ستباعد بين الثلاثة كلها. أما الـ margin التلقائية فأدقّ:
.site-header { display: flex; align-items: center; gap: 1rem; }
.site-header .tickets { margin-inline-start: auto; }الـ margins التلقائية على عناصر flex تبتلع كل المساحة الحرّة في جانبها، فينتقل الرابط إلى النهاية ويبقى كل ما قبله متراصًّا. إنها في flexbox بمثابة نابض يدفع ما بعده إلى الطرف.
الالتفاف دون media queries
شريط الفلاتر يحمل أربعة فلاتر للمسارات. على شاشة عريضة تتّسع في سطر واحد؛ وعلى الهاتف لا ينبغي أن تنضغط إلى شرائح نحيلة لا تُقرأ. الالتفاف مع أساس محدّد يعطيك ذلك دون أيّ breakpoint (نقطة تحوّل):
.filters {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.filters > * {
flex: 1 1 10rem;
}كل فلتر يريد 10rem. يضع المتصفّح في السطر أكبر عدد ممكن من العناصر بعرض 10rem، ويلفّ الباقي، ثم يترك عناصر كل سطر تنمو لتملأه. عند عرض 25rem تحصل على اثنين في كل سطر؛ وعند 45rem على الأربعة. نقطة التحوّل يفرضها المحتوى ضمنيًا.
دورك الآن
يعطيك التمرين صف جلسة عرضه 400px بعنوان طويل جدًا. اجعل الوقت عمودًا ثابتًا بعرض 5rem، ودع العنوان يملأ المساحة المتبقية ويُقتطع بعلامة حذف، وأبقِ زر الحفظ في النهاية. وحين تحتاج صفوف البطاقات إلى الاصطفاف في بُعدين، ينتهي الطريق أمام flexbox؛ وهناك يتسلّم grid المهمة في الدرس التالي.
أهم النقاط
- يحدّد flexbox أحجام العناصر على مرحلتين: يبدأ كل عنصر من
flex-basisالخاصة به، ثم تتقاسم العناصر المساحة المتبقية بحسبflex-grow، أو تستردّflex-shrinkالنقص منها. flex: 1تعني1 1 0%، فتحصل العناصر على حصص متساوية مهما كان محتواها؛ وflex: autoتعني1 1 auto، فيُحفظ حجم المحتوى ولا يُقسَّم إلا الفائض.- عناصر flex تأتي افتراضيًا بـ
min-width: auto، ما يمنعها من التقلّص إلى أقل من محتواها؛ اضبطmin-width: 0ليُقتطع النص بدل أن يفيض. - الـ margin التلقائية (auto) على عنصر flex تبتلع كل المساحة الحرّة في ذلك الجانب، وهي أنظف طريقة لدفع عنصر واحد إلى الطرف البعيد.