اذهب إلى المحتوى

تخطيط الصندوق المرن Flexbox في صفحات الويب


ابراهيم الخضور

الصندوق المرن Flexbox هو أسلوب تخطيط وحيد الاتجاه لترتيب العناصر في صفحة الويب سواء على سطر واحد أو ضمن عمود واحد. إذ تتمتد العناصر لتشغل مساحة أوسع، أو تتقلص لتتلائم مع مساحة أقل. سنتطرق في هذا المقال إلى جميع الأساسيات التي تغطي هذا المفهوم.

عليك قبل البدء في قراءة هذا المقال أن:

  1. تطلع على أساسيات HTML كما شرحناها في سلسلة مقالات مدخل إلى HTML.
  2. تفهم أساسيات عمل CSS.

لماذا نستخدم الصندوق المرن؟

بقيت التخطيطات المعتمدة على خاصيات CSS المتعلقة بتعويم العناصر floats وبتوضعها positioning ولفترة طويلة أكثر التخطيطات موثوقية عبر مختلف المتصفحات، وقد نجح هذا الأمر لكن مع وجود شيء من المحدودية في التنفيذ وشيء من الإحباط أحيانًا. فتخطيطات بسيطة كالتي سنذكرها ستكون إما صعبة التنفيذ أو مستحيلة باستخدام تلك الأدوات وبأسلوب مرن وملائم:

  • توسيط كتلة من المحتوى عموديًا ضمن العنصر الأب.
  • التوزيع المتساوي لاتساع العنصر الأب بين مختلف العناصر الأبناء ضمن حاوية بغض النظر عن مقدار المساحة المتوفرة.
  • ضبط جميع الأعمدة في التخطيط متعدد الأعمدة على نفس الارتفاع إن ضمت كميات مختلفة من المحتوى.

وكما سنرى، يساعدنا تخطيط الصندوق المرن في تنفيذ الكثير من المهام بسهولة أكبر، وإليك التفاصيل.

مثال تمهيدي بسيط

سنمر في هذا المقال بسلسلة من التمارين كي نفهم آلية عمل الصندوق المرن. عليك بداية أن تنسخ ملف التمرين من جيت-هاب إلى جهازك، ثم حمّله ضمن متصفح حديث (كروم أو فايرفوكس) والق نظرة على الشيفرة باستخدام محرر الشيفرة الذي تستخدمه. بإمكان أيضًا الاطلاع على طريقة عمله مباشرة على جيت-هاب.

01 example0 normal flow

ستلاحظ وجود ترويسة <header> تضم عنوانًا من المستوى الأول، وكذلك العنصر <section> الذي يضم ثلاث عناصر <article>. نستخدم هذه الشيفرة في بناء تخطيط معياري مكون من ثلاث أعمدة.

تحديد العناصر التي ينبغي ترتيبها كصناديق مرنة

علينا كبداية اختيار العناصر التي سترتب كصناديق مرنة، ولفعل ذلك ضبطنا الخاصية display للعنصر الأب للعناصر التي تريدها أن تتحول لصناديق مرنة (وهي في حالتنا العناصر <article>) على القيمة flex. وبالطبع فإن العنصر الأب هو <section>.

section {
  display: flex;
}

هكذا يصبح العنصر حاوية مرنة وتصبح العناصر الأبناء عناصر مرنة. وستكون النتيجة شيئًا من هذا القبيل:

02 example0 flex columns

إذًا، منحنا هذا التصريح بمفرده ما نريد، وهذا أمر رائع! إذ عُرض المحتوى ضمن ثلاث أعمدة لها الاتساع ذاته والارتفاع ذاته. والسبب في ذلك أن أن القيمة الافتراضية للعناصر المرنة (العناصر الأبناء ضمن الحاوية المرنة) تحل هذا النوع من المسائل مباشرة.

