בניית רכיב של לחצן פעולה צף (FAB)

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

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

אם ברצונך ליצור סרטון, הנה גרסת YouTube של הפוסט הזה:

סקירה כללית

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

אלמנטים וסגנונות

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

מאגר FAB

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

תגי עיצוב של FAB

מתחילים עם המחלקה .fabs שה-CSS יכול להתחבר אליה בתור סגנון, ואז מוסיפים את role="group" ואת aria-label כך שלא יהיה רק קונטיינר גנרי, יש לו שם ותכליתי.

<div class="fabs" role="group" aria-label="Floating action buttons">
  <!-- buttons will go here -->
</div>

סגנון FAB

כדי שפריטי ה-FAB יהיו נוחות, הם נצמדים לאזור התצוגה כל הזמן. זה תרחיש מצוין למיקום fixed. בחרתי להשתמש ב-inset-block וב-inset-inline במיקום של אזור התצוגה, כדי שיתאים למצב המסמך של המשתמש, כמו מימין לשמאל או משמאל לימין. מאפיינים מותאמים אישית משמשים גם למניעת חזרות ולהבטיח מרחק שווה מהקצה התחתון ומהקצה הצדדי של אזור התצוגה:

.fabs {
  --_viewport-margin: 2.5vmin;

  position: fixed;
  z-index: var(--layer-1);

  inset-block: auto var(--_viewport-margin);
  inset-inline: auto var(--_viewport-margin);
}

לאחר מכן, נותנים לתצוגה של הקונטיינר flex ומשנים את כיוון הפריסה ל-column-reverse. כך הילדים יקובצו אחד על השני (עמודה) וגם הפכת את הסדר החזותי שלהם. באופן כזה, האלמנט הראשון שניתן להתמקד בו הוא הרכיב התחתון ולא החלק העליון, כך שהמיקוד עובר בדרך כלל לפי מסמך ה-HTML. היפוך הסדר החזותי מאחד את החוויה של משתמשים רואים ומשתמשי מקלדת, כי העיצוב של הפעולה הראשית גדול יותר מהלחצנים המקוצרים מרמז למשתמשים שזו הפעולה הראשית, ומשתמשי המקלדת יתמקדו בה בתור הפריט הראשון במקור.

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

.fabs {
  …

  display: flex;
  flex-direction: column-reverse;
  place-items: center;
  gap: var(--_viewport-margin);
}

המרכוז מטופל באמצעות place-items, ו-gap מוסיף רווח בין לחצני FAB שנמצאים בקונטיינר.

לחצני FAB

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

לחצן FAB שמוגדר כברירת מחדל

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

תגי עיצוב של FAB

הרכיב <button> הוא הבחירה הנכונה. נתחיל עם המוצר הזה כבסיס משום שהוא מספק חוויית משתמש מעולה בעכבר, במגע ובמקלדת. ההיבט החשוב ביותר בתגי העיצוב הוא להסתיר את הסמל מהמשתמשים בקורא מסך באמצעות aria-hidden="true", ולהוסיף את טקסט התווית הנדרש לתגי העיצוב של <button> עצמם. במקרים כאלה, אני רוצה להוסיף תוויות גם בעזרת title, כך שמשתמשי העכבר יוכלו לקבל מידע על מה שהסמל מקווה להעביר.

<button data-icon="plus" class="fab" title="Add new action" aria-label="Add new action">
  <svg aria-hidden="true" width="24" height="24" viewBox="0 0 24 24">...</svg>
</button>

סגנון FAB

קודם כל נהפוך את הלחצן ללחצן עגול מרופד עם צל חזק, מכיוון שאלו התכונות הראשונות של הלחצן:

.fab {
  --_size: 2rem;

  padding: calc(var(--_size) / 2);
  border-radius: var(--radius-round);
  aspect-ratio: 1;
  box-shadow: var(--shadow-4);
}

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

.fab {
  …

  /* light button and button hover */
  --_light-bg: var(--pink-6);
  --_light-bg-hover: var(--pink-7);

  /* dark button and button hover */
  --_dark-bg: var(--pink-4);
  --_dark-bg-hover: var(--pink-3);

  /* adaptive variables set to light by default */
  --_bg: var(--_light-bg);

  /* static icon colors set to the adaptive foreground variable */
  --_light-fg: white;
  --_dark-fg: black;
  --_fg: var(--_light-fg);

  /* use the adaptive properties on some styles */
  background: var(--_bg);
  color: var(--_fg);

  &:is(:active, :hover, :focus-visible) {
    --_bg: var(--_light-bg-hover);

    @media (prefers-color-scheme: dark) {
      --_bg: var(--_dark-bg-hover);
    }
  }

  /* if users prefers dark, set adaptive props to dark */
  @media (prefers-color-scheme: dark) {
    --_bg: var(--_dark-bg);
    --_fg: var(--_dark-fg);
  }
}

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

