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

استخدام اﻷصناف الزائفة pseudo-classes في تنسيق واجهة المستخدم


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

تعرفنا في مقال سابق على طريقة تنسيق استمارات الويب بشكل متقدم واستعرضنا أمثلة على بعض الحالات التي نستخدم فيها أصناف التنسيق الزائفة pseudo-classes مثل checked: لاستهداف صندوق التحقق في الحالة التي يكون فيها مفعّلًا. وسنتابع في هذا المقال التعرف أكثر على هذه اﻷصناف الزائفة واستخداماتها في تنسيق استمارات الويب.

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

ما هي اﻷصناف الزائفة المتاحة؟

إليك قائمة باﻷصناف الزائفة اﻷصلية التي تتعلق بالاستمارات كما قدمتها CSS 2.1:

  • الصنف الزائف hover: يختار العنصر عندما يتحرك مؤشر الفأرة فوقه.
  • الصنف الزائف focus: يختار العنصر عندما يكتسب تركيز الدخل (عندما تنتقل إليه عبر الضغط على الزر Tab).
  • الصنف الزائف active: يختار العنصر عندما يُفعّل -بالنقر عليه مثلًا- أو عند الضغط على الزر Enter.

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

  • يستخدم الصنفان required:   و optional: في استهداف عناصر HTML التي تمتلك الخاصية required والتي تحدد ما إذا كان هذا العنصر مطلوبًا أم اختياريًا.

  • تستخدم الأصناف valid: و invalid: و in-range: و out-of-range: لاستهداف عناصر الاستمارة ذات القيمة الصالحة أو غير الصالحة وفقًا لقيود التحقق من القيمة وكذلك إن كانت ضمن المجال المطلوب أو خارجه.

  • تستهدف الأصناف enabled: و disabled: و read-only: و write-only: العناصر التي يمكن تعطيلها وتفعيلها (تمتلك الخاصية disabled)، وتلك التي تسمح بالقراءة فقط أو الكتابة فقط (تمتلك الخاصية readonly).

  • تستهدف الأصناف checked: و indeterminate: و default: بالترتيب صناديق التحقق وأزرار الاختيار المتعدد المفعّلة والعناصر في الحالة العائمة indeterminate (ليست مفعلة أو غير مفعلة)، والعنصر المختار افتراضيًا عند تحميل الصفحة مثل صندوق تحقق مفعل افتراضيًا أو عنصر استخدمت فيه الخاصية selected.

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

ملاحظة: نستخدم عددًا من اﻷصناف الزائفة السابقة لتنسيق عناصر تحكم استمارة ويب وفقًا لصلاحية قيمها (قيمتها صالحة أو لا) وهذا ما سنراه في مقال لاحق، لذلك سنبقي اﻷمور بسيطة قدر اﻹمكان فيما يخص أمور التحقق من الصلاحية.

تنسيق عناصر اﻹدخال في حال كانت مطلوبة أم لا

من أهم اﻷساسيات التي تتعلق بالتحقق من صحة المدخلات في طرف العميل تحديد إن كان عنصر إدخال ما ضروريًا (يجب إدخال قيمته قبل إرسال الاستمارة) أم اختياريًا.

ولبعض العناصر مثل <input> و <textarea> الخاصية required التي تشير عند ضبطها إلى ضرورة إدخال قيمة لهذا العنصر، وإلا ستُخفق عملية إرسال الاستمارة. إليك مثالًا:

<form>
 <fieldset>
    <legend>Feedback form</legend>
    <div>
     <label for="fname">First name: </label>
     <input id="fname" name="fname" type="text" required />
    </div>
    <div>
     <label for="lname">Last name: </label>
     <input id="lname" name="lname" type="text" required />
    </div>
    <div>
     <label for="email">
      Email address (include if you want a response):
     </label>
     <input id="email" name="email" type="email" />
    </div>
    <div><button>Submit</button></div>
 </fieldset>
</form>

نجد في هذه الاستمارة أن الاسم الأول واﻷخير مطلوبان، لكن البريد اﻹلكتروني اختياري. ويمكنك استهداف الحالتين السابقتين باستخدام الصنفين required: و optional:. فلو طبقنا مثلًا قواعد CSS التالية:

input:required {
 border: 1px solid black;
}

input:optional {
 border: 1px solid silver;
}

سيكون للحقول المطلوبة حواف أو إطار أسود اللون، وستكون حواف العنصر غير المطلوب رمادية اللون:

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

وعلى الرغم من أن اﻷسلوب السابق ليس سيئًا كبداية، لكن اﻹشارة إلى أن عنصر اﻹدخال مطلوب عن طريق اللون فقط أمر لا يكفي في حالات عدة منها أن يكون المستخدم مريضًا بعمى اﻷلوان، إضافة إلى وجود عرف يقضي بتعليم العنصر المطلوب بإشارة * أو ربط الكلمة "مطلوب required" بالعنصر. لهذا السبب، سنلقي نظرة في القسم التالي على أمثلة أفضل عن استخدام الصنف required: وكذلك استخدام المحتوى المولَّد.

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

ملاحظة: إن كان لأحد أزرار الاختيار المتعدد في مجموعة أزرار لها نفس الاسم الخاصية required فلن تتمكن من إرسال الاستمارة ما لم يجري اختيار أحد أزرار المجموعة، لكن التنسيق باستخدام required:سيطبق فقط على الزر الذي يمتلك تلك الخاصية.

استخدام المحتوى المولَّد generated content مع الأصناف الزائفة

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

تكمن الفكرة في إمكانية استخدام العنصرين الزائفين after:: و before:: مع الخاصية content ﻹظهار محتوى قبل أو بعد العنصر المستهدف. لن يضاف المحتوى الجديد إلى شجرة DOM وسيكون بالتالي مخفيًا عن قارئات الشاشة. وطالما أن المحتوى الجديد هو عنصر زائف، سنتمكن من تنسيقه بنفس اﻷسلوب الذي نستهدف فيه عنصرًا من DOM وننسقه.

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

input[type="radio"]::before {
 display: block;
 content: " ";
 width: 10px;
 height: 10px;
 border-radius: 6px;
 background-color: red;
 font-size: 1.2em;
 transform: translate(3px, 3px) scale(0);
 transform-origin: center;
 transition: all 0.3s ease-in;
}

input[type="radio"]:checked::before {
 transform: translate(3px, 3px) scale(1);
 transition: all 0.3s cubic-bezier(0.25, 0.25, 0.56, 2);
}

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

وبالعودة إلى مثالنا السابق الذي ينسق العناصر المطلوبة، سنستخدم في هذه النسخة محتوىً مولّدًا ﻹضافة مؤشر إلى ضرورة هذا العنصر.

نضيف بداية مقطعًا إلى بداية الاستمارة يوضح ما نريد فعله:

<p>Required fields are labeled with "required".</p>

ستنطق قارئات الشاشة الكلمة "required مطلوب" عندما يصل المستخدم إلى كل حق مطلوب، بينما سيرى المستخدمون الأصحاء عناونًا يوضح ذلك.

وطالما أن عناصر اﻹدخال لا تدعم المحتوى المولّد (لأنها تسلك سلوك عناصر مستبدلة replaced elements، بينما يوضع المحتوى المولّد قبل أو بعد العنصر الذي يمتلك صندوق تنسيق فقط)، سنضيف عنصر <span> فارغ ليضم هذا المحتوى:

<div>
 <label for="fname">First name: </label>
 <input id="fname" name="fname" type="text" required />
 <span></span>
</div>

أما المشكلة التي ستظهر هنا هو انتقال هذا العنصر إلى سطر جديد ﻹن كل من العنوان وعنصر اﻹدخال قد ضبطا ليشغلا كامل الاتساع width: 100%. لهذا ننسق العنصر اﻷب <div> ليصبح حاوية مرنة، وننسقه أيضًا أن ينقل المحتوى إلى سطر جديد إن كان طويلًا جدًا:

fieldset > div {
 margin-bottom: 20px;
 display: flex;
 flex-flow: row wrap;
}

يظهر تأثير هذا التنسيق بأن يكون العنوان وعنصر اﻹدخال ضمن سطرين منفصلين لأن كلاهما يمتد ليشمل كامل الاتساع المتاح له width:100%، وطالما أن للعنصر <span> له الاتساع 0، سيقع على نفس سطر عنصر اﻹدخال. علينا اﻵن توليد المحتوى باستخدام CSS ووضعه بعد العنصر <span> الذي يأتي بعد عنصر إدخال مطلوب:

input + span {
 position: relative;
}

input:required + span::after {
 font-size: 0.7rem;
 position: absolute;
 content: "required";
 color: white;
 background-color: black;
 padding: 5px 10px;
 top: -26px;
 left: -70px;
}

ضبطنا موقع العنصر <span> ليكون نسبيًا position: relative كي نتمكن من توليد محتوى توضُّعه مطلق position: absolute يمكن ضبط موقعه بالنسبة إلى العنصر <span> (وضعه نسبي) وليس بالنسبة إلى العنصر <body> (إذ يعمل المحتوى المولد وكأنه أبن للعنصر الذي يولّد عليه وذلك لتوضيعه بالشكل المناسب).

بعدها حددنا المحتوى المطلوب وهو العبارة "required مطلوب"، وكانت النتيجة كالتالي:

تنسيق عنصر التحكم وفقًا لصلاحية القيمة المدخلة

من المعايير اﻷساسية المهمة أيضًا في عملية التحقق من الاستمارات هو صحة القيم المدخلة (في حالة القيم العددية أو ضمن مجال محدد أو خارجه). أي يمكن استهداف عناصر تحكم النموذج التي لها قيم محدودة وفقًا لصلاحية هذه القيمة أو لا.

الصنفان valid: و invalid:

لاستخدام هذين الصنفين مع عناصر تحكم الاستمارة لا بد أن تتذكر أن:

  • تُعد العناصر التي لا حدود لقيمتها، صالحة دائمًا، ويستهدفها الصنف valid:.
  • تُعد العناصر المطلوبة required الفارغة التي لا تضم قيمًا غير صالحة، وسوف يستهدفها الصنفان invalid: و required:.
  • تُعد العناصر التي تتحقق من القيم المدخلة إليها وفق نمط محدد مثل عناصر إدخال البريد اﻹلكتروني أو عنوان URL غير صالحة إن لم تتطابق البيانات المدخلة مع نمط التحقق الخاص بالعنصر لكنها صالحة عندما تكون فارغة.
  • تُعد العناصر التي تتجاوز قيمتها المجال المحدد بقيمتي الخاصيتين min و max غير صالحة كما يستهدفها أيضًا الصنف out-of-range:.
  • سنتعرف لاحقًا على طرق أخرى لجعل العنصر مستهدفًا من قبل الصنفين valid: و invalid: لكننا سنُبقي اﻷمر بسيطًا في هذا المقال.

لنلق نظرة اﻵن على مثال يستخدم الصنفين الزائفين السابقين. وكما فعلنا في المثال السابق نستخدم عنصر <span> إضافي لتوليد المحتوى الذي يُستخدم للإشارة إن كان المحتوى صالحًا أم لا:

<div>
 <label for="fname">First name: </label>
 <input id="fname" name="fname" type="text" required />
 <span></span>
</div>

نستخدم شيفرة CSS التالية لعرض هذه المؤشرات:

input + span {
 position: relative;
}

input + span::before {
 position: absolute;
 right: -20px;
 top: 5px;
}

input:invalid {
 border: 2px solid red;
}

input:invalid + span::before {
 content: "✖";
 color: red;
}

input:valid + span::before {
 content: "✓";
 color: green;
}

ضبطنا موقع العنصر <span> ليكون نسبيًا position: relative كي نتمكن من توليد محتوى توضُّعه مطلق position: absolute بالنسبة للعنصر السابق. سيكون المحتوى إشارة أو ﻹظهار حالة طارئة يجدر متابعتها، كما أظهرنا إطارًا أحمر سميك ﻹظهار أن البيانات المدخلة غير صحيحة.

ملاحظة: استخدمنا before: ﻹضافة هذه العناوين كما استخدمنا after: لوضع العنوان "required مطلوب".

لاحظ كيف تكون عناصر اﻹدخال المطلوبة غير صالحة عندما تكون فارغة لكنها صالحة عندما ندخل فيها شيئًا ما. أما البريد اﻹلكتروني فهو صالح طالما أنه فارغ ويصبح غير صالح عندما لا تدخل عنوان بريد إلكتروني صحيح.

بيانات داخل وخارج مجال محدد

يستهدف الصنفان in-range: و out-of-range: عناصر اﻹدخال العددية التي تقبل قيمًا ضمن مجال محدد تضبطه الخاصيتين min و max وذلك إن كانت القيمة المدخلة ضمن هذا المجال أو خارجه.

ملاحظة: عناصر اﻹدخال العددية هي العناصر date و month و week و time و datetime-local و number و range.

من الجدير ملاحظة أن القيم التي تقع ضمن المجال تستهدف من قبل الصنف valid: وإن كانت خارج المجال ستسهدف من قبل الصنف invalid:. هذا اﻷمر تحديدًا من الأمور الدلالية التي نهتم فيها بمدلول استخدام الصنف. فالصنف out-of-range: هو نوع ذو دلالة خاصة من أنواع عدم الصلاحية invalidation، فمن اﻷفضل في هذه الحالات إبلاغ المستخدم أنه أدخل قيمة خارج المجال بدلًا من أن تقول له أن القيمة غير صالحة وحسب، وقد ترغب في اﻹشارة إلى الحالتين معًا.

لنلق نظرة على مثالنا عن القيم خارج المجال والذي بني على أساس المثال السابق لعرض رسالة خارج المجال للمدخلات العددية واﻹشارة إلى أن هذه القيمة مطلوبة أو لا.

<div>
 <label for="age">Age (must be 12+): </label>
 <input id="age" name="age" type="number" min="12" max="120" required />
 <span></span>
</div>

وستبدو تنسيقات CSS كالتالي:

input + span {
 position: relative;
}

input + span::after {
 font-size: 0.7rem;
 position: absolute;
 padding: 5px 10px;
 top: -26px;
}

input:required + span::after {
 color: white;
 background-color: black;
 content: "Required";
 left: -70px;
}

input:out-of-range + span::after {
 color: white;
 background-color: red;
 width: 155px;
 content: "Outside allowable value range";
 left: -182px;
}

نطبق هنا ما فعلناه سابقًا مع مثال required: مع اختلاف واحد هو أننا فصلنا هنا التصريحات التي تُطبق على أي محتوى مولّد بعد العنصر after:: ضمن قاعدة خاصة، وأعطينا كل من الحالتين required: و out-of-range: محتوىً وتنسيقًا خاصًا بها:

فمن الممكن أن يكون الرقم المدخل مطلوبًا وخارج المجال في الوقت ذاته، فما الذي سيحدث عندها؟ طالما أن القاعدة out-of-range: تظهر بعد required: في الشيفرة المصدرية، ووفقًا لقواعد CSS، ستستخدم أولًا وتظهر رسالة out-of-range.

يعمل هذا التنسيق جيدًا في الواقع. فعندما تحمل الصفحة للمرة الأولى ستظهر رسالة "required مطلوب" مع إشارة وحواف حمراء لعنصر اﻹدخال، وعندما تدخل رقمًا ضمن المجال المسموح (12-120) تصبح القيم المدخلة صالحة، وإلا ستظهر الرسالة "Outside allowable value range خارج المجال المسموح" بدلًا من "required".

ملاحظة: عليك النقر على عنصر التحكم وكتابة الرقم ضمنه لتجرب ما ذكرناه، ولن يسمح لك زر الزيادة واﻹنقاص الذي يظهر بتجاوز الحدود المسموحة.

تنسيق عناصر اﻹدخال المعطلّة والمفعلة وعناصر القراءة فقط والكتابة فقط

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

يمكن استهداف العناصر وفقًا لتفعيلها من حلال الصنفين الزائفين enabled: و disabled:، لكن لماذا قد نستهدف عنصرًا معطلّا؟ إن لم تكن بيانات محددة ضرورية لبعض المستخدمين، فلن ترغب بإرسالها إلى الخادم عند إرسال الاستمارة. من اﻷمثلة على هذه الحالة استمارة شحن البضائع فقد يطلب منك وضع عنوان الدفع وعنوان وجهة البضاعة، وعندما يكون العنوان نفسه في الحالتين، عندها يمكن تعطيل حقل عنوان الدفع مثلًا.

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

<form>
 <fieldset id="shipping">
    <legend>Shipping address</legend>
    <div>
     <label for="name1">Name: </label>
     <input id="name1" name="name1" type="text" required />
    </div>
    <div>
     <label for="address1">Address: </label>
     <input id="address1" name="address1" type="text" required />
    </div>
    <div>
     <label for="pcode1">Zip/postal code: </label>
     <input id="pcode1" name="pcode1" type="text" required />
    </div>
 </fieldset>
 <fieldset id="billing">
    <legend>Billing address</legend>
    <div>
     <label for="billing-checkbox">Same as shipping address:</label>
     <input type="checkbox" id="billing-checkbox" checked />
    </div>
    <div>
     <label for="name" class="billing-label disabled-label">Name: </label>
     <input id="name" name="name" type="text" disabled required />
    </div>
    <div>
     <label for="address2" class="billing-label disabled-label">
      Address:
     </label>
     <input id="address2" name="address2" type="text" disabled required />
    </div>
    <div>
     <label for="pcode2" class="billing-label disabled-label">
      Zip/postal code:
     </label>
     <input id="pcode2" name="pcode2" type="text" disabled required />
    </div>
 </fieldset>

 <div><button>Submit</button></div>
</form>

أما الجزء المتعلق بموضوعنا في شيفرة CSS هو التالي:

input[type="text"]:disabled {
 background: #eee;
 border: 1px solid #ccc;
}

.disabled-label {
 color: #aaa;
}

اخترنا مباشرة عناصر اﻹدخال النصي المعطلة باستخدام input[type="text"]:disabled، لكننا نريد أيضًا إظهار العناوين المرتبطة بها بلون رمادي. وطالما أن استهدافها ليس سهلًا، استخدمنا صنفًا يطبق عليها disabled-label. كي تُستهدف.

استخدمنا أخيرًا جافا سكريبت للتنقل بين حالتي التعطيل والتفعيل لحقول عنوان الدفع:

// انتظر حتى تنهي الصفحة تحميلها
document.addEventListener(
 "DOMContentLoaded",
 () => {
    // إلى صندوق التحقق `change` إضافة مترصد الحدث
    document
     .getElementById("billing-checkbox")
     .addEventListener("change", toggleBilling);
 },
 false,
);

function toggleBilling() {
 // اختيار حقول عنوان الدفع
 const billingItems = document.querySelectorAll('#billing input[type="text"]');
 // اختيار العناوين المرتبطة بحقول عنوان الدفع
 const billingLabels = document.querySelectorAll(".billing-label");

 // تغيير حالة التعطيل والتفعيل للحقول والعناوين
 for (let i = 0; i < billingItems.length; i++) {
    billingItems[i].disabled = !billingItems[i].disabled;

    if (
     billingLabels[i].getAttribute("class") === "billing-label disabled-label"
    ) {
     billingLabels[i].setAttribute("class", "billing-label");
    } else {
     billingLabels[i].setAttribute("class", "billing-label disabled-label");
    }
 }
}

تستخدم شيفرة جافا سكريبت مترصد للحدث change كي نسمح للمستخدم تعطيل أو تفعيل حقول عنوان الدفع وتغيير التنسيق العناوين المرتبطة بها في كل حالة.

استخدام الصنفين read-only: و read-write:

يستخدم الصنفان السابقان لاستهداف عناصر اﻹدخال وفقًا ﻹمكانية الكتابة والقراءة. فعناصر اﻹدخال المخصصة للقراءة فقط، سترسل محتواها إلى الخادم لكن المستخدم لن يتمكن من تعديلها. بينما يمكن للمستخدم تعديل محتوى العنصر في العناصر القابلة للقراءة والكتابة معًا.

يمكن ضبط عنصر اﻹدخال ليكون مخصصًا للقراءة فقط باستخدام الخاصية readonly. وكمثال على ذلك، نفترض أن المطور قد صمم صفحة للتحقق من صحة جميع البيانات المدخلة. حيث تُنقل إليها جميع البيانات التي قدمها المستخدم حتى يتحقق منها دفعة واحدة ويؤكد الطلب قبل إرسالها إلى الخادم دفعة واحدة.

لنلق نظرة اﻵن على الشكل التي قد تكون عليه الاستمارة، إليك جزءًا من شيفرة HTML يوضح استخدام الخاصية readonly:

<div>
 <label for="name">Name: </label>
 <input id="name" name="name" type="text" value="Mr Soft" readonly />
</div>

إن جربت المثال مباشرة قد تلاحظ أن عناصر الاستمارة العليا لا يمكن أن تتلقى تركيز الدخل، مع ذلك تُرسل قيمها عند تسليم النموذج. كما نسقنا النموذج بالاعتماد على الصنفين read-only: و read-write:

input:read-only,
textarea:read-only {
 border: 0;
 box-shadow: none;
 background-color: white;
}

textarea:read-write {
 box-shadow: inset 1px 1px 3px #ccc;
 border-radius: 5px;
}

يبدو المثال بشكله المكتمل كالتالي:

ملاحظة: قد لا تستخدم الصنفين enabled: و read-write: إلا نادرًا كون الحالتين الموافقتين لهما (التفعيل والقراءة والكتابة) هي الحالات الافتراضية للعناصر.

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

يمكن لصناديق التحقق وأزرار الاختيار المتعدد أن تكون مفعلة أو غير مفعلة أو معطلة، لكن هنالك عدة حالات يمكن النظر إليها:

  • default:: وهو صنف يستهدف الحالة التي يكون فيها العنصر مفعلًا افتراضيًا عند تحميل الصفحة أي استُخدمت ضمنه الخاصية checked. وتبقى هذه العناصر مستهدفة حتى لو ألغى المستخدم تفعيلها.
  • indeterminate: إن لم يكن صندوق التحقق أو زر الاختيار مفعلًا أو غير مفعل، سنتمكن من استهدافه باستخدام هذا الصنف الزائف.

الصنف checked:

عندما يفعّل عنصر التحقق أو زر الاختيار سيستهدفه الصنف checked:. يشيع استخدام هذا الصنف عندما تُفعّل هذه العناصر، وخاصة عندما تزيل التنسيق الافتراضي باستخدام appearance:none وتريد تنسيقه بنفسك، وقد رأينا أمثلة في المقال السابق عن هذا الاستخدام.

وإذا عدنا إلى مثال تنسيق أزرار الاختيار المتعدد في مقال "التنسيق المتقدم لاستمارات الويب"، سنرى أننا استخدمنا الشيفرة التالية في التنسيق:

input[type="radio"]::before {
 display: block;
 content: " ";
 width: 10px;
 height: 10px;
 border-radius: 6px;
 background-color: red;
 font-size: 1.2em;
 transform: translate(3px, 3px) scale(0);
 transform-origin: center;
 transition: all 0.3s ease-in;
}

input[type="radio"]:checked::before {
 transform: translate(3px, 3px) scale(1);
 transition: all 0.3s cubic-bezier(0.25, 0.25, 0.56, 2);
}

بإمكانك تجربتها في اﻹطار التالي:

لقد نسقنا في تلك الشيفرة مظهر الدائرة الداخلية التي تظهر ضمن أزرار الاختيار المتعدد باستخدام العنصر الزائف before:: ثم طبقنا تحويلًا باستخدام الخاصية transform قيمته (scale(0. ومن ثم طبقنا انتقالًا transition لتوليد محتوى متحرك ضمن الزر عندما يُفعَّل أو يُلغى تفعيله. إن ميزة استخدام التحويل بدلًا من تطبيق انتقال على الارتفاع والاتساع هو إمكانية استخدام الخاصية transform-origin حتى يبدأ الرسم المتحرك من مركز الدائرة ثم ينمو وليس من طرف الدائرة ثم يقفز بعدها إلى المركز. أما الارتداد الخفيف للدائرة نحو المركز فكان باستخدام تابع بيزيه التكعيبي.

الصنفان default: و indeterminate:

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

كما يستهدف الصنف الزائف indeterminate: تلك العناصر عندما تكون غير محددة الحالة أو عائمة أي ليست مفعلة وليست غير مفعلة، ونصادف هذه الحالة عندما:

  • عندما تكون جميع أزرار التحقق في نفس المجموعة غير مفعلّة.
  • عندما تُضبط الخاصية indeterminate لصندوق التحقق على القيمة true.
  • العناصر <progress> التي ليس لها قيمة.

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

سنلقي نظرة اﻵن على نسختين مختلفتين من المثال السابق، اﻷولى تذكر المستخدم ما هي الخيارات التي كانت مفعلة افتراضيًا والثانية ننسق فيها عناوين أزرار الاختيار المتعدد عندما تكون في الحالة غير المحددة. ولكلتا النسختين شيفرة HTML التالية:

<p>
 <input type="radio" name="fruit" value="cherry" id="cherry" />
 <label for="cherry">Cherry</label>
 <span></span>
</p>

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

input ~ span {
 position: relative;
}

input:default ~ span::after {
 font-size: 0.7rem;
 position: absolute;
 content: "Default";
 color: white;
 background-color: black;
 padding: 5px 10px;
 right: -65px;
 top: -3px;
}

تولد هذه الشيفرة محتوى نصي عنوانه "Default" إلى جوار العنصر الذي كان مختارًا افتراضيًا عند تحميل الصفحة. لاحظ كيف استخدمنا محدد التجميع (~) الذي يستهدف الأشقاء بدلًا من محدد التجميع (+) الذي يستهدف أشقاء متجاورين، ذلك أن العنصر <span> لا يأتي بالضرورة بعد العنصر <input> مباشرة في ترتيب الشيفرة المصدرية. إليك نتيجة الشيفرة:

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

input[type="radio"]:indeterminate {
 outline: 2px solid red;
 animation: 0.4s linear infinite alternate outline-pulse;
}

@keyframes outline-pulse {
 from {
    outline: 2px solid red;
 }

 to {
    outline: 6px solid red;
 }
}

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

أصناف زائفة أخرى

لنتحدث قليًلا عن بعض اﻷصناف التي لم نغطيها لكنها تستحق الوقت الذي قد تقضيه في الاطلاع عليها:

  • focus-within:: يستهدف العنصر الذي يتلقى تركيز الدخل أو الذي يضم عنصرًا تلقى تركيز الدخل. ويستخدم مثلًا إن أردت اﻹشارة إلى استمارة تلقى أحد عناصرها تركيز الدخل.
  • focus-visible:: يستهدف العناصر التي تلقت تركيز الدخل عبر لوحة المفاتيح (بدلًا من النقر بالفأرة)، ولهذا الصنف فائدته إن أردت التمييز بين الحالتين.
  • placeholder_shown:: ويستهدف العناصر التي تعرض حدود موضعها المؤقت placeholder وذلك عندما تستخدم الخاصية placeholder.

وهذه الأصناف مميزة أيضًا لكنها غير مدعومة جيدًا من قبل المتصفحات:

  • blank:: يستهدف عناصر التحكم الفارغة (التي لا تضم محتوى).

  • empty:: يستهدف العناصر التي لا تضم أبناءً وبالتالي تستهدف أيضًا العناصر الخالية void elements التي لا يمكن أن تضم أبناء أصلًا مثل عناصر <input> و <hr>. وتعد أكثر دعمًا من سابقتها، لأن blank: صنف لا يزال في فترة إعداد التوصيفات الخاصة به ولم يُدعم بعد.

  • user-invaild:: سيكون مشابهًا -عندما يُدعم- للصنف invaild: لكنه سيقدم تجربة مستخدم أفضل. فعندما تكون القيمة المدخلة صالحة عندما يتلقى العنصر التركيز، قد يستهدفه الصنف invaild: وكذلك عندما يدخل المستخدم قيمة غير صالحة مؤقتًا. بينما سيستهدف الصنف user-invaild: العنصر إن كانت القيمة المدخلة غير صالحة وفقد العنصر تركيز الدخل. وإذا كانت القيمة غير صالحة أصلًا، يستهدف كلا الصنفين العنصر طالما أنه يحتفظ بتركيز الدخل. وسيتوقف استهداف العنصر من كلا الصنفين عندما تصبح القيمة صالحة.

الخلاصة

لقد أنهينا في هذا المقال اﻹطلاع على اﻷصناف الزائفة التي تستهدف عناصر واجهة المستخدم وخاصة الاستمارات. يبقى عليك متابعة التجربة والعمل على هذه اﻷصناف لتألف طريقة استهدافها للعناصر وبالتالي تطبيق التنسيق المطلوب عليها.

ترجمة -وبتصرف- للمقال: UI pseudo-classes

اقرأ أيضًا


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

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

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



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

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

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

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


×
×
  • أضف...