إنّ HTML و CSS من أفضل وأسهل الطرق لتقديم المحتوى وأكثرها مرونة. فهي سهلة التعلم وقوية. لكن شيئا واحدا تعجَز فيه هذه اللغات هو الهيكلة المعقدة.، فإذا أردت إنشاء موقع بسيط بهيكلة واضحة فالأمر سهل جدا، ولكن انتقل إلى محتوى متعدد الأعمدة مثلا وشيئا آخر تماما، فهنا تقع نقطة ضعف لغات هيكلة الويب، فيستلزم بنا استخدام طرق ملتوية لإصلاح المشاكل، ناهيك عن توافق هذه الطرق مع مختلف المتصفحات وطريقة ظهورها في كل متصفح.
لمجابهة هذه المشكلة يقدم لنا الإصدار الثالث من CSS مجموعة من الحلول البسيطة والسهلة لهذه المشاكل، وهي كالتالي:
- Multi-column layout Module.
- Grid layout Module.
- Flexbox layout Module.
وسنتكلم نحن اليوم عن Flexbox (المعروف عموما بـFlex) وهو أكثرهم شيوعا وأكثرهم دعما من قبل المتصفحات (لدى كتابة هذا المقال كل المتصفحات تدعم flex إلى جانب الإصدار العاشر من IE)، وما يقوم به Flexbox هو التحكم بهيكلة مجموعة من العناصر التي تقع تحت حاوي واحد، ويسمح لنا بـ:
- صف هذه العناصر في سطر واحد بدون تحديد عرض كل واحد منها (واستخدام float) كما يقوم بإضافة العناصر إلى سطر جديد إن لم تكفي المساحة.
- صّف هذه العناصر على شكل عمود بسهولة كبيرة.
- محاذات العناصر إلى اليمين أو اليسار أو الوسط (بالنسبة للحاوي).
- تغيير الترتيب الذّي تظهر به العناصر بدون التعديل على HTML.
- تحديد المساحة التي يأخذها كل عنصر بدون القلق في حال تغيير حجم الحاوي.
والآن لنتفقد المزيد من المميزات.
مثال بسيط للعمل به
حتى نبدأ باستخدام Flexbox، علينا استخدام مثال بسيط لنشرح به، ومن أجل ذلك اخترنا العمل على هيكلة ذيل صفحة يحتوي على 3 عناصر تجدها في أيّ ذيل صفحة وسنقوم بالتجربة عليها. ما نريد إنجازه هو أن نقوم بصف العناصر الثلاثة بشكل أفقي، وأن نقوم بمحاذاتها عموديا إلى المنتصف وأن يستغل العنصر الأخير ضعف مساحة بقية العناصر، لنقوم بالأمر بالطريقة التقليدية سيتوجب علينا صف العناصر باستخدام float مع تحديد مساحة كل واحدة وحسابها بشكل دقيق حتى يكون هناك ما يكفي من مكان. هذه هي النتيجة النهائية.
البدء باستخدام Flexbox
الشيء الذي يجب أن نفهمه هو أن Flexbox ليس خاصية واحدة بل مجموعة من الخواص المختلفة، ونستعمل Flexbox عبر تطبيق هذه الخواص على الحاوي والبعض الآخر على العناصر التي نريد التحكم بها. ولنبدأ باستخدام Flexbox نقوم بتطبيق الخاصية التالية على الحاوي:
footer { display: flex; }
تستطيع أيضا استخدام خاصية flex-flow التي تسمح لك بأن تحدد هل تريد أن تصف العناصر على شكل صف أفقي (row وهي القيمة الإفتراضية )أو على شكل عمود (column) وهل تريد أن تحشر كل العناصر في سطر واحد (nowrap وهي القيمة الافتراضية) أو أن تضيف سطرا جديدا (أو عمودا جديدا) في حال نفاذ المكان (wrap).
footer { display: flex; flex-flow: row wrap; }
ملاحظة: flex-flow تجمع ما بين الخاصيتين flex-direction (وقيمها هي row , column row-reverse column-reverse) و flex-wrap (قيمها هي wrap no-wrap wrap-reverse).
المحور الرئيسي والمحور الجانبي
Flexbox تعتمد على مبدأ المحاور في العمل، فهي لا تعمل على أساس محور أفقي ومحور عمودي (حيث ستنعكس الأمور إذا صفننا العناصر عموديا عبر flex-direction : column) بل تستخدم محورا رئيسيا أو Main Axis وهو يتبع الإتجاه الذي حددناه في flex-direction بمعنى أنه من بداية الصفحة إلى نهايتها إذا حددنا flex-direction : row أو من أسفل الصفحة إلى أعلاها إذا حددنا flex-direction : column-reverse أما المحور الجانبي فهو يعامد المحور الرئيسي ويجري في نفس اتجاهه، هذه صورة توضح الأمر.
محاذات العناصر
يتيح لنا Flexbox محاذات العناصر بأكثر من طريقة، وعبر المحور الرئيسي والجانبي.
المحاذات في المحور الجانبي
للمحاذات على المحور الجانبي نستخدم خاصية align-items وقيمه هي:
- flex-start/baseline: تقوم بمحاذات أعلى نقطة من كل عنصر عند بداية المحور الجانبي.
- flex-end: تقوم بمحاذات نهاية كل عنصر عند نهاية المحور الجانبي.
- center: تقوم بمحاذات منتصف كل العناصر مع منتصف المحور الجانبي.
- stretch: تقوم بجعل العناصر تتمدد حتى تملأ مساحة كامل المحور الجانبي.
كل هذه القيم واضحة، ولكن إن احتجت فهمها أكثر، جرب التعديل على المثال التالي:
See the Pen jPzGPR by Hsoub Academy (@HsoubAcademy) on CodePen.
بالنسبة لمثالنا فقد قررت استخدام stretch:
footer { display: flex; flex-flow: row wrap; align-items: stretch; }
والآن نحن نملك عناصر تأخذ كامل مساحة الحاوي، مهما كان ارتفاعه ومهما كان محتواها قصيرا أو طويلا، ألم تتمنى لو كنت قادرا على الحصول على أعمدة متساوية الطول سابقا ولجأت إلى حلول غريبة جدا.
ملاحظة: هناك خاصية اسمها align-self تستطيع تطبيقها على العناصر وتملك نفس القيم، وسوف تتخطى أيّ قيمة حددتها في align-items.
المحاذات على المحور الرئيسي
بعد أن شاهدنا طريقة لمحاذات العناصر على المحور الجانبي، سنرى الآن كيف سنقوم بمحاذاتهم على المحور الرئيسي، وذلك يتم عبر خاصية justify-content والتي تحدد كيف يجب أن تتم محاذات العناصر على المحور الرئيسي، أو بالأحرى كيف تم توزيع المساحة الفارغة المتبقية. لا يكون لهذه الخاصية أيّ تأثير إذا كان مجموع أطوال العناصر (بالإضافة إلى margin الخاص بها) يساوي طول العنصر. بالنسبة لمثالنا فطول العناصر يساوي طول الحاوي لذا لا حاجة لها، ولكن سنرى كيف تعمل.
الخاصية تأخذ القيم التالية:
- flex-start: تقوم بصف كامل العناصر في بداية المحور مع ترك المساحة الفارغة في النهاية.
- flex-end: تقوم بصف كامل العناصر في نهاية المحور مع ترك المساحة الفارغة في البداية.
- center: تقوم بصف العناصر في منتصف المحور، مع ترك مساحة متساوية على يمين وعلى يسار العناصر.
- space-between: تقوم بحساب كامل المساحة الفارغة، ثم تقوم بتوزيعها بين العناصر.
- space-around: تقوم أيضا بحساب كامل المساحة الفارغة وتقوم بتوزيعها بين العناصر، ولكن تقوم أيضا بتوزيع المساحة قبل أول عنصر وبعد آخر عنصر.
جرب اللعب بهذا المثال حتى تفهم أكثر:
See the Pen xGWXZE by Hsoub Academy (@HsoubAcademy) on CodePen.
بالنسبة لمثالنا الأول فقد استخدمت التالي:
#first { width: 25%; } #second { width: 40%; } #third { width: 25%; } footer { display: flex; flex-flow: row wrap; align-items: stretch; justify-content: space-around; }
جعل العناصر مرنة
أحد أقوى الخواص في Flexbox هي القدرة على جعل العناصر مرنة بحيث تقوم بإعطائها طولا محددا (عرضا محددا إذا كنت تستخدم flex-flow: row أو ارتفاعا معينا إذا كنت تستخدم flex-flow: column) ليتغير طول العنصر إعتمادا على المساحة الفارغة المتوفرة في الحاوي، يتم هذا عبر خاصية flex التي تأخذ 3 خواص مجتمعة، سنجرب أول خاصية فيها وهي معامل التضخم flex grow factor:
#first { flex: 1; } #second { flex: 1; } #third { flex: 1; }
هذه القيم عديمة الوحدة وهي تحدد كم المساحة التي يأخذها كل عنصر من الحاوي، إذا قمنا بتحديد 1 لكل العناصر، فسيأخذون نفس المساحة، وإذا حدننا لأحدهم 2 فسوف يأخذ ضعف المساحة لبقية العناصر:
#first { flex: 1; } #second { flex: 2; } #third { flex: 1; }
وتستطيع أيضا تحديد قيمة flex-basis لكل واحد هكذا:
#first { flex: 1 200px; } #second { flex: 2 300px; } #third { flex: 1 250px; }
خاصية flex-basis تعني الطول الذي سيأخذه كل عنصر (عرض في حال row و ارتفاع في حال column) ثم، المساحة الفارغة الباقية في الحاوي يتم توزيعها اعتمادا على معامل التضخم grow factor حتى يتم تحديد العرض النهائي للعناصر، ولنضرب مثالا أوضح:
العناصر أطوالها الإبتدائية هي 200 + 300 + 250 وهي 750px وعرض الحاوي هو 950px مما يعني وجود 200px من المساحة الفارغة ليتم توزيعها على العناصر.
أول وثالث عنصر (الذين يملكون flex:1) سيحصلون على 50px إضافية ليصبح حجمهم النهائي 250px و 300px على الترتيب. أما العناصر الثاني (الذي يملك flex:2) فسيحصل على 100px أيّ ضعف بقية العناصر ليكون حجمه النهائي 400px.
مثال آخر، لنقل أن العنصر الثاني كان يملك flex:3. الآن كيف سنعرف ماهي المساحة التي سيكتسبها كل عنصر، حسنا الأمر بسيط سنقوم بحساب مجموع هذه المعاملات (1 + 3 + 1 = 5) ثم نقوم بقسم المساحة المتبقية على المجموع (200px ÷ 5 = 40px) الآن سنضيف للعنصر الأول 40px والعنصر الثالث 40px والعنصر الثاني 3×40px أي 120px.
الخاصية الثالثة والتي نادرا ما تستخدم هي معامل التقلص flex shrink factor:
#first { flex: 1 1 400px; } #second { flex: 2 3 600px; } #third { flex: 1 2 400px; }
معامل التقلص هو أيضا بلا وحدة، ويعمل عكس معامل التضخم، ويكون للقيم تأثير عندما يتجاوز مجموع أطوال العناصر طول الحاوي والهدف منه هو تحديد القيمة التي سيصغر بها كل عنصر، لنضرب مثالا.
لنقل أنّ حجم الحاوي هو 1100px، ومجموع العناصر فوق هو 1400px أي أنهم سيتجاوزون الحاوي بقيمة 300px. معامل التقلص سيحدد القيمة التي ينقص بها كل عنصر الآن، وهي كالتالي:
- العنصر الأول سيفقد 1/6 من المساحة الإضافية أي سيفقد 50px ليصبح طوله 350px.
- العنصر الثاني سيفقد 3/6 من المساحة الإضافية أي سيفقد 150px ليصبح حجمه 450px.
- العنصر الثالث سيفقد 2/6 المساحة الإضافية أي سيفقد 100px ليصبح حجمه 300px.
لذا كلما ارتفعت قيمة معامل التقلص، تقلص العنصر أكثر.
القيم التي نستخدمها في المثال هي كالتالي:
.first { flex: 1 0 7rem; } .second { flex: 2 0 8rem; order: 1; } .third { flex: 1.5 0 7rem; }
ملاحظة: خاصية flex هي اختصار للقيم التالية على الترتيب:
- flex-grow
- flex-shrink
- flex-basis
flex: auto و flex: initial
أحد أكثر قيم flex إفادة هم auto و initial.
flex: auto والتي هي اختصار لـ flex: 1 1 auto تجعل من العنصر مرنا جدا، خصوصا إذا حددت له قيمة لـ min-width فسيتمدد العنصر إن كان هناك مساحة فارغة إضافية، ويتقلص إن لم تكفي المساحة، وإذا أضفت له min-width فسيتقلص إلى تلك القيمة، ثم تقفز بقية العناصر إلى سطر جدي وتتوزع المساحة مجددا. شاهد هذا المثال لترى كيف تتقلص العناصر وتتمد إعتمادا على المساحة المتوفرة (جرب تصغير المتصفح).
أما إذا حددنا القيمة إلى flex: initial (التي هي اختصار ل flex: 0 1 auto فستلاحظ أن العناصر لا تتمدد في حال وجود مساحة فراغة ولكنها تتقلص عند الحاجة.
See the Pen EjEzXy by Hsoub Academy (@HsoubAcademy) on CodePen.
خلاصة
أتمنى أن تكون هذه المقالة واضحة وبسيطة لتشرح مجموعة الخواص الرائعة هذه، Flexbox تسمح لنا بالكثير من "المرونة" في التطوير وتتيح لنا أشياء لم نكن قادريين على القيام بها سابقا.
ترجمة -وبتصرّف- للمقال Flexbox — Fast Track to Layout Nirvana.
أفضل التعليقات
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.