.fab {
  …

  & > svg {
    inline-size: var(--_size);
    block-size: var(--_size);
    stroke-width: 3px;
  }
}

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

.fab {
  -webkit-tap-highlight-color: transparent;
}

מיני FAB

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

תגי עיצוב של Mini FAB

ה-HTML זהה ל-FAB, אבל אנחנו מוסיפים מחלקה ".mini" כדי לתת ל-CSS חיבור לגרסה.

<button data-icon="heart" class="fab mini" title="Like action" aria-label="Like action">
  <svg aria-hidden="true" width="24" height="24" viewBox="0 0 24 24">...</svg>
</button>
סגנון Mini FAB

בעקבות השימוש במאפיינים מותאמים אישית, השינוי היחיד שנדרש הוא התאמה של המשתנה --_size.

.fab.mini {
  --_size: 1.25rem;
}

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

נגישות

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

הדגמה של אינטראקציה עם המקלדת

אחרי שהמשתמשים מתמקדים במאגר ה-FAB, כבר הוספנו את הערכים role="group" ו-aria-label="floating action buttons", שמאפשרים למשתמשים בקוראי מסך לדעת במה הם התמקדו. באופן אסטרטגי, הצבתי תחילה את ברירת המחדל של הלחצן הראשי, כדי שהמשתמשים ימצאו קודם את הפעולה הראשית. לאחר מכן אני משתמש ב-flex-direction: column-reverse; כדי לסדר באופן חזותי את הלחצן הראשי בחלק התחתון, קרוב לאצבעות המשתמשים לצורך גישה נוחה. זה יתרון נחמד כי לחצן ברירת המחדל בולט לעין באופן חזותי, והוא ראשון גם עבור משתמשי המקלדת, ומספק להם חוויות דומות מאוד.

לסיום, חשוב להסתיר את הסמלים מפני משתמשים בקורא המסך, ולוודא שתוסיפו להם תווית ללחצן כדי שהיא תישאר תעלומה. הפעולה הזו בוצעה ב-HTML עם aria-hidden="true" ב-<svg> וב-aria-label="Some action" ב-<button>.

Animation

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

אסטרטגיה של צמצום התנועה עם מאפיינים מותאמים אישית

נוצרים שלושה מאפיינים מותאמים אישית ב-CSS הבא: --_motion-reduced, --_motion-ok ו---_transition. שני הסוגים הראשונים מחזיקים מעברים מתאימים בהתאם להעדפות של המשתמש, והמשתנה האחרון --_transition יוגדר בתור --_motion-reduced או --_motion-ok בהתאמה.

.fab {
  /* box-shadow and background-color can safely be transitioned for reduced motion users */
  --_motion-reduced:
    box-shadow .2s var(--ease-3),
    background-color .3s var(--ease-3);

  /* add transform and outline-offset for users ok with motion */
  --_motion-ok:
    var(--_motion-reduced),
    transform .2s var(--ease-3),
    outline-offset 145ms var(--ease-2);

  /* default the transition styles to reduced motion */
  --_transition: var(--_motion-reduced);

  /* set the transition to our adaptive transition custom property*/
  transition: var(--_transition);

  /* if motion is ok, update the adaptive prop to the respective transition prop */
  @media (prefers-reduced-motion: no-preference) {
    --_transition: var(--_motion-ok);
  }
}

בעזרת ההגדרות שלמעלה, אפשר להעביר את השינויים ב-box-shadow, ב-background-color, ב-transform וב-outline-offset, וכך לתת למשתמש משוב נחמד לגבי ממשק המשתמש על כך שהאינטראקציה שלו התקבלה.

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

.fab {
  …

  &:active {
    @media (prefers-reduced-motion: no-preference) {
      transform: translateY(2%);
    }
  }
}

לבסוף, מבצעים את השינויים הרצויים בסמלי SVG בלחצנים:

.fab {
  …

  &[data-icon="plus"]:hover > svg {
    transform: rotateZ(.25turn);
  }

  & > svg {
    @media (prefers-reduced-motion: no-preference) {
      will-change: transform;
      transition: transform .5s var(--ease-squish-3);
    }
  }
}

סיכום

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

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

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

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

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

משאבים