مقدمة
دليلنا الشامل لتخطيطات Flexbox في CSS. يشرح هذا الدليل الشامل كل شيء عن Flexbox، مع التركيز على جميع السمات الممكنة للعنصر الرئيسي (حاوية Flex) والعناصر الفرعية (عناصر Flex). كما يتضمن سجلًا، وعروضًا توضيحية، وقوالب، ومخطط دعم المتصفحات.
سياق
تهدف وحدة تخطيط Flexbox (توصية مرشحة من W3C في أكتوبر 2017) إلى توفير طريقة أكثر كفاءة لترتيب ومحاذاة وتوزيع المساحة بين العناصر داخل الحاوية، حتى عندما يكون حجمها غير معروف و/أو ديناميكي (ومن هنا جاءت كلمة "flex").
الفكرة الرئيسية وراء التصميم المرن هي السماح للحاوية بتغيير عرض/ارتفاع (وترتيب) عناصرها لملء المساحة المتاحة على النحو الأمثل (وذلك غالبًا لاستيعاب مجموعة متنوعة من أجهزة العرض وأحجام الشاشات). تعمل الحاوية المرنة على توسيع العناصر لملء المساحة الفارغة المتاحة، أو تقليصها لمنع امتلاءها.
الأهم من ذلك، أن تخطيط Flexbox اتجاهي، على عكس التخطيطات العادية (كتلة محاذية رأسيًا ومضمنة بناءً على تخطيط أفقي). على الرغم من أنها مناسبة للصفحات، إلا أنها تفتقر إلى المرونة (دون تورية) اللازمة لدعم التطبيقات الكبيرة أو المعقدة (خاصةً فيما يتعلق بتغيير الاتجاه، وتغيير الحجم، والتمديد، والتقليص، وما إلى ذلك).
ملاحظة: تخطيط Flexbox مناسب أكثر لمكونات التطبيق والتخطيطات ذات النطاق الصغير، بينما تخطيط Grid مخصص للتخطيطات ذات النطاق الأكبر.
الأساسيات والمصطلحات
بما أن Flexbox وحدة متكاملة وليست ميزة واحدة، فهي تتضمن العديد من العناصر، بما في ذلك مجموعة خصائصها الكاملة. بعضها مُصمم ليتم ضبطه على الحاوية (العنصر الرئيسي، المعروف باسم "الحاوية المرنة")، بينما يُصمم البعض الآخر على العناصر الفرعية (المعروفة باسم "عناصر المرونة").
إذا كان التصميم "العادي" يعتمد على اتجاهي التدفق الكتلي والخطي، فإن التصميم المرن يعتمد على "اتجاهات التدفق المرنة". يُرجى الاطلاع على هذا النموذج من المواصفات، فهو يشرح الفكرة الرئيسية وراء التصميم المرن.
يتم وضع العناصر على طول المحور الرئيسي (من البداية الرئيسية إلى النهاية الرئيسية) أو المحور المتقاطع (من البداية المتقاطعة إلى النهاية المتقاطعة).
- المحور الرئيسي - المحور الرئيسي لحاوية المرونة هو المحور الرئيسي الذي تُوضع عليه العناصر المرنة. انتبه، ليس بالضرورة أن يكون أفقيًا، بل يعتمد على خاصية اتجاه المرونة (انظر أدناه).
- البداية الرئيسية | النهاية الرئيسية – يتم وضع العناصر المرنة داخل الحاوية بدءًا من البداية الرئيسية وحتى النهاية الرئيسية.
- الحجم الأصلي - عرض أو ارتفاع العنصر المرن، أيهما في البعد الأصلي، هو الحجم الأصلي للعنصر. خاصية الحجم الأصلي للعنصر المرن هي إما "العرض" أو "الارتفاع"، أيهما في البعد الأصلي.
- المحور المتقاطع - يُسمى المحور العمودي على المحور الرئيسي بالمحور المتقاطع. ويعتمد اتجاهه على اتجاه المحور الرئيسي.
- بداية متقاطعة | نهاية متقاطعة – يتم ملء خطوط Flex بالعناصر ووضعها في الحاوية بدءًا من جانب بداية متقاطعة للحاوية المرنة والتحرك نحو النهاية المتقاطعة.
- حجم العرض - عرض أو ارتفاع عنصر مرن، أيهما يقع في البعد العرضي، هو حجم العرض للعنصر. خاصية حجم العرض هي أيهما يقع في البعد العرضي، إما "العرض" أو "الارتفاع".
ميزات Flexbox
خصائص للوالدين
(حاوية)
عرض
يُعرّف هذا حاوية مرنة. بناءً على القيمة المُعطاة، سواءً كانت سطرية أو كتلة، يُوفر سياقًا مرنًا لجميع عناصره الفرعية المباشرة.
.container {
display: flex; /* or inline-flex */
}اتجاه مرن
يُنشئ هذا المحور الرئيسي، مما يُحدد اتجاه وضع العناصر المرنة داخل حاوية المرونة. يُعدّ Flexbox (باستثناء التغليف الاختياري) مفهوم تخطيط أحادي الاتجاه. تخيّل أن العناصر المرنة غالبًا ما تكون في صفوف أفقية أو أعمدة رأسية.
.container {
flex-direction: row | row-reverse | column | column-reverse;
}- الصف (افتراضي): من اليسار إلى اليمين (ltr). من اليمين إلى اليسار (rtl).
- صف عكسي: من اليمين إلى اليسار في اتجاه اليسار. من اليسار إلى اليمين في اتجاه اليمين
- العمود: مثل الصف ولكن من الأعلى إلى الأسفل
- العمود العكسي: مثل الصف العكسي ولكن من الأسفل إلى الأعلى
لفافة مرنة
افتراضيًا، جميع العناصر المرنة تُجمع في سطر واحد. يمكنك تغيير ذلك والسماح بإغلاق العناصر باستخدام هذه الخاصية عند الحاجة.
.container {
flex-wrap: nowrap | wrap | wrap-reverse;
}- nowrap (افتراضي): سيتم تغليف جميع عناصر flex على سطر واحد
- التغليف: يتم تغليف العناصر المرنة عبر خطوط متعددة، من الأعلى إلى الأسفل.
- التفاف عكسي: يتم لف العناصر المرنة على خطوط متعددة من الأسفل إلى الأعلى.
فليكس فلو
هذا اختصار لخاصيتي flex-direction وflex-width، اللتين تحددان معًا المحور الرئيسي والمحور المتقاطع لحاوية flex. القيمة الافتراضية هي row nowrap.
.container {
flex-flow: column wrap;
}تبرير المحتوى
يُحدد هذا الخيار المحاذاة على طول المحور الرئيسي. يُساعد هذا الخيار على توزيع المساحة البيضاء الزائدة عندما تكون جميع العناصر المرنة في سطر ما غير مرنة أو مرنة ولكنها وصلت إلى أقصى حجم لها. كما يُتيح هذا الخيار التحكم في محاذاة العناصر عند تجاوزها الحد الأقصى.
.container {
justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly | start | end | left | right ... + safe | unsafe;
}- flex-start (افتراضي): يتم تعبئة العناصر نحو بداية اتجاه flex.
- flex-end: يتم تعبئة العناصر نحو نهاية اتجاه flex.
- البدء: يتم تعبئة العناصر نحو بداية اتجاه وضع الكتابة.
- النهاية: يتم تعبئة العناصر نحو نهاية اتجاه وضع الكتابة.
- يسار: يتم تعبئة العناصر باتجاه الحافة اليسرى للحاوية، ما لم يكن ذلك غير منطقي مع اتجاه المرونة، ثم يعمل مثل البداية.
- يمين: يتم تعبئة العناصر باتجاه الحافة اليمنى للحاوية، ما لم يكن من المنطقي أن نكون مرنين في هذا الاتجاه، عندها يكون بمثابة النهاية.
- المركز: يتم وضع العناصر في المنتصف على طول الخط.
- المسافة بين العناصر: تُوزّع العناصر بالتساوي على الخط. العنصر الأول عند خط البداية، والأخير عند خط النهاية.
- المساحة المحيطة: تُوزّع العناصر بالتساوي في خط مستقيم، مع وجود مساحة متساوية حولها. يُرجى ملاحظة أن المساحات غير متساوية بصريًا، حيث تتساوى جميع العناصر على كلا الجانبين. ستكون للعنصر الأول وحدة مساحة واحدة على حافة الحاوية، ولكن ستكون هناك وحدتا مساحة بينه وبين العنصر التالي، لأن لكل عنصر مسافة خاصة به.
- توزيع متساوٍ للمساحة: يتم توزيع العناصر بطريقة تجعل المسافة بين أي عنصرين (والمسافة إلى الحواف) متساوية.
هناك أيضًا كلمتان رئيسيتان إضافيتان يمكنك ربطهما بهذه القيم: "آمن" و"غير آمن". يضمن استخدام "آمن" أنه مهما كانت طريقة تحديد الموقع، لن تتمكن من إبعاد أي عنصر بعيدًا عن الصفحة (مثلًا، من أعلى الصفحة) بحيث لا يمكن تمرير المحتوى (ما يُعرف بـ"فقدان البيانات").
محاذاة العناصر
يُحدد هذا السلوك الافتراضي لكيفية ترتيب العناصر المرنة على طول المحور المتقاطع في السطر الحالي. يُمكن اعتباره نسخة تسويغ المحتوى للمحور المتقاطع (عموديًا على المحور الرئيسي).
.container {
align-items: stretch | flex-start | flex-end | center | baseline | first baseline | last baseline | start | end | self-start | self-end + ... safe | unsafe;
}- STREtch (افتراضي): قم بالتمديد لملء الحاوية (لا يزال يحترم الحد الأدنى/الحد الأقصى للعرض)
- بداية مرنة / بداية / بداية ذاتية: توضع العناصر في بداية المحور المتقاطع. الفرق بينهما دقيق، ويتعلق بمراعاة قواعد اتجاه المرونة أو قواعد وضع الكتابة.
- flex-end / end / self-end: توضع العناصر في نهاية المحور المتقاطع. الفرق بسيطٌ أيضًا، ويتعلق بمراعاة قواعد اتجاه flex مقابل قواعد وضع الكتابة.
- المركز: توجد العناصر على المحور المتقاطع
- خط الأساس: يتم محاذاة العناصر مثل خطوط الأساس الخاصة بها
محاذاة المحتوى
عندما تكون هناك مساحة إضافية على المحور المتقاطع، يتم محاذاة خطوط الحاوية المرنة بالداخل، على غرار الطريقة التي يقوم بها justify-content بمحاذاة العناصر الفردية على المحور الرئيسي.
.container {
align-content: flex-start | flex-end | center | space-between | space-around | space-evenly | stretch | start | end | baseline | first baseline | last baseline + ... safe | unsafe;
}- عادي (افتراضي): يتم تعبئة العناصر في موضعها الافتراضي كما لو لم يتم تعيين أي قيمة.
- flex-start / start: العناصر المغلفة في بداية الحاوية. يشير flex-start (مع مزيد من الدعم) إلى اتجاه flex بينما يحترم start اتجاه وضع الكتابة.
- flex-end / end: العناصر التي يتم تغليفها في نهاية الحاوية. (مزيد من الدعم) يشير flex-end إلى اتجاه flex بينما يحترم end اتجاه وضع الكتابة.
- المركز: العناصر الموجودة في وسط الحاوية
- المسافة بين العناصر: تُوزّع العناصر بالتساوي. السطر الأول في بداية الحاوية، والسطر الأخير في نهايتها.
- المساحة حول: يتم توزيع العناصر بالتساوي مع توفير مساحة متساوية حول كل سطر.
- المساحة بالتساوي: يتم توزيع العناصر بالتساوي مع وجود مساحة متساوية حولها
- التمدد: يتم تمديد الخطوط لاحتلال المساحة المتبقية.
فجوة، فجوة الصف، فجوة العمود
تتحكم خاصية الفجوة صراحةً بالمسافة بين العناصر المرنة. تنطبق هذه المسافة بين العناصر فقط، وليس على الحواف الخارجية.
.container {
display: flex;
...
gap: 10px;
gap: 10px 20px; /* row-gap column gap */
row-gap: 10px;
column-gap: 20px;
}يمكن اعتبار هذا السلوك بمثابة فجوة ضئيلة، بحيث إذا كانت الفجوة أكبر بطريقة ما (بسبب شيء مثل justify-content: spacing-between; )، فإن هذه الفجوة لن يكون لها تأثير إلا عندما تصبح هذه المساحة أصغر.
لا يقتصر هذا على flexbox، حيث تعمل الفجوات أيضًا في تخطيطات الشبكة والأعمدة المتعددة.
بادئة Flexbox
يتطلب Flexbox بعض بادئات البائع لدعم معظم المتصفحات الممكنة. لا يقتصر هذا على إضافة بادئة البائع إلى السمات فحسب، بل يتضمن أيضًا أسماء وقيمًا مختلفة تمامًا للخصائص. يعود ذلك إلى تغير مواصفات Flexbox بمرور الوقت، مما أدى إلى ظهور إصدارات "قديمة" و"مُحسّنة" و"جديدة".
ربما تكون أفضل طريقة للتعامل مع هذا هي الكتابة باستخدام بناء الجملة الجديد (والنهائي) وتشغيل CSS عبر Autoprefixer، والذي يستخدم المسافات الخلفية بشكل جيد.
بدلاً من ذلك، إليك Sass @mixin للمساعدة في بعض البادئات، والتي ستمنحك أيضًا فكرة عن نوع الأشياء التي يجب القيام بها:
@mixin flexbox() {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
@mixin flex($values) {
-webkit-box-flex: $values;
-moz-box-flex: $values;
-webkit-flex: $values;
-ms-flex: $values;
flex: $values;
}
@mixin order($val) {
-webkit-box-ordinal-group: $val;
-moz-box-ordinal-group: $val;
-ms-flex-order: $val;
-webkit-order: $val;
order: $val;
}
.wrapper {
@include flexbox();
}
.item {
@include flex(1 200px);
@include order(2);
}أمثلة
لنبدأ بمثال بسيط جدًا، لحل مشكلة يومية تقريبًا: التركيز المثالي. الأمر غاية في البساطة عند استخدام Flexbox.
<ul class="navigation">
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Products</a></li>
<li><a href="#">Contact</a></li>
</ul>.parent {
display: flex;
height: 300px; /* Or whatever */
}
.child {
width: 100px; /* Or whatever */
height: 100px; /* Or whatever */
margin: auto; /* Magic! */
}يعود ذلك إلى أن الهامش المُعَيَّن تلقائيًا في حاوية مرنة سيشغل مساحة إضافية. لذا، سيؤدي ضبط الهامش تلقائيًا إلى جعل العنصر متمركزًا تمامًا على كلا المحورين.
لنستخدم الآن بعض الخصائص الإضافية. لنفترض أن لدينا قائمة من ستة عناصر، جميعها ذات أبعاد ثابتة، ولكن يمكن ضبط حجمها تلقائيًا. نريد توزيعها بالتساوي على المحور الأفقي، بحيث يتم ضبط حجم كل شيء بسلاسة عند تغيير حجم المتصفح دون أي طلبات وسائط.
.flex-container {
/* We first create a flex layout context */
display: flex;
/* Then we define the flow direction
and if we allow the items to wrap
* Remember this is the same as:
* flex-direction: row;
* flex-wrap: wrap;
*/
flex-flow: row wrap;
/* Then we define how is distributed the remaining space */
justify-content: space-around;
}تم. كل شيء آخر يتعلق بالتصميم فقط. يظهر أدناه قلم. تأكد من الانتقال إلى CodePen وتغيير حجم النوافذ لترى ما سيحدث.
لنجرب شيئًا آخر. تخيل أن لدينا عنصر تنقل محاذيًا لليمين في أعلى موقعنا الإلكتروني، لكننا نريد وضعه في المنتصف على الشاشات متوسطة الحجم، وعمودًا واحدًا على الأجهزة الصغيرة. الأمر بسيط جدًا.
/* Large */
.navigation {
display: flex;
flex-flow: row wrap;
/* This aligns items to the end line on main-axis */
justify-content: flex-end;
}
/* Medium screens */
@media all and (max-width: 800px) {
.navigation {
/* When on medium sized screens, we center it by evenly distributing empty space around items */
justify-content: space-around;
}
}
/* Small screens */
@media all and (max-width: 500px) {
.navigation {
/* On small screens, we are no longer using row direction but column */
flex-direction: column;
}
}لنجرب شيئًا أفضل من خلال تجربة مرونة العناصر المرنة! ماذا عن تصميم بثلاثة أعمدة يُركّز على الأجهزة المحمولة، مع رأس وتذييل بعرض كامل، بغض النظر عن ترتيب المصدر؟.
<div class="wrapper">
<header class="header">Header</header>
<article class="main">
<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>
</article>
<aside class="aside aside-1">Aside 1</aside>
<aside class="aside aside-2">Aside 2</aside>
<footer class="footer">Footer</footer>
</div>.wrapper {
display: flex;
flex-flow: row wrap;
}
/* We tell all items to be 100% width, via flex-basis */
.wrapper > * {
flex: 1 100%;
}
/* We rely on source order for mobile-first approach
* in this case:
* 1. header
* 2. article
* 3. aside 1
* 4. aside 2
* 5. footer
*/
/* Medium screens */
@media all and (min-width: 600px) {
/* We tell both sidebars to share a row */
.aside { flex: 1 auto; }
}
/* Large screens */
@media all and (min-width: 800px) {
/* We invert order of first sidebar and main
* And tell the main element to take twice as much width as the other two sidebars
*/
.main { flex: 3 0px; }
.aside-1 { order: 1; }
.main { order: 2; }
.aside-2 { order: 3; }
.footer { order: 4; }
}











