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

التنسيق المتقدم لاستمارات الويب


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

نناقش في هذا المقال استخدام لغة CSS في تنسيق بعض عناصر التحكم التي يصعب تنسيقها في استمارة الويب. وكما رأينا في المقال السابق أن معظم العناصر سهلة التنسيق مثل الحقول النصية والأزرار، وبعضها اﻵخر صعب أو يسبب مشاكل أثناء التنسيق مثل صناديق التحقق وبعض أنواع عناصر اﻹدخال.

ولكي نلخص ما ذكرناه سابقًا، فإن هناك نوعين من عناصر التحكم من ناحية التنسيق:

  • صعبة التنسيق: تتطلب قواعد CSS معقدة أو استخدام حيل محددة نذكر من هذه العناصر صناديق التحقق check-boxes و أزرار الاختيار المتعدد radio buttons.
  • غير قابلة للتنسيق الكامل: لا يمكن تنسيقها بشكل كامل باستخدام CSS مثل:
  • حقل اﻹدخال من النوع color.
  • حقل اﻹدخال من النوع datetime.
  • حقل اﻹدخال من النوع range.
  • حقل اﻹدخال من النوع file.
  • عناصر القوائم منسدلة مثل العنصر <select> و <option> و <optgroup>.
  • عناصر أشرطة التقدم مثل <meter> و <progress>.

لهذا، سنتحدث في بداية عن الخاصية appearance التي تساعد في تنسيق تلك العناصر.

الخاصية appearance والتنسيق على مستوى نظام التشغيل

تحدثنا في مقال سابق كيف أن تنسيق عناصر التحكم في الاستمارات يعتمد على نظام التشغيل الذي يستضيف صفحة الويب، وهذا جزء من السبب الذي يجعل تنسيق بعض العناصر صعبًا. لهذا السبب أنشئت الخاصية appearance لتقدم طريقة للتحكم بتنسيق عناصر تحكم الاستمارة، فالقيمة التي ستتعامل معها (وقد لا ترى غيرها) لهذه الخاصية هي القيمة none. حيث تمنع هذه القيمة استخدام التنسيق على مستوى نظام التشغيل قدر اﻹمكان وتسمح ببناء تنسيق مخصص باستخدام CSS.

لنلق نظرة على عناصر التحكم التالية:

<form>
 <p>
    <label for="search">search: </label>
    <input id="search" name="search" type="search" />
 </p>
 <p>
    <label for="text">text: </label>
    <input id="text" name="text" type="text" />
 </p>
 <p>
    <label for="date">date: </label>
    <input id="date" name="date" type="datetime-local" />
 </p>
 <p>
    <label for="radio">radio: </label>
    <input id="radio" name="radio" type="radio" />
 </p>
 <p>
    <label for="checkbox">checkbox: </label>
    <input id="checkbox" name="checkbox" type="checkbox" />
 </p>
 <p><input type="submit" value="submit" /></p>
 <p><input type="button" value="button" /></p>
</form>

إن تطبيق القاعدة التالية سيزيل التنسيق على مستوى نظام التشغيل:

input {
 appearance: none;
}

عند تنفيذ تلك الشيفرة، ستكون لديك النتيجة التالية التي تضم عناصر التحكم التي طُبق عليها تنسيق نظام التشغيل (إلى اليسار) ونفس العناصر بعد تطبيق قاعدة CSS (إلى اليمين):

يكون التأثير في معظم الأحيان إزالة الحواف المنسقة وبالتالي سيسهل هذا قليلًا استخدام CSS، قد لا يبدو لك هذا باﻷمر المهم. لكن سيظهر تأثيره المفيد في حالات استخدام عنصر حقل اﻹدخال search وكذلك عند استخدام صناديق التحقق وأزرار الاختيار المتعدد.

العمل مع صناديق البحث

صندوق البحث هو نوع من أنواع عناصر اﻹدخال يشابه عنصر اﻹدخال النصي، لكن ما فائدة القاعدة appearance: none في هذه الحالة؟ الجواب هو أن متصفح سفاري يطبق بعض القيود على صناديق البحث، فلن تتمكن من تغيير ارتفاعه height أو حجم الخط font-size بحرية. باﻹمكان إصلاح هذا اﻷمر باستخدام القاعدة السابقة التي تعطل المظهر الافتراضي. إليك مثالًا:

input[type="search"] {
 appearance: none;
}

سترى في المثال التالي صندوقي بحث متطابقين من ناحية التنسيق، لكن طبقت على الصندوق اليميني القاعدة appearance: none بينما لم تُطبق على الصندوق اليساري. إن نظرت جيدًا إلى الصندوقين في متصفح سفاري على نظام ماك أو إس macOS، قد تلاحظ أن أبعاد الصندوق اليساري لم تضبط بالشكل الصحيح.

ومن المثير للاهتمام اختفاء مشكلة اﻷبعاد السابقة عند ضبط الحواف أو الخلفية لصندوق البحث. فلم تُطبق القاعدة appearance: none على صندوق البحث في المثال التالي، لكنه لم يعاني من ذات المشكلة عند عرضه في متصفح سفاري!

ملاحظة: لربما لاحظت أن اﻷيقونة x في حقل البحث (التي تظهر عندما يكتسب صندوق البحث تركز الدخل ولم يكن فارغًا) ستختفي عندما يفقد الصندوق تركيز الدخل في متصفحي كروم وإيدج لكنها تبقى في متصفح سفاري. لإزالتها باستخدام CSS بإمكاننا استخدام القاعدة التالية:

input[type="search"]:not(:focus, :active)::-webkit-search-cancel-button {
  display: none;
}

تنسيق صناديق التحقق وأزرار الاختيار من متعدد

إن تنسيق هذه العناصر مربك قليلًا، فلم يؤخذ بالاعتبار إمكانية تغيير أبعاد هذه العناصر وفق تصميمها الافتراضي، وسيختلف سلوك المتصفحات عندما تحاول ذلك. لنلق نظرة على الحالة التالية:

<label
 ><span><input type="checkbox" name="q5" value="true" /></span> True</label
>
<label
 ><span><input type="checkbox" name="q5" value="false" /></span> False</label
>
span {
 display: inline-block;
 background: red;
}

input[type="checkbox"] {
 width: 100px;
 height: 100px;
}

تتعامل المتصفحات مع صندوق التحقق والعنصر <span> بطرق مختلفة وبعضها سيئ المظهر:

المتصفح طريقة التصيير
فايرفوكس 71 (على ماك أو إس) Rounded corners and 1px light grey border
فايرفوكس 57 (ويندوز 10) Rectangular corners with 1px medium grey border
كروم 77 (ماك أو إس)/ سفاري 13، أوبيرا Rounded corner with 1px medium grey border
كروم 63 (ويندوز 10) Rectangular borders with slightly greyish background instead of white.
إيدج 16 (ويندوز 10) Rectangular borders with slightly greyish background instead of white.

استخدام القاعدة appearance: none مع صناديق التحقق وأزرار الاختيار المتعدد

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

<form>
 <fieldset>
    <legend>Fruit preferences</legend>

    <p>
     <label>
      <input type="checkbox" name="fruit" value="cherry" />
      I like cherry
     </label>
    </p>
    <p>
     <label>
      <input type="checkbox" name="fruit" value="banana" disabled />
      I can't like banana
     </label>
    </p>
    <p>
     <label>
      <input type="checkbox" name="fruit" value="strawberry" />
      I like strawberry
     </label>
    </p>
 </fieldset>
</form>

سننسق صناديق التحقق كي تأخذ تصميمًا خاصًا، وسنبدأ بإلغاء التنسيق اﻷصلي:

input[type="checkbox"] {
 appearance: none;
}

نستطيع استخدام الصنفين الزائفين checked: و disabled: لتغيير مظهر صندوق التحقق وتغيير حالته:

input[type="checkbox"] {
 position: relative;
 width: 1em;
 height: 1em;
 border: 1px solid gray;
 /* Adjusts the position of the checkboxes on the text baseline */
 vertical-align: -2px;
 /* Set here so that Windows' High-Contrast Mode can override */
 color: green;
}

input[type="checkbox"]::before {
 content: "✔";
 position: absolute;
 font-size: 1.2em;
 right: -1px;
 top: -0.3em;
 visibility: hidden;
}

input[type="checkbox"]:checked::before {
 /* Use `visibility` instead of `display` to avoid recalculating layout */
 visibility: visible;
}

input[type="checkbox"]:disabled {
 border-color: black;
 background: #ddd;
 color: gray;
}

سنتعرف على الأصناف الزائفة ونقاط أخرى في مقال قادم، لكن ما يفعله الصنفان السابقان هو التالي:

  • checked: تُطبَّق عندما يكون صندوق التحقق أو زر الاختيار المتعدد في حالة التفعيل، أي أنه نقر من قبل المستخدم.
  • disabled: تُطبَّق عندما يكون صندوق التحقق أو زر الاختيار المتعدد في حالة التعطيل، أي لا يمكن للمستخدم التعامل معه.

إليك نتيجة الشيفرة السابقة:

ستجد هنا أيضًا مثالين آخرين لتوضيح الفكرة:

إن حاولت استعراض صناديق التحقق السابقة في متصفح لا يدعم الخاصية appearance لن تشاهد التنسيق الذي خصصته، لكنها ستحافظ على شكل صندوق التحقق وتؤدي نفس الوظيفة.

ما الذي يمكن فعله للعناصر التي لا يمكن تنسيقها باستخدام CSS فقط؟

ما الذي يمكن فعله لتنسيق عناصر لا يمكن تنسيقها بالكامل باستخدام CSS مثل القوائم المنسدلة والعناصر المركبة مثل منتقي الألوان color picker أو عنصر تحديد التاريخ date-time وعناصر مراقبة التقدم progress elements وغيرها؟

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

لنلق نظرة على المثال التالي الذي يعرض عددًا من العناصر صعبة التنسيق في استمارة الويب:

طُبقت قواعد التنسيق التالية على العناصر السابقة:

body {
 font-family: "Josefin Sans", sans-serif;
 margin: 20px auto;
 max-width: 400px;
}

form > div {
 margin-bottom: 20px;
}

select {
 appearance: none;
 width: 100%;
 height: 100%;
}

.select-wrapper {
 position: relative;
}

.select-wrapper::after {
 content: "▼";
 font-size: 1rem;
 top: 3px;
 right: 10px;
 position: absolute;
}

button,
label,
input,
select,
progress,
meter {
 display: block;
 font-family: inherit;
 font-size: 100%;
 margin: 0;
 box-sizing: border-box;
 width: 100%;
 padding: 5px;
 height: 30px;
}

input[type="text"],
input[type="datetime-local"],
input[type="color"],
select {
 box-shadow: inset 1px 1px 3px #ccc;
 border-radius: 5px;
}

label {
 margin-bottom: 5px;
}

button {
 width: 60%;
 margin: 0 auto;
}

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

button,
label,
input,
select,
progress,
meter {
 display: block;
 font-family: inherit;
 font-size: 100%;
 margin: 0;
 box-sizing: border-box;
 width: 100%;
 padding: 5px;
 height: 30px;
}

أضفنا أيضًا بعض الظلال المنتظمة والزوايا الدائرية في العناصر التي يبدو فيها اﻷمر منطقيًا:

input[type="text"],
input[type="datetime-local"],
input[type="color"],
select {
 box-shadow: inset 1px 1px 3px #ccc;
 border-radius: 5px;
}

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

العنصر <select> وقوائم البيانات

تقدم المتصفحات الحديثة تنسيقًا افتراضيًا مقبولًا لقوائم البيانات، ولن تضطر إلى تغيير تنسيقها كثيرًا. وبالنسبة للمظهر الأساسي للصناديق فقد حافظنا عليه مع بعض التغييرات الطفيفة لتبدو منتظمة ومتناسقة، وطالما أن عناصر القوائم هي في الواقع عناصر إدخال نصي <input> (قيمة الخاصية type له تساوي "text") فهي بسيطة التنسيق.

أما ما يجعل اﻷمر صعبًا فهما ناحيتان: اﻷولى هي اختلاف أيقونة السهم في العنصر <select> التي تشير إلى اتجاه انسدال القائمة من متصفح ﻵخر، وقد تتغير هذه اﻷيقونة عند تغيير حجم صندوق الاختيار أو تتغير أبعادها بطريقة سيئة. وﻹصلاح هذه المشكلة استخدمنا بداية الخاصية appearance: none للتخلص من الأيقونة بالمطلق:

select {
 appearance: none;
}

ثم أنشأنا أيقونة مخصصة باستخدام المحتوى المولَّد (باستخدام الخاصية content). ووضعنا عنصر تغليف إضافي حول عنصر التحكم لأن الصنفان after:: و before:: لا يعملان مع العنصر <select>. والسبب في ذلك أن موضع المحتوى المولَّد عن طريق الشيفرة سيكون منسوبًا لصندوق التنسيق الذي يحيط بها، لكن عناصر اﻹدخال تعمل كأنها عناصر مُستبدلة، إذ يقرر المتصفح طريقة عرضها ويضعها في مكانها فهي لا تمتلك صندوق تنسيق:

<label for="select">Select a fruit</label>
<div class="select-wrapper">
 <select id="select" name="select">
    <option>Banana</option>
    <option>Cherry</option>
    <option>Lemon</option>
 </select>
</div>

نستخدم بعدها محتوى مولَّد لتمثيل سهم نحو الأسفل ونضعه في مكانه الصحيح باستخدام خاصية التموضع position:

.select-wrapper {
 position: relative;
}

.select-wrapper::after {
 content: "▼";
 font-size: 1rem;
 top: 6px;
 right: 10px;
 position: absolute;
}

أما الناحية الثانية الأكثر أهمية، هي عدم قدرتنا على التحكم بمظهر الصندوق الذي يضم الخيارات عند النقر على صندوق العنصر <select> لفتحه. وعلى الرغم من وراثة خط الكتابة عن العنصر اﻷب، إلا أنك لن تكون قادرًا على ضبط التباعد بين الحروف أو اللون. وينطبق هذا اﻷمر على قوائم اﻹكمال التلقائي التي تظهر مع العنصر <datalist>.

فإن أردت تحكمًا كاملًا عند تنسيق قوائم الخيارات، عليك استخدام نوع من المكتبات التي تقدم عنصر تحكم مخصص أو أن تبني بنفسك هذا العنصر. أو استخدم في حالة العنصر <select> الخاصية multiple والتي تعرض جميع الخيارات معًا متجنبًا هذه المشكلة بالتحديد:

<label for="select">Select fruits</label>
<select id="select" name="select" multiple></select>

ملاحظة: قد لا يتناسب هذا الحل مع تصميمك لكنه يستحق المحاولة.

تنسيق عنصر التقويم

لجميع أنواع عنصر التقويم المسؤولة عن إدخال التاريخ والوقت مثل (datetime-local و time و week و month) نفس مشكلات التنسيق الرئيسية. فمن الممكن أن تنسق الصندوق الذي يضمها بكل سهولة كأي عنصر إدخال نصي، لكن لا يمكن تنسيق اﻷجزاء الداخلية منها مثل التقويم الذي تعرضه أو زر الزيادة والنقصان إطلاقًا، ولا يمكن إزالتها باستخدام القاعدة appearance: none فإن أردت تحكمًا كاملًا بهذه العناصر لا بد من الاستعانة بمكتبة خارجية تبني لك العنصر أو أن تحاول بناء عنصرك المخصص بنفسك.

