بناء مكون زر

نظرة عامة أساسية حول كيفية إنشاء مكونات <button> متكيّفة مع الألوان ومتجاوبة وسهلة الاستخدام

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

يمكن التفاعل مع الأزرار باستخدام لوحة المفاتيح والماوس في المظهرَين الفاتح والداكن.

إذا كنت تفضّل مشاهدة الفيديوهات، يمكنك الاطّلاع على نسخة من هذه المشاركة على YouTube:

نظرة عامة

توافق المتصفّح

  • Chrome: 1.
  • Edge: 12.
  • Firefox: 1.
  • Safari: 1.

المصدر

تم تصميم العنصر <button> للتفاعل مع المستخدم. يتم تنشيط حدث click من لوحة المفاتيح والماوس واللمس والصوت وغير ذلك، مع قواعد ذكية حول توقيته. وتتوفّر أيضًا بعض الأنماط التلقائية في كل متصفح، حتى تتمكّن من استخدامها مباشرةً بدون أي تخصيص. استخدِم color-scheme للموافقة على استخدام الزرَّين الفاتح والداكن المتوفّرين في المتصفّح أيضًا.

هناك أيضًا أنواع مختلفة من buttons، يتم عرض كلّ منها في رمز Codepen المضمّن السابق. سيتم تعديل <button> بدون نوع ليصبح ضمن <form>، وسيتم تغييره إلى نوع الإرسال.

<!-- buttons -->
<button></button>
<button type="submit"></button>
<button type="button"></button>
<button type="reset"></button>

<!-- button state -->
<button disabled></button>

<!-- input buttons -->
<input type="button" />
<input type="file">

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

معاينة المجموعة النهائية من جميع أنواع الأزرار، معروضة في نموذج وليس في نموذج، مع إضافات رائعة لأزرار الرموز والأزرار المخصّصة
معاينة المجموعة النهائية من جميع أنواع الأزرار، معروضة في نموذج وليس في نموذج، مع إضافات رائعة لأزرار الرموز والأزرار المخصّصة

تحتوي الأزرار أيضًا على فئات صورية لكي تستخدمها لغة CSS في تحديد النمط. توفّر هذه الفئات عناصر CSS لضبط مظهر الزر: :hover عند تمرير الماوس فوق الزر، :active عند الضغط على الماوس أو لوحة المفاتيح، :focus أو :focus-visible للمساعدة في تصميم التكنولوجيا المساعِدة.

button:hover {}
button:active {}
button:focus {}
button:focus-visible {}
معاينة المجموعة النهائية من جميع أنواع الأزرار في المظهر الداكن
معاينة المجموعة النهائية من جميع أنواع الأزرار في المظهر الداكن

Markup

بالإضافة إلى أنواع الأزرار التي تقدّمها مواصفات HTML، أضفت زرًا يتضمّن رمزًا وزرًا يتضمّن فئة مخصّصة btn-custom.

<button>Default</button>
<input type="button" value="<input>"/>
<button>
  <svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true">
    <path d="..." />
  </svg>
  Icon
</button>
<button type="submit">Submit</button>
<button type="button">Type Button</button>
<button type="reset">Reset</button>
<button disabled>Disabled</button>
<button class="btn-custom">Custom</button>
<input type="file">

بعد ذلك، يتم وضع كل زر داخل نموذج لأغراض الاختبار. بهذه الطريقة، يمكنني التأكّد من تعديل أنماط الزر التلقائي بشكل مناسب، والذي يعمل كزر إرسال. وأغيّر أيضًا استراتيجية الرمز، من رسومات SVG مضمّنة إلى رسومات SVG مموّهة، لضمان عمل كليهما بشكلٍ جيد بالقدر نفسه.

<form>
  <button>Default</button>
  <input type="button" value="<input>"/>
  <button>Icon <span data-icon="cloud"></span></button>
  <button type="submit">Submit</button>
  <button type="button">Type Button</button>
  <button type="reset">Reset</button>
  <button disabled>Disabled</button>
  <button class="btn-custom btn-large" type="button">Large Custom</button>
  <input type="file">
</form>

إنّ مصفوفة التركيبات ضخمة جدًا في هذه المرحلة. بين أنواع الأزرار والفئات الزائفة وظهورها داخل نموذج أو خارجه، هناك أكثر من 20 تركيبة من الأزرار. من الجيد أنّ CSS يمكن أن تساعدنا في توضيح كلٍّ من هذه العناصر بوضوح.

تسهيل الاستخدام

يمكن الوصول إلى عناصر الأزرار بشكل طبيعي، ولكن هناك بعض التحسينات الشائعة.

التمرير بمؤشر الماوس والتركيز معًا

أريد تجميع :hover و:focus معًا باستخدام :is()، وهو عنصر اختيار وظيفي زائف. يساعد ذلك في ضمان أنّ واجهاتي تراعي دائمًا التنسيقات الخاصة بكل من لوحة المفاتيح والتكنولوجيا المساعِدة.

button:is(:hover, :focus) {
  
}
يمكنك تجربة الإصدار التجريبي.

حلقة التركيز التفاعلية

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

:where(button, input):where(:not(:active)):focus-visible {
  outline-offset: 5px;
}

التأكّد من اجتياز اختبار تباين الألوان

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

إخفاء الرموز عن المستخدمين الذين لا يمكنهم رؤيتها

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

<button>
  <svg … aria-hidden="true">...</svg>
  Icon Button
</button>
أدوات مطوّري البرامج في Chrome تعرض شجرة تسهيل الاستخدام للزر تتجاهل الشجرة صورة الزر لأنّها تم ضبط aria-hidden على true.
أداة Chrome DevTools تعرض شجرة تسهيل الاستخدام للزر. تتجاهل الشجرة صورة الزر لأنّها تم ضبط aria-hidden على true

الأنماط

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

استراتيجية خاصة مخصّصة قابلة للتكيّف

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

button {
  --_bg-light: white;
  --_bg-dark: black;
  --_bg: var(--_bg-light);

  background-color: var(--_bg);
}

@media (prefers-color-scheme: dark) {
  button {
    --_bg: var(--_bg-dark);
  }
}

ما أعجبني هو أنّ المظهرَين الفاتح والداكن واضحان وصريحان. يتمّ نقل الاستدلال غير المباشر والتجريد إلى السمة المخصّصة --_bg، التي أصبحت الآن السمة "التفاعلية" الوحيدة، بينما السمتَان --_bg-light و--_bg-dark ثابتتان. من الواضح أيضًا أنّ المظهر الفاتح هو المظهر التلقائي ولا يتم تطبيق المظهر الداكن إلا بشكل مشروط.

التحضير لضمان اتساق التصميم

أداة الاختيار المشتركة

يُستخدَم المحدّد التالي لاستهداف جميع الأنواع المختلفة من الأزرار، وهو قد يكون مربكًا بعض الشيء في البداية. يتم استخدام :where() كي لا يتطلّب تخصيص الزر أيّ تحديد. غالبًا ما يتم تعديل الأزرار لتناسب سيناريوهات بديلة، ويضمن أداة الاختيار :where() سهولة تنفيذ المهام. داخل :where()، يتم اختيار كل نوع زر، بما في ذلك ::file-selector-button، الذي لا يمكن استخدامه داخل :is() أو :where().

:where(
  button,
  input[type="button"],
  input[type="submit"],
  input[type="reset"],
  input[type="file"]
),
:where(input[type="file"])::file-selector-button {
  
}

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

لون تمييز الزر

إنّ أزرار الإرسال والرموز هي مكان رائع لإضافة لمسة من الألوان:

--_accent-light: hsl(210 100% 40%);
--_accent-dark: hsl(210 50% 70%);
--_accent: var(--_accent-light);

لون نص الزر

لا تكون ألوان نص الأزرار بيضاء أو سوداء، بل هي إصدارات أغمق أو أفتح من --_accent باستخدام hsl() والتقيّد بنغمة 210:

--_text-light: hsl(210 10% 30%);
--_text-dark: hsl(210 5% 95%);
--_text: var(--_text-light);

لون خلفية الزر

تتّبع خلفيات الأزرار نمط hsl() نفسه باستثناء أزرار المظهر الفاتح، والتي يتم ضبطها على اللون الأبيض لكي تبدو سطحها قريبة من المستخدِم أو أمام الأسطح الأخرى:

--_bg-light: hsl(0 0% 100%);
--_bg-dark: hsl(210 9% 31%);
--_bg: var(--_bg-light);

خلفية الزر

يُستخدَم لون الخلفية هذا لظهور سطح خلف مساحات أخرى، وهو مفعّل لخلفية إدخال الملف:

--_input-well-light: hsl(210 16% 87%);
--_input-well-dark: hsl(204 10% 10%);
--_input-well: var(--_input-well-light);

المساحة الفارغة حول الزر

يتم ضبط المسافة حول النص في الزر باستخدام وحدة ch ، وهي طول نسبي لحجم الخط. يصبح هذا الأمر مهمًا عندما يتمكّن الزرّ الكبير من زيادة مقاييس font-size والزرّ بشكلٍ نسبي:

--_padding-inline: 1.75ch;
--_padding-block: .75ch;

حدود الزر

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

--_border-radius: .5ch;

--_border-light: hsl(210 14% 89%);
--_border-dark: var(--_bg-dark);
--_border: var(--_border-light);

تأثير تمييز الزر عند التمرير فوقه

تحدِّد هذه السمات سمة المقاس لعملية النقل عند التفاعل، ويتبع لون التمييز نظام الألوان التكيُّفية. سنتناول كيفية تفاعل هذه العوامل مع بعضها لاحقًا في هذه المشاركة، ولكن في النهاية يتم استخدامها لتحقيق box-shadow تأثير:

--_highlight-size: 0;

--_highlight-light: hsl(210 10% 71% / 25%);
--_highlight-dark: hsl(210 10% 5% / 25%);
--_highlight: var(--_highlight-light);

ظل نص الزر

يحتوي كل زر على نمط ظلال نصي خفيف. يساعد ذلك في وضع النص فوق الزر، ما يُحسِّن من وضوحه ويضيف لمسة جمالية إلى العرض.

--_ink-shadow-light: 0 1px 0 var(--_border-light);
--_ink-shadow-dark: 0 1px 0 hsl(210 11% 15%);
--_ink-shadow: var(--_ink-shadow-light);

رمز الزر

تكون الرموز بحجم حرفَين بفضل وحدة الطول النسبي ch مرة أخرى، ما سيساعد في تغيير حجم الرمز بما يتناسب مع نص الزر. يعتمد لون الرمز على --_accent-color للحصول على لون متوافق مع المظهر.

--_icon-size: 2ch;
--_icon-color: var(--_accent);

ظل الزر

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

--_shadow-color-light: 220 3% 15%;
--_shadow-color-dark: 220 40% 2%;
--_shadow-color: var(--_shadow-color-light);

--_shadow-strength-light: 1%;
--_shadow-strength-dark: 25%;
--_shadow-strength: var(--_shadow-strength-light);

باستخدام الألوان ودرجات القوة التكيُّفية، يمكنني تجميع عمقَين للتظليل:

--_shadow-1: 0 1px 2px -1px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 9%));

--_shadow-2: 
  0 3px 5px -2px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 3%)),
  0 7px 14px -5px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 5%));

بالإضافة إلى ذلك، لمنح الأزرار مظهرًا ثلاثي الأبعاد قليلاً، يمكنك استخدام 1px box-shadow لإضفاء هذا المظهر:

--_shadow-depth-light: 0 1px var(--_border-light);
--_shadow-depth-dark: 0 1px var(--_bg-dark);
--_shadow-depth: var(--_shadow-depth-light);

انتقالات الأزرار

وفقًا لنمط الألوان التكيُّفية، أُنشئ سمتَين ثابتتَين لشدَّد خيارات نظام التصميم:

--_transition-motion-reduce: ;
--_transition-motion-ok:
  box-shadow 145ms ease,
  outline-offset 145ms ease
;
--_transition: var(--_transition-motion-reduce);

جميع المواقع معًا في أداة الاختيار

جميع الخصائص المخصّصة في أداة اختيار

:where(
  button,
  input[type="button"],
  input[type="submit"],
  input[type="reset"],
  input[type="file"]
),
:where(input[type="file"])::file-selector-button {
  --_accent-light: hsl(210 100% 40%);
  --_accent-dark: hsl(210 50% 70%);
  --_accent: var(--_accent-light);

--_text-light: hsl(210 10% 30%); --_text-dark: hsl(210 5% 95%); --_text: var(--_text-light);

--_bg-light: hsl(0 0% 100%); --_bg-dark: hsl(210 9% 31%); --_bg: var(--_bg-light);

--_input-well-light: hsl(210 16% 87%); --_input-well-dark: hsl(204 10% 10%); --_input-well: var(--_input-well-light);

--_padding-inline: 1.75ch; --_padding-block: .75ch;

--_border-radius: .5ch; --_border-light: hsl(210 14% 89%); --_border-dark: var(--_bg-dark); --_border: var(--_border-light);

--_highlight-size: 0; --_highlight-light: hsl(210 10% 71% / 25%); --_highlight-dark: hsl(210 10% 5% / 25%); --_highlight: var(--_highlight-light);

--_ink-shadow-light: 0 1px 0 hsl(210 14% 89%); --_ink-shadow-dark: 0 1px 0 hsl(210 11% 15%); --_ink-shadow: var(--_ink-shadow-light);

--_icon-size: 2ch; --_icon-color-light: var(--_accent-light); --_icon-color-dark: var(--_accent-dark); --_icon-color: var(--accent, var(--_icon-color-light));

--_shadow-color-light: 220 3% 15%; --_shadow-color-dark: 220 40% 2%; --_shadow-color: var(--_shadow-color-light); --_shadow-strength-light: 1%; --_shadow-strength-dark: 25%; --_shadow-strength: var(--_shadow-strength-light); --_shadow-1: 0 1px 2px -1px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 9%)); --_shadow-2: 0 3px 5px -2px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 3%)), 0 7px 14px -5px hsl(var(--_shadow-color)/calc(var(--_shadow-strength) + 5%)) ;

--_shadow-depth-light: hsl(210 14% 89%); --_shadow-depth-dark: var(--_bg-dark); --_shadow-depth: var(--_shadow-depth-light);

--_transition-motion-reduce: ; --_transition-motion-ok: box-shadow 145ms ease, outline-offset 145ms ease ; --_transition: var(--_transition-motion-reduce); }

تظهر الأزرار التلقائية جنبًا إلى جنب في المظهرَين الفاتح والداكن.

التعديلات على المظهر الداكن

تصبح قيمة نمط العناصر الثابتة -light و-dark واضحة عند ضبط عناصر المظهر الداكن:

@media (prefers-color-scheme: dark) {
  :where(
    button,
    input[type="button"],
    input[type="submit"],
    input[type="reset"],
    input[type="file"]
  ),
  :where(input[type="file"])::file-selector-button {
    --_bg: var(--_bg-dark);
    --_text: var(--_text-dark);
    --_border: var(--_border-dark);
    --_accent: var(--_accent-dark);
    --_highlight: var(--_highlight-dark);
    --_input-well: var(--_input-well-dark);
    --_ink-shadow: var(--_ink-shadow-dark);
    --_shadow-depth: var(--_shadow-depth-dark);
    --_shadow-color: var(--_shadow-color-dark);
    --_shadow-strength: var(--_shadow-strength-dark);
  }
}

لا يُعدّ هذا الأسلوب مناسبًا للقراءة فحسب، بل يمكن لمستخدِمي هذه الأزرار المخصّصة استخدام العناصر الأساسية بثقة بأنّها ستتلاءم بشكل مناسب مع الإعدادات المفضّلة للمستخدم.

التعديلات التي تقلّل من الحركة

إذا كان هذا المستخدم الزائر يوافق على استخدام ميزة "الحركة"، يمكنك ضبط الإعداد --_transition على var(--_transition-motion-ok):

@media (prefers-reduced-motion: no-preference) {
  :where(
    button,
    input[type="button"],
    input[type="submit"],
    input[type="reset"],
    input[type="file"]
  ),
  :where(input[type="file"])::file-selector-button {
    --_transition: var(--_transition-motion-ok);
  }
}

بعض الأنماط المشتركة

يجب ضبط خطوط الأزرار والمدخلات على inherit لكي تتطابق مع بقية خطوط الصفحة، وإلا سيضبط المتصفّح أسلوبها. وينطبق ذلك أيضًا على letter-spacing. يؤدي ضبط line-height على 1.5 إلى ضبط حجم مربّع الرسالة لإعطاء النص بعض المساحة أعلاه وأسفله:

:where(
  button,
  input[type="button"],
  input[type="submit"],
  input[type="reset"],
  input[type="file"]
),
:where(input[type="file"])::file-selector-button {
  /* …CSS variables */

  font: inherit;
  letter-spacing: inherit;
  line-height: 1.5;
  border-radius: var(--_border-radius);
}

