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

סקירה כללית בסיסית על יצירת רכיבי <button> עם התאמה לצבע, תגובה נגישה.

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

העיצוב של הלחצנים מתבצע באמצעות המקלדת והעכבר בעיצובים כהים או בהירים.

אם אתם מעדיפים סרטון, הנה גרסה של הפוסט הזה ב-YouTube:

סקירה כללית

תמיכה בדפדפנים

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

מקור

הרכיב <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 לקביעת סגנון. המחלקות האלה מספקות הוק של 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 שמוצגים בהם עץ הנגישות של הלחצן. העץ מתעלם מתמונת הלחצן כי הוא מוגדר כ-true.
כלי הפיתוח ל-Chrome שמוצג בו עץ הנגישות של הלחצן. המערכת מתעלמת מתמונת הלחצן כי האפשרות aria-hidden מוגדרת כ-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%));

בנוסף, כדי לתת ללחצנים מראה קצת תלת-ממדי, הוספת box-shadow‏ 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);
  }
}

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

התאמות לתנועה מופחתת

אם המשתמש הזה בסדר עם התנועה, מקצים את --_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 ל-none. צבעי הדגשה בהקשה (-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 עד שהציון עמד בדרישות ב-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 של הלחצן כדי לדחוף את טקסט ה-span מהלחצן וליצור רווח.

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

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

סיכום

עכשיו, אחרי שסיפרתי לך איך עשיתי את זה, איך היית עושה את זה? 🙂

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

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

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

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

משאבים