البحث في الموقع
المحتوى عن 'css2'.
-
إنّ إتقان تخطيط صفحات الويب بدون إتقان لغة CSS سيكون كمن يحاول السباحة على أرضٍ جافة، ولكن على عكس السباحة التي عندما تتقنها تبقى معك طول الحياة فإنّه لا يوجد مرحلة يمكنك عندها التوقف عن التعلم وتقول أنّك أتقنت CSS فهذه اللغة تتطور بسرعة يومًا بعد يوم. كما أنّ تعلم وإتقان هذه اللغة سيكون أكثر تحديًا بسبب وجود إختلافات في كيفية تطبيق ودعم هذه اللغة من قبل المتصفحات (حتى بين الإصدارات المختلفة للمتصفح نفسه). ولمدة تناهز العشر سنوات كان مطوّرو الويب يتصارعون ويعانون من الدعم المتشتت وغير المتناسق لخصائص CSS3 في كل إصدار جديد للمتصفحات. ولكن لنتفق على شيء ما وهو أنّ إتقان CSS شيء لا بد منه لأي مطور ويب جيد. وفي هذا المقال سوف نأخذكم في جولة لنتعرف على مبادئ CSS في تخطيط الصفحات وسوف نبدأ من التقنيات التي ظهرت في CSS2 وانتهاءً بآخر ما ظهر في CSS3. ملاحظة: سوف نستخدم HTML5 وSass في هذا المقال. ويمكنك الحصول على الشيفرات البرمجية كاملة من هنا. إحدى حالات الاستخدامإنّ من أفضل الطرق لتعلم أي تقنية هو أن يكون هناك حالة استخدام محددة تحاول دعمها أو أنّك تبحث عن حل لمشكلة ما. وحتى نهاية هذا المقال سنركز على حالة استخدام بمجموعة من المتطلبات. ستكون حالة الاستخدام التي سنعمل عليها عبارة عن تخطيط لتطبيق ويب (Web App) مع بعض السلوكيات المتغيرة/الديناميكية (dynamic)، بحيث سيكون هناك عناصر ثابتة في الصفحة مثل الترويسة (header) والتذييل (footer) وقائمة رئيسية (navigation) وقائمة فرعية (sub-navigation) وقسم محتوى قابل للتمرير(scrollable content). ستكون المتطلبات الخاصة بتخطيط الصفحة كما يلي: التخطيط الأساسي:الترويسة، التذييل، قائمة رئيسية وقائمة فرعية وهذه العناصر ستبقى ثابتة عند التمرير (scroll).سوف تشغل القائمة الرئيسية والقائمة الفرعية أي مساحة عمودية فارغة.سوف يشغل قسم المحتوى المساحة المتبقية في الصفحة وسوف يحتوي على منطقة قابلة للتمرير.السلوكيات المتغيرة/الديناميكية:سوف تحتوي القائمة الرئيسية على أيقونات فقط بشكل افتراضي، ولكن يمكن لها أن تتمدد لتحتوي على بعض النصوص (وأيضًا تتقلص/تنطوي لتظهر الأيقونات فقط مرة أخرى). اختلافات في تخطيط الصفحة:ستحتوي بعض الصفحات على قائمة فرعية بجانب القائمة الرئيسية والبعض الآخر لا. استخدام تقنيات CSS2 هذا هو تخطيط HTML5 الذي سوف نستخدمه: <body class="layout-classic"> <header id="header"></header> <nav id="nav"></nav> <aside id="subnav"></aside> <main id="main"></main> <footer id="footer"></footer> </body> 1. الموضعة الثابتة (position: fixed)في CSS2 يمكنك الحصول على عناصر ثابتة في الصفحة (مثل الترويسة، التذييل...الخ) عن طريق توظيف نموذج تخطيط يَستخدم الموضعة الثابتة (يستخدم position: fixed). سوف نستخدم أيضًا الخاصية z-index لنتأكد بأنّ العناصر الثابتة سوف تظهر فوق جميع العناصر الأخرى في الصفحة، بحيث تقوم هذه الخاصية بتحديد مكان العنصر إمّا أعلى أو أسفل عنصر آخر، فالعناصر التي تحتوي على قيمة z-index كبيرة سوف تظهر فوق العناصر التي تحتوي على قيمة z-index أقل. هناك شيء مهم يجب عليك تذكره وهو أنّ خاصية z-index لن تعمل إلا بوجود خاصية position، أي أنّك إذا استخدمت خاصية z-index على أحد العناصر ولكنك لم تستخدم خاصية position على نفس العنصر فإنّ خاصية z-index لن تعمل. وبالنسبة لنا، فسوف نستخدم القيمة 20 (وهي أعلى من القيمة الافتراضية) حتى نُبقي العناصر الثابتة فوق العناصر الأخرى في الصفحة. وسوف نستخدم خاصية width ونعطيها القيمة 100% وهذا سيسمح للعناصر بالتمدد أفقيًا بالقدر الذي تستطيعه. #header, #footer { position: fixed; width: 100%; z-index: 20; } #header { top: 0; height: 5em; } #footer { bottom: 0; height: 3em; }هذا بالنسبة للترويسة والتذييل، ولكن ماذا بالنسبة للقائمة الرئيسية (nav#) والفرعية (subnav#)؟ 2. تقنية التوسع/التمدد في CSSبالنسبة للقائمة الرئيسية (nav#) والفرعية (subnav#)، سوف نستخدم تقنية تسمى بتقنية التمدد (CSS Expantion) بحيث تُستخدم هذه التقنية على العناصر التي تحتوي على الخاصية position: fixed (بحيث يبقى العنصر ثابت في الصفحة) أو الخاصية position: absolute (بحيث يتم موضعة العنصر بناءً على أقرب عنصر حاوي يحتوي على الخاصية position بقيمة غير القيمة static). يمكن الحصول على تمدد رأسي/عمودي (vertical) باستخدام الخاصيتين top و bottom وإعطائها قيم محددة بحيث يتمدد العنصر عموديًا ليستخدم المساحة العمودية المتبقية وفقًا لتلك القيم، أي أنّ ما نقوم به هو ربط الجزء العلوي للعنصر بمسافة محددة من الجزء العلوي للصفحة وكذلك ربط الجزء السفلي للعنصر بمسافة محددة من الجزء السفلي للصفحة مما سيؤدي إلى تمدد العنصر ليشغل المساحة العمودية بين هاتين النقطتين (العلوية والسفلية). ونفس الأمر ينطبق على التمدد الأفقي بحيث نستخدم الخاصيتين left و right ونعطيها قيم محددة بحيث يتمدد العنصر أفقيًا ليشغل المساحة الأفقية المتبقية وفقًا لتلك القيم. وبالنسبة لنا في هذه الحالة فإننا نريد أن نستخدم التمدد العمودي: #nav, #subnav { position: fixed; top: 6em; /* ترك مسافة فوق الترويسة */ bottom: 4em; /* ترك مسافة تحت التذييلة */ z-index: 20; } #nav { left: 0; width: 5em; } #subnav { left: 6em; /* leave 1em margin to right of nav */ width: 13em; }3. الموضعة الإفتراضية/الساكنة (static)سوف نستخدم الموضعة الساكنة لموضعة منطقة المحتوى القابلة للتمرير، بحيث تظهر العناصر وتتموضع بالترتيب كما تظهر بالتدفق الطبيعي للمستند (كما تظهر في ملف HTML)، وبما أنّ جميع العناصر الأخرى في الصفحة متموضعة بشكل ثابت فإنّ هذا العنصر سيكون هو العنصر الوحيد الذي يظهر وفقًا للتدفق الطبيعي للمستند. ونتيجة لذلك فكل ما نحتاجه لموضعة العنصر بشكل مناسب هو استخدام الخاصية margin حتى لا يحصل تداخل بينه وبين العناصر الأخرى الثابتة (الترويسة، التذييل والقائمتين الرئيسية والفرعية): #main { margin: 6em 0 4em 20em; }وبهذا نكون قد أتممنا متطلبات التخطيط الأساسي باستخدام CSS2 وبقي علينا أن نهتم بأمر المتطلبات الإضافية الخاصة بالسلوكيات المتغيرة/الديناميكية. 4. السلوكيات المتغيرة/الديناميكية باستخدام تقنيات CSS2ذكرنا سابقًا بأنّ القائمة الرئيسية سوف تحتوي على أيقونات فقط بشكل افتراضي، ولكن يمكن لها أن تتمدد لتحتوي على بعض النصوص (وأيضًا تتقلص/تنطوي لتظهر الأيقوانات فقط مرة أخرى). لنبدأ أولًا بإعطاء القائمة الرئيسية عندما تكون متمددة عرضًا (width) بقيمة 5em زيادة على عرضها الرئيسي (أي يصبح عرضها عندما تتمدد 10em)، وسوف نقوم بذلك عن طريق إنشاء class باسم "expanded" بحيث يمكننا ديناميكيًا (باستخدام الجافاسكربت) إضافته أو إزالته من القائمة الرئيسية: #nan { left: 0; width: 5em; &.expanded { /* Sass notation */ width: 10em; } } يمكنك بالأسفل رؤية كود الجافاسكربت (jQuery في حالتنا هذه) الذي سوف نستخدمه لإضافة أو إزالة الـclass الذي يحمل الاسم "expanded" عندما يقوم المستخدم بالنقر على أيقونة القائمة: $('.layout-classic #nav').on('click', 'li.nav-toggle', function() { $('#nav').toggleClass('expanded'); });يمكن الآن للقائمة الرئيسية أن تتمدد أو تتقلص بكل سهولة. ولكن هناك مشكلة صغيرة وهو أنه عندما تتمدد القائمة الرئيسية فإنها سوف تتداخل مع القائمة الفرعية وهو ما لا نريده بكل تأكيد، ولذلك سوف نحتاج إلى تعديل الأمور قليلًا. يمكنك الآن رؤية واحدة من المشاكل/القيود في CSS2، فسوف نحتاج الآن إلى كتابة العديد من الأكواد الخاصة بقيم العناصر المتموضعة بشكل ثابت، ونتيجة لذلك فسوف نحتاج إلى تعريف classes باسم "expanded" إضافية حتى نسمح للعناصر الأخرى بأن تتموضع لاستيعاب القائمة الرئيسية عندما تتمدد، وبذلك سوف نحتاج إلى كتابة المزيد والمزيد من الأكواد الإضافية. #subnav { left: 6em; width: 13em; &.expanded { left: 11em; /* تحريكها لليمين */ } } #main { margin: 6em 0 4em 20; z-index: 10; &.expanded { margin-left: 25em; /* تحريكها لليمين */ } }سوف نحتاج أيضًا إلى إضافة أكواد جافاسكربت إضافية لإضافة أو إزالة الـclass "expanded" لتلك العناصر عندما يقوم المستخدم بالنقر على القائمة الرئيسية. $('.layout-classic #nav').on('click', 'li.nav-toggle', function() { $('#nav, #subnav, #main').toggleClass('expanded'); });سيكون كل شيء أفضل الآن. 5. اختلافات تخطيط الصفحة باستخدام تقنيات CSS2كنا قد ذكرنا مسبقًا بأنّ بعض الصفحات لن تحتوي على قائمة فرعية. ولنكون أكثر دقة فإننا نريد للقائمة الفرعية أن تختفي عندما يضغط المستخدم على أيقونة "المستخدمين" (users) الموجودة في القائمة الرئيسية. سوف نبدأ أولًا بإنشاء class بالاسم "hidden" وفيه الخاصية display: none: hidden { display: none; }كما أننا سنستخدم الجافاسكربت لإخفاء القائمة الفرعية وذلك عن طريق تطبيق الفئة "hidden" على هذه القائمة عندما يقوم المستخدم بالنقر على أيقونة "المستخدمين" (users): $('#nav.fa-user').on('click', function() { $('#subnav').toggleClass('hidden'); });وبهذا يمكن للعناصر أن تختفي عند النقر على أيقونة "المستخدمين" ولكن المساحة التي كانت تحتلها سوف تبقى غير مستخدمة بدلًا من أن تقوم العناصر الأخرى باستخدام تلك المساحة. وحتى نحصل على السلوك المطلوب عندما نقوم بإخفاء القائمة الفرعية فإننا سوف نستخدم المحدد المجاور(adjacent sibling selector) وهو يأتي على شكل إشارة الجمع +. 6. المحدد المجاوريُستخدم المحدد المجاور لتحديد عنصرين واختيار العنصر الثاني الذي يأتي مباشرة بعد العنصر الأول. فعلى سبيل المثال، سيقوم الكود التالي باختيار العنصر الذي يحمل ID بقيمة main والذي يأتي مباشرة بعد العنصر الذي يحمل ID بقيمة subnav: #subnav + #main { margin-left: 20em; }استخدمنا الكود في الأعلى لإعطاء العنصر main# الخاصية margin-left: 20em فقط إذا كان هذا العنصر يأتي مباشرة بعد العنصر subnav#. ولكن عندما يتمدد العنصر nav# (بحيث يتم إضافة الفئة expanded إلى العنصر main# بناءً على الكود الذي كتبناه سابقًا) فإننا نريد للخاصية margin-left أن تحتوي على القيمة 25em. #subnav + #main.expanded { margin-left: 25em; }وأمّا إذا كانت القائمة الفرعية subnav# مخفية فإننا نريد للخاصية margin-left الخاصة بالعنصر main# أن تحتوي على القيمة 6em: #subnav.hidden + #main { margin-left: 6em; }ملاحظة: واحدة من مساوئ استخدام المحدد المجاور هو أن الـDOM سوف يحتوي دائمًا على العنصر subnav# حتى لو كان غير ظاهر في الصفحة. وأخيرًا، إذا كان العنصر subnav# مخفيًا وnav# متمددًا فإننا نريد الخاصية margin-left للعنصر main# بأن تكون بالقيمة 11em: #subnav.hidden + #main.expanded { margin-left: 11em; }خاتمةكل شيء إلى الآن يظهر في مكانه الصحيح من دون الحاجة إلى استخدام أكواد جافاسكربت كثيرة، ولكن يمكنك ملاحظة أن الكود يمكن أن يكون كبيرًا ومعقدًا إذا ما أردنا إضافة المزيد من العناصر إلى الصفحة. لاحظ أيضًا أنّه باستخدام CSS2 سيكون هناك الكثير من الأكواد لموضعة كل شيء في مكانه المناسب. لذلك سوف نقوم في الدرس القادم باستخدام بعض تقنيات CSS3 الجديدة وإعادة تخطيط الصفحة باستخدام تلك التقنيات. ترجمة -وبتصرّف- للمقال CSS Layout Tutorial: From Class+ic Approaches to the Latest Techniques لصاحبه Laureano Martin Arcanio.