دعونا نعيد ما حدث حتى يكون كل شيء واضحًا. يعمل العنصر الذي ضبطنا قيمة الخاصية display له على flex كعنصر كتلي من ناحية الطريقة التي يتفاعل فيها مع بقية أجزاء الصفحة، لكن أبناءه قد رُتِّبت كعناصر مرنة. وسنشرح في القسم التالي بتفاصيل أكبر ما يعنيه هذا الكلام. لا حظ أيضًا إمكانية استخدام القاعدة ;display: inline-flex إن أردت توضيع أبناء عنصر معين كعناصر مرنة لكن سيسلك هذا العنصر سلوك العناصر السطرية.

نموذج الصندوق المرن

عندما تتوضع العناصر بصفتها عناصر مرنة فإنها تتوضع وفق محورين:

03 flexbox axes

  • المحور الأساسي main axis: وله الاتجاه الذي تتوضع وفقه العناصر المرنة (أي على شكل سطر عبر الصفحة أو عمود يتجه لأسفل الصفحة) وتُدعى بداية هذا المحور البداية الأساسية main start وتُدعى نهايته بالنهاية الأساسية main end.
  • المحور القاطع cross axis: هو المحور العمودي على اتجاه توضع العناصر المرنة وله بداية القاطع cross start ونهاية القاطع cross end.
  • يُدعى العنصر الذي تُطبق عليه القاعدة display: flex (العنصر <section> في مثالنا) بالحاوية المرنة flex container.
  • تُدعى العناصر الموجودة داخل الحاوية المرنة بالعناصر المرنة (العناصر <article> في مثالنا). تذكر هذه المصطلحات دائمًا، وعد إليها إن اختلط عليك الأمر في الأقسام القادمة.

أعمدة وأسطر

يقدم مخطط الصندوق المرن خاصية تُدعى flex-direction تحدد اتجاه المحور الأساسي (الاتجاه التي تُترتب وفقه عناصر الصندوق المرن). تأخذ هذه الخاصية القيمة row افتراضيًا والتي ترتب العناصر في صف باتجاه انسياب اللغة الافتراضية للمتصفح (من اليمين إلى اليسار في العربية و العكس في الإنجليزية).

حاول أن تضيف التصريح التالي لقاعدة التنسيق الخاصة بالعنصر <section>:

flex-direction: column;

سترى أن هذه القاعة ستعيد العناصر إلى تخطيط العمود الواحد كما كان تقريبًا قبل إضافة أية تنسيقات. احذف هذا التصريح من شيفرة مثالنا قبل المتابعة.

ملاحظة: بإمكانك إيضًا ترتيب العناصر المرنة عكسيًا باستخدام القيمتين row-reverse و column-reverse.

التفاف العناصر

من أحد المشاكل التي تظهر عند استخدام تخطيط ثابت الاتساع أو الإرتفاع هو طفحان العناصر في مرحلة ما خارج الحاوية مما يدمر التخطيط. لنلق نظرة على المثال wrap0.html الموجود على جيت-هاب (انسخ هذا المثال على جهازك إن كنت ترغب في تطبيق الأكواد الواردة في هذا المقال)

04 example1 overflow

لاحظ هنا كيف خرجت الأعمدة الأبناء خارج الحاوية، ولحل هذه المشكلة يمكن أن نستخدم التصريح التالي ضمن قاعدة تنسيق الكتلة الحاوية <section>:

flex-wrap: wrap;

أضف أيضًا التصريح التالي إلى قاعدة تنسيق العناصر <article>:

flex: 200px;

حاول استعراض الشيفرة الآن في المتصفح وسترى أن التخطيط قد تحسّن كثيرًا:

05 example1 wrapped

لدينا الآن عدة أسطر يضم كلًا منها عدة عناصر أبناء مرنة تشغل تمامًا المساحة المتاحة للسطر، وعند حدوث طفحان يُنقل العنصر إلى السطر التالي. واستخدم التصريح flex: 200px في تنسيق العناصر <article> للدلالة إلى أن اتساع كل عنصر يجب أن يكون على الأقل 200 بكسل، وسنناقش هذه الخاصية بالتفصيل لاحقًا. يمكن أن نلاحظ أيضًا أن آخر العناصر الأبناء في السطر الأخير أكثر اتساعًا كي تشغل مساحة السطر بأكمله.

هناك الكثير لنفعله أيضًا! حاول أن تغيّر قيمة الخاصية flex-direction إلى row-reverse وسترى أن تخطيط الأسطر المتعددة بقي كما هو لكن العناصر قد رتّبت بشكل معكوس ابتداءًا من الزاوية الأخرى للمتصفح.

الخاصية المختصرة flex-flow

تجدر الملاحظة هنا أن الخاصيات المختصرة موجودة للخاصيات flex-direction و flex-wrap و flex-flow. إذ يمكنك مثلًا استبدال التصريح:

flex-direction: row;
flex-wrap: wrap;

بالتصريح التالي:

flex-flow: row wrap;

التحديد المرن لأبعاد العناصر المرنة

لنعد الآن إلى مثالنا الأول لنرى كيف يمكننا التحكم بحجم المساحة الفارغة التي يمكن أن يشغلها العنصر المرن بالنسبة إلى بقية العناصر المرنة. شغّل الملف flexbox0.html أو انسخ الملف flexbox1.html إلى جهازك ليكون نقطة الانطلاق إذا قررت تطبيق ما سنفعله.

أضف بداية القاعدة التالية أسفل تصريحات CSS:

article {
  flex: 1;
}

إن القيمة في التصريح السابق هي قيمة نسبية لا وحدة لها تشير إلى حجم الفراغ المتاح لكل عنصر مرن على امتداد المحور الأساسي موازنة مع غيره من العناصر المرنة. في حالتنا منحنا كل عنصر <article> نفس القيمة وهي 1 كي تأخذ جميع العناصر نفس الكمية من الفراغ الإضافي الذي قد يبقى (الذي لا يتسع لعنصر بأكمله) بعد أن تُحتسب قيم بعض الخاصيات مثل الهوامش والحشوات. تشترك جميع العناصر المرنة بهذه النسبة وحتى لو وضعنا القيمة 40000 بدل القيمة 1 فسيكون لها الأثر ذاته.

أضف الآن القاعدة التالية تحت القاعدة السابقة:

article:nth-of-type(3) {
  flex: 2;
}

عند النقر على زر التحديث في المتصفح، سترى أن العنصر <article> الثالث يشغل ضعفي مساحة العنصرين الباقيين. في هذه الحالة سيكون هناك أربع وحدات تناسبية إجمالًا موزعة على الشكل (4=1+1+2). سيشغل أو عنصرين مرنين ما مقداره وحدة من أصل أربعة أي 1/4 من المساحة المتاحة، وسيشغل العنصر الثالث الربعين الآخرين.

بإمكانك أيضًا أن تخصص حدًا أدنى من الحجم لكل عنصر مرن. لترى ذلك، حاول تعديل قواعد تنسيق العنصر <article> كما يلي:

article {
  flex: 1 200px;
}

article:nth-of-type(3) {
  flex: 2 200px;
}

تنص هذه القواعد على أن كل عنصر مرن سيعطى اتساعًا قدره 200 بكسل بداية من المساحة المتوفرة، وبعدها تتقاسم العناصر المساحة الباقية بنفس النسبة. جرّب أن تنقر على زر التحديث في المتصفح وسترى اختلافًا في طريقة تقاسم المساحة الفارغة.

06 flex flow

تتجلى القيمة الحقيقية لتخطيط الصندوق المرن من خلال مرونته وتجاوبه، فإن غيرّت أبعاد المتصفح أو أضفت عنصر <article> جديد سيبقى التخطيط جميلًا.