لقطة شاشة تعرض الأزرار بعد تطبيق الأنماط السابقة

أزرار التصميم

ضبط أداة الاختيار

إنّ العنصر المحدّد input[type="file"] ليس جزء الزر من الإدخال، بل هو العنصر الاصطناعي ::file-selector-button، لذلك أزلنا input[type="file"] من القائمة:

:where(
  button,
  input[type="button"],
  input[type="submit"],
  input[type="reset"],
  input[type="file"]
),
:where(input[type="file"])::file-selector-button {
  
}

تعديلات المؤشر واللمس

أولاً، أضبط أسلوب المؤشر على pointer، ما يساعد الزر في الإشارة إلى مستخدمي الماوس بأنّه تفاعلي. بعد ذلك، أضِف touch-action: manipulation لجعل النقرات لا تحتاج إلى الانتظار وملاحظة نقرة مزدوجة محتملة، ما يجعل استخدام buttons أسرع:

:where(
  button,
  input[type="button"],
  input[type="submit"],
  input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
  cursor: pointer;
  touch-action: manipulation;
}

الألوان والحدود

بعد ذلك، خصّصت حجم الخط والخلفية والنص وألوان الحدود باستخدام بعض الخصائص المخصّصة التكيُّفية التي تم إنشاؤها سابقًا:

:where(
  button,
  input[type="button"],
  input[type="submit"],
  input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
  

  font-size: var(--_size, 1rem);
  font-weight: 700;
  background: var(--_bg);
  color: var(--_text);
  border: 2px solid var(--_border);
}

لقطة شاشة تعرض الأزرار بعد تطبيق الأنماط السابقة

الظلال

تم تطبيق بعض الأساليب الرائعة على الأزرار. text-shadow هو رمز متوافق مع المظهر الفاتح والداكن، ما يخلق مظهرًا لطيفًا لنص الزر الذي يظهر بشكل جميل على أعلى الخلفية. بالنسبة إلى box-shadow، يتمّ تخصيص ثلاثة ظلال. الخيار الأول، --_shadow-2، هو ظل مربّع عادي. إنّ الظل الثاني هو خدعة للعين تجعل الزر يبدو منحنيًا قليلاً للأعلى. الظل الأخير مخصّص لتمييز المؤشر، وهو يبدأ بحجم 0، ولكن سيتم منحه حجمًا لاحقًا وسيتم نقله ليبدو كأنّه يكبر من الزر.

:where(
  button,
  input[type="button"],
  input[type="submit"],
  input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
  

  box-shadow: 
    var(--_shadow-2),
    var(--_shadow-depth),
    0 0 0 var(--_highlight-size) var(--_highlight)
  ;
  text-shadow: var(--_ink-shadow);
}

لقطة شاشة تعرض الأزرار بعد تطبيق الأنماط السابقة

التنسيق

لقد أضفت إلى الزر تنسيق صندوق مرن، وتحديدًا تنسيق inline-flex الذي يناسب محتواه. بعد ذلك، أتوسّط النص وأحاذي العناصر الفرعية عموديًا وأفقيًا في الوسط. سيساعد ذلك في محاذاة الرموز وغيرها من عناصر الزر بشكل صحيح.

:where(
  button,
  input[type="button"],
  input[type="submit"],
  input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
  

  display: inline-flex;
  justify-content: center;
  align-items: center;
  text-align: center;
}

لقطة شاشة تعرض الأزرار بعد تطبيق الأنماط السابقة

المسافات

بالنسبة إلى المسافة بين الأزرار، استخدمت gap لمنع العناصر المتشابهة من التلامس والسمات المنطقية للمسافة الفارغة حتى تعمل المسافة بين buttons في جميع تنسيقات النص.

:where(
  button,
  input[type="button"],
  input[type="submit"],
  input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
  

  gap: 1ch;
  padding-block: var(--_padding-block);
  padding-inline: var(--_padding-inline);
}

لقطة شاشة تعرض الأزرار بعد تطبيق الأنماط السابقة

تجربة المستخدم في اللمس والماوس

