بناء مكون زر

نظرة عامة أساسية حول طريقة تصميم مكوّنات <button> تراعي الألوان وسريعة الاستجابة ويسهل الوصول إليها

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

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

في ما يلي إصدار YouTube من هذه المشاركة إذا كنت تفضّل الفيديوهات:

نظرة عامة

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

  • 1
  • 12
  • 1
  • 4 أو أقل

المصدر

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

هناك أيضًا أنواع مختلفة من الأزرار، ويعرض كل منها في تضمين 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 هنا لفحص كل نتائجه وعرضها في وقت واحد:

إخفاء الأيقونات عن الأشخاص الذين لا يمكنهم الرؤية

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

<button>
  <svg … aria-hidden="true">...</svg>
  Icon Button
</button>
&quot;أدوات مطوري البرامج في Chrome&quot; تعرض شجرة تسهيل الاستخدام للزر تتجاهل الشجرة صورة الزر لأنها تتضمن مجموعة aria-hidden على true.
"أدوات مطوري البرامج في Chrome" تعرض شجرة تسهيل الاستخدام للزر. تتجاهل الشجرة صورة الزر لأنّها تتضمّن ضبط 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 في إنشاء الصورة الوهمية:

--_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 لضمان عدم الحاجة إلى الانتظار وملاحظة نقرة مزدوجة محتملة، ما يجعل الأزرار أسرع:

: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);
}

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

التنسيق

منحت الزر تنسيق flexbox، وتحديدًا تنسيق 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 لمنع الأشقاء من اللمس والخصائص المنطقية للمساحة المتروكة بحيث يعمل تباعد الأزرار مع جميع تنسيقات النص.

: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) هي ميزات أزرار أخرى تركّز على الويب ولا تتوافق مع التوقعات العامة للمستخدمين بشأن الأزرار، لذلك أزيلها أيضًا.

: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 حتى اجتياز النتيجة في أدوات مطوّري البرامج أو 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);
}

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

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

زر إدخال الملف هو حاوية مسافة وزر. يمكن لـ 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));
}

يظهر زر مع رمز بمظهر فاتح وداكن.

الخلاصة

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

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

يمكنك إنشاء عرض توضيحي وروابط تغريدات لي وسنضيفها إلى قسم الريمكسات في المنتدى أدناه.

ريمكسات من المنتدى

لا يتوفّر أي محتوى بعد.

المراجِع