إنشاء نظام شبكي مرن وقوي في CSS


عمر الوريكات

منذ بدء استخدامنا لمفهوم التصميم المتجاوب في سير العمل الخاص بنا، ظهرت العديد من الأدوات كمحاولة لتسهيل عملنا وتسهيل تصميم المواقع المتجاوبة.

grid.thumb.png.0a0b59edbcd8c8482a5578b68

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

وفي هذا المقال سوف أتحدث عن بعض الطرق التي طوّرتها لإنشاء نظام شبكي (grid) مرن وسلس يسمح بالتضمين (nesting) كما يعطيك الحرية الكاملة حول كيفية تصرّف هذا النظام الشبكي في كافة الأبعاد.

كل هذا سوف يتم بمساعدة من مولّد النظام الشبكي المسمى Gridpak.

الأمور التي سوف نتمكن من فعلها

عندما ننتهي من هذا الدرس سوف يكون لدينا نظام شبكي يمكنه فعل بعض مما يظهر في هذه المعاينة.

ويمكن استخدامه في تنظيم تخطيط الصفحات كما في هذه المعاينة.

متطلبات ما قبل البدء

قبل أن نبدأ بمعرفة كيفية إنشاء هذا النظام الشبكي دعونا أولًا نقوم بتحديد ما نتوقعه من هذا النظام.

هذه بعض النقاط التي أرى أنها مهمة عند استعمال أي نظام شبكي:

  • الأعمدة دقيقة ويمكن توقعها لجميع أبعاد الأجهزة.
  • التنسيقات والتوصيف (markup) يجب أن يكون بسيطًا وسهل الاستخدام.
  • لا يعتمد على جهاز معين أو أبعاد معينة وأن يكون مرن بشكل كامل.
  • قابل للتضمين (nestable) لأي عمق.
  • مكون من وحدات (modular) وله سيطرة كاملة على الأعمدة في جميع الأبعاد.
  • يجب أن يعمل من دون الحاجة لـ polyfill في المتصفحات القديمة.

بالنسبة للنقطة الأخيرة، فكثير من المطورين يحبون استعمال respond.js لاستخدام ودعم الـmedia query في المتصفحات القديمة.

الجيد في الأمر أنّ المتصفحات القديمة لا تتطلب أن يتم دعمها في أي جهاز سوى أجهزة سطح المكتب وأجهزة الحاسوب المحمول. لذلك سوف أقوم بتوضيح كيفية تحديد هذه المتصفحات وحفظ طلب http واحد.

التنصيب

1. وسم <html> ودعم تراجعي (fallback) لمتصفح IE

سوف نحتاج في البداية إلى التأكد بأنّنا نستطيع تحديد المتصفحات القديمة وجعل تنسيقات CSS تعمل عليها. هذه الطريقة تم استيحاؤها من html5 boilerplate وتم توضيحها في هذه المقالة.

<!doctype html>

<!--[if IE 8]> <html class="no-js ie8 oldie" lang="en"> <![endif]-->

<!--[if IE 9]> <html class="no-js ie9 oldie" lang="en"> <![endif]-->

<!--[if gt IE 9]><!--> <html class="no-js" lang="en"> <!--<![endif]-->

كل ما تفعله الشيفرة البرمجية في الأعلى هو إضافة فئة (class) إلى وسم <html> بناءً على المتصفح الذي يستخدمه الزائر. في هذا المقال سوف نقوم فقط بدعم متصفحات Internet Explorer بدءًا من الإصدار الثامن.

وبهذا يمكننا أن نقوم بتحديد الإصدارات القديمة من متصفح Internet Explorer بالشكل التالي:

/* target only IE8 with the following class */

.ie8 .my-class { ... }

2. التنسيقات الأساسية ووحدة Rem

