בניית רכיב לחצן

סקירה כללית בסיסית של יצירת רכיבי <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">

באתגר GUI של החודש, כל לחצן יקבל סגנונות שיעזרו להבדיל באופן חזותי בין הכוונה שלהם. ללחצני איפוס יהיו צבעי אזהרה כי הם הרסניים, ולחצני השליחה יקבלו טקסט משני כחול כך שהם יופיעו מעט יותר מקודמות מלחצנים רגילים.

תצוגה מקדימה של הקבוצה הסופית של כל סוגי הלחצנים, המוצגת בטופס ולא בטופס, עם תוספות נחמדות ללחצני סמלים ולחצנים מותאמים אישית.
תצוגה מקדימה של הקבוצה הסופית של כל סוגי הלחצנים, שמוצגת בטופס ולא בצורת

ללחצנים יש גם מחלקות (פסאודו-מחלקות) שבהן CSS יכול להשתמש לעיצוב. השיעורים האלה מספקים קטעי הוק (hooks) ל-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>
כלי הפיתוח ל-Chrome שבו מוצג עץ הנגישות של הלחצן. העץ מתעלם מתמונת הלחצן מפני שההסתרה של ARIA מוגדרת כ-true.
כלי הפיתוח ל-Chrome שבו מוצגים עץ הנגישות של הלחצן. העץ מתעלם מתמונת הלחצן כי ההסתרה של ARIA מוגדרת כ-True

סגנונות

בקטע הבא נסביר קודם מערכת של מאפיינים מותאמים אישית לניהול הסגנונות המותאמים של הלחצן. בעזרת המאפיינים המותאמים אישית האלה אני יכול להתחיל לבחור רכיבים ולהתאים אישית את המראה שלהם.

אסטרטגיה מותאמת של נכסים מותאמים אישית

האסטרטגיה של הנכסים המותאמים אישית שבה משתמשים באתגר הזה של ממשק GUI דומה מאוד לזו שמשמשת לבניית ערכת צבעים. במערכות מותאמות של צבעים בהירים וצבעים כהים, מאפיין מותאם אישית לכל עיצוב מוגדר ונקרא בהתאם. לאחר מכן מאפיין מותאם אישית אחד משמש לשמירת הערך הנוכחי של העיצוב, ומוקצה למאפיין 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 המותאם מוקצה לנכס המעבר:

: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 יכול לעצב קצת את מאגר הקלט, וגם את הלחצן המקונן, אבל לא את ה-span. הקונטיינר מקבל את הערך 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%);
}

הלחצן &#39;התאמה אישית&#39; מוצג בצבע בהיר ובכהה. הלחצן הזה הוא כחול עז מאוד, כמו שלחצני פעולה ראשיים טיפוסיים הם בדרך כלל.

לחצן גדול

סגנון הלחצן הזה נוצר על ידי שינוי המאפיין המותאם אישית --_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));
}

לחצן עם סמל מוצג בעיצוב בהיר או בעיצוב כהה.

סיכום

עכשיו, אחרי שאת יודעת איך עשיתי את זה, איך היית רוצה ‽ 🙂

בואו נגוון את הגישות שלנו ונלמד את כל הדרכים לבנות באינטרנט.

צור הדגמה (דמו), ציוץ לי קישורים ואני אוסיף אותה לקטע 'רמיקסים של הקהילה' למטה!

רמיקסים של הקהילה

עדיין אין כאן מה לראות.

משאבים