ملاحظة: علينا أن نذكر هنا عنصر اﻹدخال العددي <'input type = 'number> الذي يمتلك أيضًا زر لزيادة أو إنقاص القيمة العددية. فقد يعاني أيضًا من نفس المشكلة السابقة. لهذا إن كانت القيمة العددية بسيطة، يمكنك استخدام النوع tel فهو لا يعرض هذا الزر، وله مظهر النوع text ويعرض لوحة مفاتيح رقمية أيضًا.

عنصر إدخال المجالات range

من الصعب تنسيق حقول المجال range، لكن باﻹمكان الاستفادة من اﻷفكار السابقة بإزالة التنسيق الافتراضي كليًا واستبداله بتنسيق مخصص كالتالي:

input[type="range"] {
 appearance: none;
 background: red;
 height: 2px;
 padding: 0;
 outline: 1px solid transparent;
}

مع ذلك، من الصعب جدًا استبدال تنسيق مقبض الجر drag handle، ولا بد من استخدام شيفرة CSS معقدة تتضمن العديد من العناصر غير المعيارية والمخصصة لمتصفحات معينة حتى تستطيع التحكم بتنسيق عنصر المجالات بشكل كامل.

عنصر انتقاء اللون

لا يبدو مظهر هذا العنصر سيئًا في المتصفحات التي تدعمه، إذ تميل معظمها إلى عرض كتلة من اﻷلوان لها طار صغير. يمكنك إزالة الإطار وإبقاء الكتلة اللونية فقط باستخدام قواعد كهذه:

input[type="color"] {
 border: 0;
 padding: 0;
}

أما التحكم الكامل، فيحتاج إلى حل مخصص.

عنصر انتقاء الملفات

لا بأس بمظهر عناصر انتقاء الملفات من النوع file، ومن السهل كما رأينا في مثال سابق أن نجعلها تبدو متناسقة مع بقية أجزاء الصفحة. إذ يرث السطر الذي يعرض الملفات التي تنتقيها العنصر اﻷب إن أردت ذلك، كما تستطيع تنسيق قائمة أسماء الملفات بالطريقة التي تريدها.

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

input[type="file"] {
 height: 0;
 padding: 0;
 opacity: 0;
}

ثم ننسق العنوان المرتبط بالعنصر حتى يبدو وكأنه زر:

label[for="file"] {
 box-shadow: 1px 1px 3px #ccc;
 background: linear-gradient(to bottom, #eee, #ccc);
 border: 1px solid rgb(169, 169, 169);
 border-radius: 5px;
 text-align: center;
 line-height: 1.5;
}

label[for="file"]:hover {
 background: linear-gradient(to bottom, #fff, #ddd);
}

label[for="file"]:active {
 box-shadow: inset 1px 1px 3px #ccc;
}

ستكون نتيجة عرض الشيفرة السابقة كما يلي:

أشرطة التقدم والعدادات

قد يكون العنصران <meter> و <progress> اﻷسوء من ناحية التنسيق. صحيح أننا تمكنا في مثال سابق من ضبط اتساعها بشكل دقيق نسبيًا، لكن خلاف ذلك، من الصعب تنسيقها بأي شكل. إذ لا يمكن مثلًا أن نضمن سلوك المتصفحات فيما يخص ارتفاع هذه العناصر، وعلى الرغم من إمكانية تغيير لون الخلفية، لكن لا يمكن تغيير اللون اﻷمامي، وتطبيق القاعدة appearance: none تزيد اﻷمر سوءًا.

لهذا من اﻷفضل أن تجد حلًا مخصصًا لتتحكم بالمظهر الكامل لهذه العناصر، أو يمكنك استخدام أية حلول تقدمها أطراف خارجية مثل progressbar.js

الخلاصة

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

ترجمة -وبتصرف- للمقال: Advanced form styling

اقرأ أيضًا


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

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

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



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

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

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

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   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.


×
×
  • أضف...