الخاصية flex المختصرة موازنة بالخاصية المطوّلة

يمكن استخدام الخاصية المختصرة flex لتحديد ثلاث قيم على الأكثر:

  • القيمة النسبية التي ليس لها واحدة وقد ناقشناها في الأعلى. بالإمكان ضبط هذه القيمة بمفردها أيضًا من خلال الخاصية المطولة flex-grow.
  • قيمة نسبية أخرى ليس لها واحدة تعبر عنها الخاصية المطوّلة flex-shrink وتظهر أهميتها عندما يحدث الطفحان في الحاوية المرنة. إذ تحدد هذه القيمة مقدار ما يتقلصه العنصر ليمنع الطفحان. لا تُعد هذه الميزة للصندوق المرن متقدمة ولن نغطيها لاحقًا.
  • القيمة التي تحدد الحد الأدنى لاتساع العنصر المرن والتي ناقشناها سابقًا. بالإمكان أن نضبط هذه القيمة أيضًا باستخدام الخاصية المطوّلة flex-basis.

لا ننصحك باستخدام الصيغ المطوّلة لخاصيات الصندوق المرن إلا في الحالة التي لا مفر من استخدامها (كأن تلغي قاعدة ما حُدِّدت قيمتها سابقًا). إذ سيزيد استخدام هذه الخاصيات من حجم الشيفرة المكتوبة، وقد تغدو مربكة أحيانًا.

المحاذاة الأفقية والعمودية

نستطيع أيضًا استخدام خاصيات الصندوق المرن لمحاذاة العناصر المرنة عبر المحور الأساسي أو القاطع. ولتوضيح ذلك، سنلقي نظرة على المثال flex-align0.html الموجود على جت-هاب (بإمكانك متابعته مباشرة) أيضًا)، وسنحاول تحويل محتواه إلى قائمة من الأزرار المرنة الأنيقة. لاحظ بداية وجود شريط قائمة أفقي يضم عدة أزرار محشورة بجوار بعضها ابتداءً من الزاوية اليمينية العليا.

07 menu bar jammed

جهز نسخة عن هذا الملف على جهازك، ثم أضف الشيفرة التالية إلى أسفل شيفرة CSS:

div {
  display: flex;
  align-items: center;
  justify-content: space-around;
}

08 aligned flx menu bar

انقر على زر "تحديث" في المتصفح وسترى أن الأزرار قد ضبطت لتبدو متمركزة في منتصف القائمة عموديًا وأفقيًا، وقد أنجزنا ذلك باستخدام الخاصيتين التاليتين:

  1. الخاصية align-items: وتتحكم بموضع العناصر المرنة على امتداد المحور القاطع:
  • تأخذ هذه الخاصية القيمة stretch افتراضيًا وتوسّع العناصر المرنة لتشغل المساحة المتاحة للعنصر الأب وفق اتجاه المحور القاطع. فإن لم يكن للعنصر الأب ارتفاع محدد وفق اتجاه المحور القاطع، ستأخذ جميع العناصر الأبناء ارتفاع أطول العناصر المرنة. لهذا كان للأعمدة في مثالنا الأول نفس الارتفاع تلقائيًا.

  • أما القيمة التي استخدمناها في الشيفرة السابقة، ستُبقي الأبعاد الأصلية للعناصر كما هي لكن ستجعلها تتمركز وفق اتجاه المحور القاطع. لهذا تجد الأزرار متمركزة عموديًا في مثالنا الحالي.

  • يمكن للخاصية أن تأخذ قيمًا مثل flex-start و flex-end والتي تحاذي العناصر المرنة إلى بداية ونهاية المحور القاطع.

    بإمكانك إلغاء سلوك الخاصية align-items لعنصر مرن محدد بتطبيق الخاصية align-self عليه. إليك كيف يكون الأمر:

button:first-child {
  align-self: flex-end;
}

09 override aligned flex item

جرب تلك القيم لضبط محاذاة العناصر لترى تأثيرها ثم احذف ما فعلته عندما تنتهي.

  1. الخاصية justify-content: وتتحكم بموضع العناصر المرنة على امتداد المحور الأساسي:
  • تأخذ الخاصية القيمة flex-start افتراضيًا مما يجعل جميع العناصر مرتبة ابتداءً من بداية المحور الأساسي.
  • يمكن أن تأخذ الخاصية القيمة flex-end فترتب حينها العناصر من ناحية النهاية.
  • وترتب العناصر حول مركز الحاوية المرنة إن كانت قيمة هذه الخاصية center.
  • استخدمنا في الشيفرة السابقة القيمة space-around والتي توزّع جميع العناصر المرنة بالتساوي على طول المحور الأساسي مع وجود بعض المساحة الفارغة في كلا الطرفين.
  • هنالك قيمة أخرى للخاصية وهيspace-between وهي مشابهة جدًا للقيمة space-around إلا أنها لا تترك أية مسافات فارغة إضافية في البداية والنهاية.

أهملت الخاصية justify-items في تخطيط الصندوق المرن ولن نشير إليها، لكننا ننصحك بتجريب القيم السابقة للخاصيتين المتعلقتين بمحاذاة العناصر المرنة قبل متابعة القراءة.

ترتيب العناصر المرنة

يمتلك تخطيط الصندوق المرن ميزة تغيير ترتيب العناصر المرنة ضمن التخطيط دون التأثير على الترتيب المصدري. وهذا أمر يستحيل إنجازه باستخدام أساليب التخطيط التقليدي.

إن الشيفرة الموافقة لهذه الميزة بسيطة، حاول أن تضيف الشيفرة التالية إلى شيفرة مثال شريط الأزرار:

button:first-child {
  order: 1;
}

انقر على زر التحديث في المتصفح وسترى أن الزر "Smile" قد انتقل إلى نهاية المحور الأساسي، وسنشرح قليلًا كيف حدث هذا:

  • تأخذ الخاصية order القيمة 0 لجميع العناصر المرنة افتراضيًا.
  • ستظهر جميع العناصر ذات القيمة الأعلى لهذه الخاصية في النهاية موازنة بالعناصر التي تحمل قيمة أقل.
  • تحافظ العناصر التي تحمل نفسة القيمة للخاصية order على ترتيب الشيفرة المصدرية. فإن كان لدينا مثلًا أربعة عناصر تحمل القيم 0،1،1،2 على الترتيب سيكون ترتيب عرضها على الشاشة الرابع ثم الثاني والثالث ثم الأول.
  • سيظهر العنصر الثالث بعد الثاني على الرغم من امتلاكهما نفس قيمة الخاصية order إلا أن الثاني جاء قبل الثالث في ترتيب الشيفرة المصدرية.

يمكن للخاصية أن تأخذ قيمًا سالبة كي تعرض العناصر التي تحمل هذه القيم قبل العنصر الذي يحمل القيمة 0. يمكننا مثلًا عرض الزر "Blush" في مثالنا في بداية المحور الأساسي باستخدام قاعدة التنسيق التالية:

button:last-child {
  order: -1;
}

صناديق مرنة متداخلة

بإمكانك إنشاء بعض التخطيطات الجميلة والمعقدة باستخدام الصناديق المرنة. فمن الممكن جدًا أن أجعل عنصرًا مرنًا حاويةً مرنةً أيضًا وأن يكون بعض أبناءه أيضًا حاويات مرنة وهكذا. ألق نظرة الآن على المثال complex-flexbox.html على جت-هاب (بإمكانك متابعة التنفيذ المباشر له أيضًا).

10 nested flex boxes

إن شيفرة HTML لهذا المثال بسيطة، إذ تحتوي الشيفرة على العنصر <section> وضمنه ثلاثة عناصر <article> يحوي آخرها ثلاث عناصر <div> ويضم أول العناصر <div> خمسة أزرار.