إذا كنت لا تستخدم الوحدة rem في تطوير المواقع فإنني أنصحك بالقيام بذلك في أقرب وقت، فهي وحدة رائعة خصوصًا فيما يتعلق بأحجام الخطوط (font sizing). وهذه الوحدة رائعة لأنها وحدة نسبية ولكنها نسبية فقط إلى تعريف واحد وهو التعريف الذي يوضع في وسم <html>. وهذا يعني أنّ جميع الحسابات المعقدة التي تنتج عن استخدام الوحدة em سوف تختفي.

أنظر إلى الشيفرة البرمجية التالية:

html {
    ...
    font-size: 100%;
    ...
}

body {
    ...
    /* base font size: 16px (user agent dependant, but usually 16px) */
    font-size: 1em;
    ...
}

...

.padding {
    /* IE8 fallback */
    padding: 32px;
    padding: 2rem; /* 2 * 16px = 32px */
}

بما أنّ متصفح IE8 لا يدعم وحدة rem فإننا نحتاج إلى استخدام وحدة px أيضًا.

وسوف أريك لاحقًا كيف يمكن أن تساعدنا هذه الوحدة في تسهيل عملنا عند إنشاء الأنظمة الشبكية.

3. الحصول على Gridpak

إذهب إلى موقع gridpak.com وحاول التلاعب بالخيارات حتى تحصل على ما يريحك.