هذا القسم التالي مخصّص في الغالب لمستخدمي الأجهزة التي تعمل باللمس على الأجهزة الجوّالة. السمة الأولى، user-select، مخصّصة لجميع المستخدمين، وهي تمنع تمييز النص لنص الزر. ويظهر ذلك بشكلٍ ملحوظ في الغالب على الأجهزة التي تعمل باللمس عند النقر مع الاستمرار على زر معيّن وتمييز نظام التشغيل لنص الزر.

لقد تبيّن لي بشكل عام أنّ هذه ليست تجربة المستخدم مع الأزرار في التطبيقات المضمّنة، لذلك أوقفها من خلال ضبط user-select على "بدون". إنّ ألوان التمييز (-webkit-tap-highlight-color) وقوائم السياقات لنظام التشغيل (-webkit-touch-callout) هي ميزات أخرى تركّز على الويب ولا تتوافق مع توقعات مستخدمي buttons بشكل عام، لذا أزيلها أيضًا.

:where(
  button,
  input[type="button"],
  input[type="submit"],
  input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
  

  user-select: none;
  -webkit-tap-highlight-color: transparent;
  -webkit-touch-callout: none;
}

الانتقالات

يتمّ تعيين المتغيّر --_transition التكيُّفي إلى سمة transition:

:where(
  button,
  input[type="button"],
  input[type="submit"],
  input[type="reset"]
),
:where(input[type="file"])::file-selector-button {
  

  transition: var(--_transition);
}

عند التمرير فوق الزر، بدون أن يضغط عليه المستخدم، يمكنك تعديل حجم تمييز الظل لإضفاء مظهر جميل للتركيز يبدو أنّه يكبر من داخل الزر:

:where(
  button,
  input[type="button"],
  input[type="submit"],
  input[type="reset"]
):where(:not(:active):hover) {
  --_highlight-size: .5rem;
}

عند التركيز على الزر، يمكنك زيادة انحراف مخطط التركيز عن الزر، ما يمنحه أيضًا مظهرًا جميلاً للتركيز يبدو أنّه يكبر من داخل الزر:

:where(button, input):where(:not(:active)):focus-visible {
  outline-offset: 5px;
}

الرموز

لمعالجة الرموز، يحتوي المحدّد على أداة اختيار :where() مضافة لعناصر SVG التابعة مباشرةً أو العناصر التي تحتوي على السمة المخصّصة data-icon. يتم ضبط حجم الرمز باستخدام السمة المخصّصة باستخدام السمتَين المنطقيتَين "مضمّن" و"مربّع". تم ضبط لون ملف التمويه ، بالإضافة إلى drop-shadow لمطابقة text-shadow. تم ضبط flex-shrink على 0 حتى لا يتم أبدًا تصغير الرمز. أخيرًا، اخترت رموزًا مسطّحة وأضفت إليها هذه الأنماط باستخدام fill: none وround لرؤوس الخطوط ووصلاتها:

:where(
  button,
  input[type="button"],
  input[type="submit"],
  input[type="reset"]
) > :where(svg, [data-icon]) {
  block-size: var(--_icon-size);
  inline-size: var(--_icon-size);
  stroke: var(--_icon-color);
  filter: drop-shadow(var(--_ink-shadow));

  flex-shrink: 0;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

لقطة شاشة تعرض الأزرار بعد تطبيق الأنماط السابقة

تخصيص أزرار الإرسال

أردت أن أمنح أزرار الإرسال مظهرًا ترويجيًا قليلاً، ونجحت في تحقيق ذلك من خلال جعل لون نص الأزرار هو اللون المميّز:

:where(
  [type="submit"], 
  form button:not([type],[disabled])
) {
  --_text: var(--_accent);
}

لقطة شاشة تعرض الأزرار بعد تطبيق الأنماط السابقة

تخصيص أزرار إعادة الضبط

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

:where([type="reset"]) {
  --_border-light: hsl(0 100% 83%);
  --_highlight-light: hsl(0 100% 89% / 20%);
  --_text-light: hsl(0 80% 50%);
  --_text-dark: hsl(0 100% 89%);
}

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

:where([type="reset"]):focus-visible {
  outline-color: currentColor;
}

لقطة شاشة تعرض الأزرار بعد تطبيق الأنماط السابقة

تخصيص الأزرار المتوقفة

من الشائع جدًا أن يكون التباين اللوني للأزرار غير النشطة ضعيفًا أثناء محاولة تخفيف ظهور الزر غير النشط. لقد اختبرت كل مجموعة من الألوان وتأكّدت من اجتياز الاختبار، مع تعديل قيمة الإضاءة في HSL إلى أن اجتازت النتيجة الاختبار في DevTools أو VisBug.

:where(
  button,
  input[type="button"],
  input[type="submit"],
  input[type="reset"]
)[disabled] {
  --_bg: none;
  --_text-light: hsl(210 7% 40%);
  --_text-dark: hsl(210 11% 71%);

  cursor: not-allowed;
  box-shadow: var(--_shadow-1);
}

لقطة شاشة تعرض الأزرار بعد تطبيق الأنماط السابقة

تخصيص أزرار إدخال الملفات

زر إدخال الملف هو حاوية لعنصر span وزر. يمكن لأسلوب CSS تنسيق حاوية الإدخال قليلاً، بالإضافة إلى الزر المُدمَج، ولكن ليس العنصر. يتم منح الحاوية max-inline-size لكي لا تكبر أكثر مما ينبغي، بينما سيسمح inline-size: 100% بتصغيرها وملاءمتها للحاويات الأصغر حجمًا. يتم ضبط لون الخلفية على لون تكيُّفي يكون أغمق من الأسطح الأخرى، بحيث يظهر خلف زر اختيار الملف.

:where(input[type="file"]) {
  inline-size: 100%;
  max-inline-size: max-content;
  background-color: var(--_input-well);
}

تم منح زرّ اختيار الملفات وأزرار نوع الإدخال تحديدًا appearance: none لإزالة أي أنماط يوفّرها المتصفّح ولم يتم استبدالها بأنماط الأزرار الأخرى.

:where(input[type="button"]),
:where(input[type="file"])::file-selector-button {
  appearance: none;
}

أخيرًا، تتم إضافة هامش إلى inline-end الزرّ لدفع نص النطاق بعيدًا عن الزرّ، ما يخلق بعض المساحة.

:where(input[type="file"])::file-selector-button {
  margin-inline-end: var(--_padding-inline);
}

لقطة شاشة تعرض الأزرار بعد تطبيق الأنماط السابقة

استثناءات خاصة للمظهر الداكن

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

@media (prefers-color-scheme: dark) {
  :where(
    [type="submit"],
    [type="reset"],
    [disabled],
    form button:not([type="button"])
  ) {
    --_bg: var(--_input-well);
  }
}

لقطة شاشة تعرض الأزرار بعد تطبيق الأنماط السابقة

إنشاء الأسعار المتغيرة

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

زرّ حيوي

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

.btn-custom {
  --_bg: linear-gradient(hsl(228 94% 67%), hsl(228 81% 59%));
  --_border: hsl(228 89% 63%);
  --_text: hsl(228 89% 100%);
  --_ink-shadow: 0 1px 0 hsl(228 57% 50%);
  --_highlight: hsl(228 94% 67% / 20%);
}

يظهر الزر المخصّص باللونَين الفاتح والداكن. وهو أزرق نابض بالحياة مثل أزرار الإجراءات الأساسية المعتادة.

زر كبير

يتمّ الحصول على نمط الزرّ هذا من خلال تعديل السمة المخصّصة --_size. تكون عناصر الحشو وعناصر المساحة الأخرى نسبية لهذا الحجم، ويتم تغيير حجمها تناسبيًا مع الحجم الجديد.

.btn-large {
  --_size: 1.5rem;
}

يظهر الزر الكبير بجانب الزر المخصّص، ويكون أكبر منه بحوالي 150 مرة.

زر الرمز

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

[data-icon="cloud"] {
  --icon-cloud: url("https://api.iconify.design/mdi:apple-icloud.svg") center / contain no-repeat;

  -webkit-mask: var(--icon-cloud);
  mask: var(--icon-cloud);
  background: linear-gradient(to bottom, var(--_accent-dark), var(--_accent-light));
}

يظهر زر يتضمّن رمزًا في المظهرَين الفاتح والداكن.

الخاتمة

الآن بعد أن عرفت كيف فعلت ذلك، كيف ستفعل ذلك؟ 🙂

لننوّع أساليبنا ونتعرّف على جميع الطرق لإنشاء تطبيقات على الويب.

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

الريمكسات التي أنشأها المستخدمون

ما مِن عناصر للاطّلاع عليها هنا حتى الآن.

الموارد