section - article
          article
          article - div - button
                    div   button
                    div   button
                          button
                          button

لنلق نظرة على الشيفرة المستخدمة لتخطيط الصفحة، وسنرى أن أول ما فعلناه هو ضبط العناصر الأبناء للعنصر <section> لتكون صناديق مرنة.

section {
  display: flex;
}

ثم ضبطنا بعض القيم المرنة للعناصر. وانتبه جيدًا إلى القاعدة الثانية في شيفرة التنسيق والتي جعلت العناصر الأبناء للعنصر <article> الثالث عناصر مرنة أيضًا لكننا رتبناها على هيئة عمود.

article {
  flex: 1 200px;
}

article:nth-of-type(3) {
  flex: 3 200px;
  display: flex;
  flex-flow: column;
}

نختار تاليًا أول العناصر <div> ونطبق عليه التنسيق ;flex: 1 100px كي نعطيه ارتفاعًا مقداره 100 بكسل كحد أدنى، ثم نرتب العناصر الأبناء له على شكل عناصر مرنة. سنختار أن تتوضع الأزرار ضمن سطر وتكون قابلة للالتفاف والانتقال إلى سطر آخر في حال الطفحان كما اخترنا أن نعطيها محاذاة إلى مركز العنصر الأب كما فعلنا مع مثال قائمة الأزرار سابقًا:

article:nth-of-type(3) div:first-child {
  flex: 1 100px;
  display: flex;
  flex-flow: row wrap;
  align-items: center;
  justify-content: space-around;
}

حاولنا في الخطوة الأخيرة تحديد حجم الأزرار باستخدام القاعدة ;flex: 1 auto. ولهذه القاعدة تأثير مهم، فإن حاولت أن تغير حجم نافذة المتصفح، ستشغل الأزرار أوسع مساحة ممكنة من الحيز المتاح وتبقى في السطر ذاته ما لم يحدث طفحان لتنتقل عندها إلى سطر آخر.

button {
  flex: 1 auto;
  margin: 5px;
  font-size: 18px;
  line-height: 1.5;
}

توافقية المتصفحات مع تخطيط الصندوق المرن

تدعم معظم المتصفحات الحديثة تخطيط الصندوق المرن مثل فايرفوكس وكروم وأوبرا ومايكروسوفت إيدج وإكسبلورر 11 والنسخ الجديدة من نظامي التشغيل أندرويد وأي أو إس. لكن عليك أن تدرك أن البعض يستخدم متصفحات قديمة لا تدعم هذا التخطيط (أو تفعل لكن بأسلوب قديم حقًا).

وطالما أنك لا تزال في مرحلة التعلم والتجريب، لا تكترث للأمر كثيرًا. فإن قررت أن تستخدم تخطيط الصندوق المرن في تصميم موقعك، لا بأس إذًا من اختبار شيفرتك وتجريب بعض الحلول حتى تبقى تجربة مستخدمي موقعك مقبولة بأكبر عدد ممكن من المتصفحات.

ويبقى تخطيط الصندوق المرن مربكًا موازنة من بعض ميزات CSS. فإن لم يدعم المتصفح مثلًا الظل حول العنصر فلن تتأثر تجربة المستخدمين كثيرًا لكن إن لم يدعم تخطيط الصنوق المرن فسيكسر المتصفح التخطيط بأكمله ولن يستطيع الزائر استخدام الصفحة أصلًا.

الخلاصة

حاولنا في هذا المقال الإشارة إلى أساسيات الصندوق المرن، ونتمنى أن تكون المعلومات التي وصلتك مفيدة وتساعدك في خطواتك التالية في رحلة التعلم.

ترجمة -وبتصرف- للمقال: Flexbox

اقرأ أيضًا


تفاعل الأعضاء

أفضل التعليقات

لا توجد أية تعليقات بعد



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...