قبل بضع سنوات، جلست لأقوم ببناء لوحة تحكم (dashboard). لم يكن شيئاً معقداً—مجرد شريط جانبي ثابت، ومنطقة محتوى رئيسية، وتذييل. بدا Flexbox الخيار البديهي، وفي البداية، كان يعمل بشكل جيد. ثم أضفت صفاً من البطاقات (cards) إلى القسم الرئيسي. انهار التخطيط بالكامل. قضيت الساعات الثلاث التالية في صراع مع نسب flex-grow وعروض النسب المئوية المتداخلة، وأنا أشاهد الحاويات ترفض الاصطفاف مهما حاولت تقليل الـ padding. شعرت وكأن الصفحة برج على وشك الانهيار.

علمتني تلك التجربة القاسية أهم شيء بخصوص تخطيط CSS الحديث: Flexbox و Grid ليسا متنافسين. إنهما أداتان لوظائف مختلفة، ومعظم التخطيطات الفاشلة تأتي من استخدام الأداة الخاطئة.

الفرق يكمن في الأبعاد

فكر في Flexbox كممر. تتدفق العناصر في اتجاه واحد، إما كصف (row) أو كعمود (column). لقد صُمم للتوزيع أحادي البعد. ينظر المتصفح إلى المحتوى، ثم يقرر كيفية تمديده أو تقليصه أو محاذاته على طول ذلك المحور الوحيد. وهذا يجعل Flexbox مثالياً للحالات التي يملي فيها المحتوى التخطيط. فشريط التنقل، أو مجموعة من حقول النموذج، أو مجموعة من الوسوم (tags) التي تحتاج إلى مسافات متساوية، كلها تستقر بشكل طبيعي داخل حاوية flex لأنها تشترك في منطق خط واحد.

أما Grid، فهو مخطط أرضية. إنه ثنائي الأبعاد تماماً، حيث يتعامل مع الصفوف والأعمدة في نفس الوقت. أنت تحدد الهيكل أولاً، ثم تضع العناصر بداخله. وهذا يجعل Grid مثالياً لهيكلية الصفحة العامة—في أي مكان تحتاج فيه إلى التحكم في التموضع العمودي والأفقي معاً. عندما تحاول فرض تصميم معقد ثنائي الأبعاد من خلال حاويات Flexbox متداخلة، ينتهي بك الأمر بترميز (markup) عميق، وأغلفة هشة، وحسابات رياضية غير مستقرة تنهار بمجرد إضافة عنصر إضافي واحد.

Flexbox لا يزال يستحق مكانه

لا تتسرع في استبدال كل حاوية flex بـ Grid. فداخل المكونات الفردية، غالباً ما يكون Flexbox أكثر نظافة ووضوحاً. إذا كان لديك تذييل بطاقة (card footer) يحتوي على زرين وتريد محاذاة أحدهما إلى اليسار والآخر إلى اليمين، فإن justify-content: space-between يفعل ما تقصده تماماً. وإذا كنت بحاجة إلى توسيط أيقونة عمودياً داخل زر مجهول الارتفاع، فإن align-items: center هو المسار الأبسط. المحتوى المتغير—مثل صف من شارات المستخدمين (user badges) بأطوال أسماء مختلفة—يناسب Flexbox تماماً لأنه يعتمد على المحتوى أولاً. تتكيف الحاوية مع ما تحتويه.

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

تخطيط الصفحة ملك لـ Grid

هنا يأتي دور Grid. هل تتذكر كابوس لوحة التحكم الخاص بي؟ إليك كيف كان يجب أن يبدو الهيكل منذ البداية:

.page {
  display: grid;
  min-height: 100vh;
  grid-template-rows: auto 1fr auto;
  grid-template-columns: 200px 1fr;
}

.header { grid-row: 1; grid-column: 1 / -1; }
.sidebar { grid-row: 2; grid-column: 1; }
.main { grid-row: 2; grid-column: 2; }
.footer { grid-row: 3; grid-column: 1 / -1; }

انظر إلى ما يحدث. تنشئ حاوية .page ثلاثة صفوف وعمودين. يأخذ الصف الأول حجمه بناءً على ما يحتويه الرأس (header) بفضل auto. ويستحوذ الصف الأوسط على كل المساحة المتبقية المتاحة باستخدام 1fr. ويستقر التذييل (footer) في الصف الأخير، بحجم يتناسب مع محتواه. وفي الوقت نفسه، يتم تثبيت عرض الشريط الجانبي (sidebar) عند 200 بكسل، بينما تملأ المنطقة الرئيسية الباقي.

منطق التموضع هو الراحة الحقيقية. يمتد الرأس (header) من خط العمود 1 إلى الخط -1، مما يعني أنه يتمدد عبر كلا العمودين بغض النظر عن عدد الأعمدة التي تضيفها لاحقاً. يتشارك الشريط الجانبي والمحتوى الرئيسي الصف 2 ولكنهما يشغلان أعمدة منفصلة. يعود التذييل إلى العرض الكامل في الصف 3. لست بحاجة إلى حسابات النسب المئوية على العناصر التابعة. لست بحاجة إلى أغلفة متداخلة تتصارع على الارتفاع. قم بتغيير عرض الشريط الجانبي في مكان واحد، وستتعدل المنطقة الرئيسية تلقائياً. يتنفس التخطيط بالكامل كنظام واحد.

سهولة القراءة باستخدام grid-template-areas

لمزيد من الوضوح، يمكنك تسمية أقسامك. بدلاً من إدارة أرقام الخطوط، يمكنك كتابة خريطة مرئية:

.page {
  grid-template-areas:
    "header header"
    "sidebar main"
    "footer footer";
}

.header { grid-area: header; }
.main { grid-area: main; }

الآن تبدو ورقة الأنماط (stylesheet) الخاصة بك وكأنها مخطط هيكلي (wireframe). إذا أردت في أي وقت أن يظهر الشريط الجانبي على اليمين لنقطة كسر (breakpoint) مختلفة، فكل ما عليك فعله هو تبديل كلمتين في سلسلة القالب (template string). هذا النوع من سهولة القراءة الهيكلية مستحيل تحقيقه داخل برج من حاويات flex المتداخلة.

درسان قاسيان

Grid ليس سحراً. هناك خطآن قد يدمران تخطيطك بسرعة.

الأول هو الاستخدام غير المنضبط للوحدات. إذا قمت بتعريف grid-template-columns: 1fr 1fr 1fr بينما يحتاج تصميمك إلى عمودين فقط من المحتوى، فإن ذلك المسار الثالث سيظل موجوداً. فإما أن يظل فارغاً ويخلق فجوة لم تكن تتوقعها، أو سيجبر محتواك الفعلي على الانضغاط بطرق تخل بتصميمك. كن دقيقاً في اختياراتك؛ فعندما تقصد عمودين، اكتب repeat(2, 1fr).