متى يكون الزر ليس زرًا؟

نشرت: 2022-03-10
ملخص سريع ↬ ليس كل ما هو مستدير ومميز يعتبر زرًا. في هذه المقالة ، يشرح Vadim كيف يمكنك إنشاء زر تفاعلي مناسب لمستخدميك - زر لا ينبغي الخلط بينه وبين أي شيء آخر.

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

شيء يشبه زر الطماطم به نص "شيء ما".
تصميم لشيء النقر الخاص بك (معاينة كبيرة)

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

رابط يشبه الزر وزر يشبه الارتباط
معضلة الارتباط أو الزر (معاينة كبيرة)
المزيد بعد القفز! أكمل القراءة أدناه ↓

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

مخطط التدفق: إنه زر. إذا لم يكن كذلك ، فهو رابط. هذا هو.
مخطط انسيابي علمي لاختيار العنصر الصحيح (معاينة كبيرة)
  1. إنه زر.
  2. إذا لم يكن كذلك ، فهو رابط.
  3. هذا هو.

إذن ، هل كل شيء زر؟ لا ، ولكن يمكنك دائمًا البدء بزر لأي عنصر تقريبًا يمكن النقر فوقه أو التفاعل معه بطريقة مماثلة. وإذا كانت تفتقر إلى شيء ما ، مثل التنقل إلى صفحة أخرى ، فاستخدم رابطًا بدلاً من ذلك. ولا ، المؤشر ليس سببًا لجعله <a href> . لدينا cursor: pointer لذلك.

زر طماطم مركز عليه نص "شيء ما"
لا تنسَ تقديم أنماط تركيز. (معاينة كبيرة)

حسنًا ، إنه <button> - نتفق على ذلك. دعنا نضعه في قالبنا ونصممه وفقًا للتصميم: بعض الحشو ، والتقريب ، وتعبئة الطماطم ، والنص الأبيض ، وحتى بعض أنماط التركيز. أوه ، هذا لطيف منك.

 <button type="button" class="button"> Something </button> <style> .button { display: inline-block; padding: 10px 20px; border-radius: 20px; background-color: tomato; color: white; } .button:focus { outline: none; box-shadow: 0 0 0 5px #006AE3; } </style>

لم يستغرق ذلك وقتًا طويلاً. كنت تريد أن تبنيها بسرعة وتناول بعض الغداء لأنك جائع. حسنًا ، دعنا نرى كيف يبدو ونبدأ.

زر طماطم قبيح المظهر ، يتم عرضه في المستعرض
في بعض الأحيان لا يكون المتصفح أفضل صديق لك. (معاينة كبيرة)

يا إلهي! هناك خطأ ما في المتصفح. لماذا هذا الزر قبيح جدا؟ النص صغير جدًا ، على الرغم من أننا قمنا بتعيين النص بشكل صريح على 16px ، وحتى body font-family خاطئة. تعتبر الحدود المستديرة ذات الظل الزائف السخيف قديمة جدًا لدرجة أنها لم تعد اتجاهًا حتى الآن.

آه ، إنه التصميم الافتراضي للمتصفح. تحتاج إلى التراجع عن ذلك بعناية أو حتى إضافة Normalize.css أو Reset.css ... أو يمكنك فقط استخدام <div> ونسيان أمره. أليس حل المشكلات بسرعة هو ما يدفعون لك مقابله؟ أنت جائع وهذا لا يساعد على الإطلاق. لكنك محترف: اجمع نفسك وفكر.

ما الفرق بين <button> و <div> على أي حال؟ <button> المدمج هو عنصر تفاعلي ، مما يعني أنه يمكن التفاعل معه. هذا عميق. يمكنك النقر فوقه ، ويمكنك التركيز عليه باستخدام لوحة المفاتيح ، كما أنه ينقل دور button الذي يمكن الوصول إليه إلى برامج قراءة الشاشة ، مما يتيح للمستخدمين فهم أنه زر.

بديع! أنت لست على دراية بعنصر <button> في HTML فحسب ، ولكنك تعرف أيضًا شيئًا أو شيئين عن ARIA ودعم قارئ الشاشة. ربما تكون قد جربت VoiceOver أو NVDA لاختبار مدى إمكانية الوصول إلى واجهاتك.

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

 <div class="button" tabindex="0" role="button"> Something </div>

الآن لا يبدو الأمر صحيحًا فحسب ، بل يمكن التركيز عليه عبر لوحة المفاتيح بفضل tabindex="0" ، وستتعامله برامج قراءة الشاشة على أنها زر مناسب لأنك أضفت بحكمة role="button" إليها. Git الالتزام && ادفع بعد ذلك! هناك بعض المهام الإضافية لهذا الشيء ، لكننا انتهينا من التصميم. ما الذي يمكن أن يحدث خطأ؟ وقت الغداء. رائع ، دعنا نذهب!

بعد ساعة…

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

 <script> const buttons = document.querySelectorAll('.button'); [...buttons].forEach(button => { button.addEventListener('click', doSomething); }); function doSomething() { console.log('Something!'); } </script>

منجز. يمكن للمستخدم الآن النقر فوقه بالماوس على سطح المكتب والنقر عليه بإصبعه على شاشة تعمل باللمس. سيتم إطلاق حدث النقر بشكل موثوق ، وسترى الكثير من شيء ما! في وحدة التحكم الخاصة بك. ما هي المهمة التالية؟

يتمسك! نحتاج إلى التأكد من أنه يعمل بنفس الطريقة لمستخدمي لوحة المفاتيح. نظرًا لأن لدينا tabindex="0" على الزر ، يمكن التركيز عليها ، وبمجرد التركيز عليها ، يجب أن يكون المستخدمون قادرين على الضغط على مفتاح المسافة أو مفتاح "Enter" لتشغيل كل ما قمنا بإرفاقه.

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

 <script> const buttons = document.querySelectorAll('.button'); [...buttons].forEach(button => { button.addEventListener('click', doSomething); button.addEventListener('keyup', (event) => { if (event.key == 'Enter' || event.key == ' ') { doSomething(); } }); }); function doSomething() { console.log('Something!'); } </script>

تفو! الآن يمكن الوصول إلى الشيء القابل للنقر بشكل كامل من لوحة المفاتيح. أنا فخور جدا بك! وجافا سكريبت سحرية حقًا - ماذا سنفعل بدونها؟

حسنًا ، ما هي المهمة الأخيرة: "يجب أن يكون للزر حالة تعطيل تغير شكله وسلوكه إلى شيء مخدر." مخدر؟ أعتقد أن هذا يعني شيئًا رماديًا ولا يستجيب للتفاعل. حسنًا ، دعنا نضيف حالة في ورقة الأنماط باستخدام تسمية BEM.

 <div class="button button--disabled" tabindex="0" role="button"> Something </div> <style> .button--disabled { background-color: #9B9B9B; } </style> 
زر رمادي مع تطبيق حالة التعطيل
هذا الزر يبدو مخدرًا بشكل مريح. (معاينة كبيرة)

هذا يبدو مخدر بشكل مريح بالنسبة لي. كلما احتاج الزر إلى التعطيل ، سنضيف button--disabled لجعله رماديًا. لكنها ليست مخدرة بما فيه الكفاية حتى الآن: لا يزال من الممكن التركيز عليها وتشغيلها بواسطة مؤشر ومن لوحة المفاتيح.

الرتق ، هذا أمر صعب.

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

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

دعنا نأكل بعض الوجبات الجاهزة. لن نكون في المنزل لتناول العشاء بحلول الوقت الذي ننتهي فيه ونختبر ذلك بشكل صحيح. W3C الدموية! لماذا لا يحاولون جعل حياتنا أسهل؟ كأنهم يهتمون بنا!

في واقع الأمر ، فإنهم يفعلون ...

لنعد بضع خطوات للوراء قبل القفز في هذه الفوضى. لماذا لا نحاول القيام بهذه الأشياء باستخدام عنصر <button> ؟ يحتوي على بعض الحيل المفيدة في جعبته ، وليس فقط الأنماط القبيحة للمتصفح. أوه ، ولا تنس type="button" - لا تريد أن يقوم زر "إغلاق" في النافذة المنبثقة بإرسال النموذج عن طريق الخطأ ، لأن type="submit" هي القيمة الافتراضية.

على ما يبدو ، عند التركيز على <button> والضغط على مفتاح المسافة أو مفتاح "Enter" ، فسيؤدي ذلك إلى تشغيل حدث click ، تمامًا كما تفعل الأجهزة المحمولة عندما تحصل على نقرات أو تربيتات أو تلعق أو أي شيء آخر يمكنها تلقيه اليوم. حدث واحد مستمع أقل في كودنا! لطيف - جيد.

 // A click is enough! button.addEventListener('click', doSomething);

بالنسبة إلى حالة التعطيل ، تتوفر السمة disabled لعنصر <button> ، وكذلك لجميع عناصر النموذج ، بما في ذلك <fieldset> . لا تمزح. هل تعلم أنه يمكنك تعطيل مجموعة كاملة من المدخلات مجمعة معًا فقط من خلال تطبيق سمة واحدة على الأصل <fieldset> ؟

مجموعة من المدخلات المعطلة وزر
تم تعطيل مجموعة من المدخلات بسمة واحدة (معاينة كبيرة)
 <fieldset disabled> <legend>A bunch of numb inputs</legend> <p> <label> <input type="radio" name="option"> Of course it's a link </label> </p> <p> <label> <input type="radio" name="option"> Obviously, it's a button </label> </p> <p> <label> <input type="radio" name="option"> I just wanna go home </label> </p> <button type="button">Button</button> </fieldset>

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

 <button disabled type="button" class="button"> Something </button>

ولكن انتظر هناك المزيد! يؤدي أيضًا إلى تشغيل فئة زائفة :disabled في CSS ، مما يعني أنه يمكننا التخلص من مُعدِّل BEM لإعلان الأنماط واستخدام المُعدِّل الديناميكي المدمج بدلاً من ذلك.

 .button:disabled { background-color: #9B9B9B; }

بالنسبة للأنماط القبيحة للمتصفح ، لا يتعين علينا استخدام جميع Normalize.css لإصلاح زر واحد. استخدمه كمصدر للحكمة: الأسطر الثلاثة الإضافية أدناه ستصلح معظم الاختلافات المزعجة من <div> . إذا احتجت إلى المزيد في أي وقت ، يمكنك نسخ الأجزاء ذات الصلة منه.

 .button { font-size: 100%; font-family: inherit; border: none; }

منجز. HTML ليست سيئة للغاية بعد كل شيء!

ولكن إذا كانت مفاجأة لك بين الحين والآخر ، فتأكد من التحقق من مواصفات HTML للحصول على إجابات. لقد أصبح أكثر ودية على مر السنين ، وهو مليء بأمثلة الاستخدام وإمكانية الوصول الجيدة. وبالطبع ، لا يزال برنامج HTML5 Doctor الجيد مكانًا موثوقًا به لمعرفة الفرق بين عنصري <section> و <article> وللتحقق مما إذا كان مخطط المستند لا يزال موجودًا (ليس حقًا). هناك فرصة جيدة أن ينتهي بك الأمر أيضًا إلى قراءة وثائق HTML بواسطة Mozilla ، ولن تندم أيضًا.

تم الانتهاء من هذه المهمة الآن! ماذا بعد؟ تقويم دائري منسدلة مع حقل بحث؟ أوه! حظا جيدا في ذلك. لكن تذكر: <button> هو صديقك!

مزيد من القراءة على SmashingMag:

  • كيفية تصميم أزرار أفضل
  • بناء أزرار تبديل شاملة
  • تصميم زر الشبح: هل هذا حقًا لا يزال شيئًا (ولماذا)؟
  • أنماط التصميم: عند كسر القواعد على ما يرام