بالنسبة لي سوف أقوم بتحميل نظام شبكي بهذه الخيارات ولكن لك الحرية في اختيار ما تريده:

  • الأبعاد: 480px، 640px، 960px وأعلى.
  • 12 عمود في جميع الأبعاد (12 عمود في الهواتف والأجهزة اللوحية وأجهزة سطح المكتب).
  • padding بقيمة تساوي صفر.
  • تباعد بين الأعمدة بقيمة (24px (24px gutter. يسمح لك Gridpak بأن تقوم بإنشاء gutters محددة لكل بعد من الأبعاد، ولكننا لن نقوم بذلك حتى تبقى الأمور بسيطة.

حاول أن تكون قيم الـpadding والـgutters قيم ناتجة عن حسابات ضرب بسيطة بالنسبة لحجم الخط في الـ body. سوف يساعد هذا على تقليل القيم العشرية لأنّ المتصفحات تتعامل مع القيم العشرية بطريقة مختلفة وحتى نُبقي كل شيء أجمل.

فعلى سبيل المثال لو كان الخط الأساسي هو 16px فإنّ التباعد بين الأعمدة يمكن أن يكون أحد القيم التالية:

  • 8px (وهذه القيمة ناتجة عن ضرب 16 في 0.5).
  • 12px (وهذه القيمة ناتجة عن ضرب 16 في 0.75).
  • 24px (وهذه القيمة ناتجة عن ضرب 16 في 1.5).
  • 32px (وهذه القيمة ناتجة عن ضرب 16 في 2).

بعد أن تقوم بتحديد جميع الخيارات قم بتحميل النظام الشبكي.

4. تفصيل الـ Gridpak

من أفضل خصائص Gridpak هو أنّك سوف تحصل على نظام شبكي دقيق ومتين فقط بعدة سطور من CSS، فقوة Gridpak تأتي من استعمال الخاصية box-sizing: border-box على جميع عناصر الموقع. ففي حالة استعمال border-box فإننا سوف نتمكن من الحصول على عمودين كل واحد منهما بعرض 50% وسوف يبقيان بجانب بعضهما وسوف تتمكن أيضًا من استيعاب أي قيمة border نعطيها له.

ومع تطبيق بعض تنسيقات CSS يمكننا أن نُعطي الـgutters حواف (borders) شفافة مما يمنحنا أعمدة دقيقة ومناسبة:

.row {
    /*
    * Rows contain columns
    *
    * Pull only the left hand side of our rows 24px left (our gutter width)
    * to allow for the border magic that happens in .col below
    */
    margin-left: -24px;
}

.col {
    /*
    * Create a gutter using a transparent border at the specified gutter width.
    * This pushes our content back the distance the row pulled us left, while
    * allowing border-box calculations to be used.
    */
    border: 0px solid rgba(0,0,0,0);
    border-left-width: 24px;
    float: left;
    /*
    * Include the border in the calculation of the column width
    */
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    /*
    * Ensure that backgrounds set on columns begin just inside the border, not underneath
    */
    -webkit-background-clip: padding-box !important;
    -moz-background-clip: padding-box !important;
    background-clip: padding-box !important;
}

وفوق كل هذا فإنّ Gridpak يقوم بوضع كل نظام شبكي لكل بُعد داخل media query خاص به:

/*
* Declare a grid between 0 and 479px only
*/

@media screen and (min-width: 0px) and (max-width: 479px) {
    ...
    .span_1 { width:8.33333333333%;}
    .span_2 { width:16.6666666667%;}
    .span_3 { width:25.0%;}
    .span_4 { width:33.3333333333%;}
    .span_5 { width:41.6666666667%;}
    .span_6 { width:50.0%;}
    .span_7 { width:58.3333333333%;}
    .span_8 { width:66.6666666667%;}
    .span_9 { width:75.0%;}
    .span_10 { width:83.3333333333%;}
    .span_11 { width:91.6666666667%;}
    .span_12 {
        margin-left:0;
        width:100%;
    }
}

/*
* Declare a grid between 480px and 639px only
*/

@media screen and (min-width: 480px) and (max-width: 639px) {
    ...
}

/* etc. */
...

إذا كان علينا أن نحدد عدد مختلف من الأعمدة لكل بُعد عندما نقوم باختيار الخيارات الخاصة بـGridpak (لنقل أنها عمودين للهواتف وأربعة للأجهزة اللوحية و12 لأجهزة سطح المكتب) فإنّ تعريفات media query سوف تمنحنا مرونة وسيطرة أكبر على الأعمدة بدل أن نقوم بجعل الهواتف والأجهزة اللوحية تأخذ عمود واحد فقط كما هو الحال في معظم الأنظمة الشبكية الأخرى.

فعلى سبيل المثال يمكن لفئة (class) واحدة أن تجعل أحد الأعمدة يحتل العرض الكامل لصف ما (row) أو نصف العرض أو حتى سُدُسَ (1/6) العرض وذلك بناءً على بُعد المتصفح.

كل هذا جيد ولكن هناك شيء ما وهو أننا نريد هذه الأعمدة أن تفعل ما أريده في جميع الأبعاد.

5. تطويع Gridpak كما نريد

استعمال وحدة rem لتسهيل عملية الصيانة

دعونا في البداية نقوم بأخذ أساس الـGridpak ونُعطيه إضافة حديثة (مع دعم المتصفحات القديمة):

.row {
    margin-left: -24px;
    margin-left: -1.5rem;
}

/* Reusable column setup */
.col {
    border: 0px solid transparent;
    border-left-width: 24px;
    border-left-width: 1.5rem;
    float: left;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    -webkit-background-clip: padding-box !important;
    -moz-background-clip: padding-box !important;
    background-clip: padding-box !important;
}

إذا أردنا في المستقبل أن نزيل دعم المتصفح IE8 فيمكننا بكل سهولة فعل ذلك عن طريق إزالة القيم ذات الوحدة px (أي أن نُزيل الخاصية margin-left: -24px وborder-left-width: 24px).

تكبير وتتابع النظام الشبكي

نريد أيضًا أن نتأكد بأنّ تخطيط الصفحة لا يصبح سيء عندما يقوم الزائر بتكبير محتوى الموقع. يمكنك قراءة هذا المقال حول استخدام الوحدات المتناسبة مع تعريفات الـmedia query.

بطبيعة الحال فإنّ استخدام وحدة الـpixel في تعريفات الـmedia query لا يبدو وكأنّه يعمل بشكل جيد عندما يقوم الزائر بتكبير المحتوى لذلك سوف نستعمل وحدة em.

زيادة على ذلك، فإنّ الـmedia queries تستخدم حجم الخط الأساسي المُعرّف في المتصفح (user agent font size)، وهذا يعني أننا -وبشكل عام- سوف نستخدم حجم الخط 16px في حساباتنا.

دعونا نتخلّص من استعمال max-width في الـmedia query حتى نستغل قوة التتابع/التعاقب (cascade):

/*
* Declare a grid which will be effective from 0px
*/

@media screen and (min-width: 0) {
    ...
}

/*
* Declare a grid which will be effective from 480px
* 480 / 16 = 30em
*/

@media screen and (min-width: 30em) {
    ...
}

/*
* Declare a grid which will be effective from 640px
* 640 / 16 = 40em
*/

@media screen and (min-width: 40em) {
    ...
}

...

علاوة على إصلاح مشاكل التكبير، فإنّ هذا الأمر يسمح لعرض الأعمدة المُعرّفة داخل أبعاد أكبر بأن تقوم بإلغاء (override) تلك المعرفة لأبعاد أصغر.

تسمية الأعمدة الخاصة ببُعد معين

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

سوف أقوم بإضافة اسم في نهاية كل span لتحديد الأبعاد التي يعمل بها:

/*
* IE8 grid
* This grid will only work in IE8, and at all widths
*/

.ie8 .span_1_ie8 { ... }
.ie8 .span_2_ie8 { ... }
...
.ie8 .span_1_ie8 { ... }

/*
* VIEWPORT ALPHA
* Declare a grid which will be effective from 0px
*/

@media screen and (min-width: 0) {
    ...
    .span_1_vpalpha { ... }
    .span_2_vpalpha { ... }
    ...
    .span_1_vpalpha { ... }
}

/*
* VIEWPORT BETA
* Declare a grid which will be effective from 480px
* 480 / 16 = 30em
*/

@media screen and (min-width: 20em) {
    ...
    .span_1_vpbeta { ... }
    .span_2_vpbeta { ... }
    ...
    .span_1_vpbeta { ... }
}

/*
* VIEWPORT GAMMA
* Declare a grid which will be effective from 640px
* 640 / 16 = 40em
*/

...

لنبدأ الآن باستعمال النظام الشبكي.

استعمال النظام الشبكي

إنّ استعمال Gridpak لهو أمر في غاية السهولة، فجميع الأعمدة يجب أن تكون موجودة داخل عنصر حاوي وهذا العنصر يجب أن يملك فئة clearfix وهذ هو كل ما تحتاج معرفته.

<!--
    create a row with 2 columns and the following features:
    mobile -> 3 spans + 9 spans
    tablet -> 6 spans + 6 spans
    desktop -> 4 spans + 8 spans
    IE8 -> 4 spans + 8 spans
-->

<div class="row cf">
    <div class="col span_3_vpalpha span_6_vpbeta span_4_vpgamma span_4_ie8">
        content...
    </div>

    <div class="col span_9_vpalpha span_6_vpbeta span_8_vpgamma span_8_ie8">
        content...
    </div>
</div>

تضمين الأعمدة يتبع نفس النمط:

<!--
     create a row with 2 columns spanning half the width for all viewports.
     Have both columns then contain 2 columns each, both spanning half the width of the parent column.
-->

<div class="row cf">
    <div class="col span_6_vpalpha span_6_ie8">
        <div class="row cf">
            <div class="col span_6_vpalpha span_6_ie8">
                content...
            </div>
            <div class="col span_6_vpalpha span_6_ie8">
                content...
            </div>
        </div>
    </div>

    <div class="col span_6_vpalpha span_6_ie8">
        <div class="row cf">
            <div class="col span_6_vpalpha span_6_ie8">
                content...
            </div>
            <div class="col span_6_vpalpha span_6_ie8">
                content...
            </div>
        </div>
    </div>
</div>

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

خاتمة

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

ترجمة -وبتصرّف- للمقال Creating Nestable Dynamic Grids لصاحبه Larry Botha.





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


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



يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن