בניית רכיב של הסבר קצר

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

בפוסט הזה אני רוצה לשתף את המחשבות שלי על איך ליצור <tool-tip>רכיב בהתאמה אישית עם נגישות ועם התאמה לצבעים. אפשר לנסות את ההדגמה ולראות את המקור.

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

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

סקירה כללית

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

מה כדאי לעשות: תמיד כדאי לתייג את הקלט.
לא מומלץ: להסתמך על תיאורי כלים במקום על תוויות

הסבר קצר לעומת תיאור קצר

בדומה לרכיבים רבים, יש תיאורים שונים של מהו תיאור קצר, למשל ב-MDN,‏ WAI ARIA,‏ Sarah Higley ו-Inclusive Components. אהבתי את ההפרדה בין תיאורי הכלים לבין תיאורי המעבר. הטולטיפ צריך להכיל מידע נוסף לא אינטראקטיבי, בעוד שהטוגלטיפ יכול להכיל אינטראקטיביות ומידע חשוב. הסיבה העיקרית לפער היא נגישות. איך מצפים מהמשתמשים לנווט אל החלון הקופץ ולגשת למידע ולכפתורים שבו? הסברים קצרים הופכים למורכבים במהירות.

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

כדי לעמוד באתגר הזה, יצרנו tooltip שמתבסס כמעט כולו על CSS. כך עושים את זה.

Markup

בחרתי להשתמש באלמנט מותאם אישית <tool-tip>. אם מחברים לא רוצים, הם לא צריכים להפוך רכיבים מותאמים אישית לרכיבי אינטרנט. הדפדפן יתייחס ל-<foo-bar> בדיוק כמו אל <div>. אפשר לחשוב על רכיב מותאם אישית כמו על שם מחלקה עם פחות ספציפיות. אין שימוש ב-JavaScript.

<tool-tip>A tooltip</tool-tip>

זה כמו תג div עם טקסט בפנים. אנחנו יכולים להתחבר לעץ הנגישות של קוראי מסך מתאימים על ידי הוספת [role="tooltip"].

<tool-tip role="tooltip">A tooltip</tool-tip>

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

צילום מסך של עץ הנגישות בכלי הפיתוח ל-Chrome שמייצג את ה-HTML. הצגת קישור עם הטקסט &#39;top ; Has tooltip: Hey, a tooltip!&#39; שאפשר להתמקד בו. בתוך הרכיב הזה יש טקסט סטטי &#39;top&#39; ורכיב של תיאור קצר.

בשלב הבא צריך לוודא שאי אפשר להתמקד בתיבת הטיפים. אם קורא המסך לא מבין את התפקיד של תיאור הכלי, הוא יאפשר למשתמשים להתמקד ב-<tool-tip> כדי לקרוא את התוכן, וחוויית המשתמש לא צריכה את זה. קוראי מסך יוסיפו את התוכן לרכיב ההורה, ולכן לא צריך להגדיר את המיקוד כדי להפוך אותו לנגיש. כאן אפשר להשתמש ב-inert כדי לוודא שאף משתמש לא ימצא בטעות את תוכן הטיפ הזה ברצף הכרטיסיות שלו:

<tool-tip inert role="tooltip">A tooltip</tool-tip>

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

לאחר מכן בחרתי להשתמש במאפיינים כממשק כדי לציין את המיקום של הכלי לטיפים. כברירת מחדל, כל ה-<tool-tip>s יניחו מיקום 'עליון', אבל אפשר להתאים אישית את המיקום ברכיב על ידי הוספת tip-position:

<tool-tip role="tooltip" tip-position="right ">A tooltip</tool-tip>

צילום מסך של קישור עם תיאור קצר בצד שמאל שאומר &#39;תיאור קצר&#39;.

אני בדרך כלל משתמש במאפיינים במקום במחלקות לדברים כאלה, כדי שלא יהיו כמה מיקומים שמוקצים ל-<tool-tip> בו-זמנית. יכול להיות רק אחד או אף אחד.

לבסוף, ממקמים את האלמנטים <tool-tip> בתוך האלמנט שרוצים להוסיף לו תיאור קצר. כאן אני משתף את הטקסט alt עם משתמשים עם ראייה תקינה על ידי הצבת תמונה וalt בתוך רכיב <picture>:<tool-tip>

<picture>
  <img alt="The GUI Challenges skull logo" width="100" src="...">
  <tool-tip role="tooltip" tip-position="bottom">
    The <b>GUI Challenges</b> skull logo
  </tool-tip>
</picture>

צילום מסך של תמונה עם תיאור קצר שאומר &#39;הלוגו של הגולגולת של GUI Challenges&#39;.

כאן אני מציב <tool-tip> בתוך רכיב <abbr>:

<p>
  The <abbr>HTML <tool-tip role="tooltip" tip-position="top">Hyper Text Markup Language</tool-tip></abbr> abbr element.
</p>

צילום מסך של פסקה עם ראשי התיבות HTML שמודגשים בקו תחתון, וטיפ מעליהם עם הכיתוב &#39;Hyper Text Markup Language&#39;.

נגישות

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

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

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

צילום מסך של VoiceOver ב-MacOS קורא קישור עם תיאור קצר

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

צילום מסך של עץ הנגישות בכלי הפיתוח ל-Chrome, שבו טקסט הקישור הוא &#39;top Hey, a tooltip!&#39;.

מוסיפים פסאודו-אלמנט לקורא מסך בלבד לרכיב <tool-tip> ואז אפשר להוסיף טקסט הנחיה משלנו למשתמשים עם לקויות ראייה.

&::before {
  content: "; Has tooltip: ";
  clip: rect(1px, 1px, 1px, 1px);
  clip-path: inset(50%);
  height: 1px;
  width: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
}

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

צילום מסך מעודכן של עץ הנגישות בכלי הפיתוח ל-Chrome, שבו נוסח הטקסט של הקישור שופר: &#39;top ; Has tooltip: Hey, a tooltip!&#39;.

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

סגנונות

האלמנט <tool-tip> יהיה צאצא של האלמנט שהוא מייצג הודעות משניות עבורו, ולכן נתחיל קודם עם הרכיבים החיוניים לאפקט השכבת-העל. כדי להוציא את המסמך מזרימת המסמכים, צריך ללחוץ על position absolute:

tool-tip {
  position: absolute;
  z-index: 1;
}

אם הרכיב ההורה הוא לא הקשר הערימה, תיאור הכלים ימוקם ליד הרכיב הקרוב ביותר שהוא כן הקשר הערימה, וזה לא מה שאנחנו רוצים. יש כלי חדש לבחירת בלוקים שיכול לעזור, :has():

Browser Support

  • Chrome: 105.
  • Edge: 105.
  • Firefox: 121.
  • Safari: 15.4.

Source

:has(> tool-tip) {
  position: relative;
}

אל תדאגו יותר מדי לגבי תמיכה בדפדפן. קודם כול, חשוב לזכור שההסברים הקצרים האלה הם תוספת. אם הם לא עובדים, זה בסדר. בשלב השני, בקטע JavaScript, נטמיע סקריפט כדי להוסיף פוליפיל לפונקציונליות שאנחנו צריכים בדפדפנים ללא תמיכה ב-:has().

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

tool-tip {
  
  pointer-events: none;
  user-select: none;
}

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

tool-tip {
  opacity: 0;
}

:has(> tool-tip):is(:hover, :focus-visible, :active) > tool-tip {
  opacity: 1;
}

:is() ו-:has() מבצעים כאן את העבודה הקשה, וגורמים לאלמנטים האב שמכילים את tool-tip להיות מודעים לאינטראקטיביות של המשתמש כדי להחליף את מצב החשיפה של תיאור הכלים של הצאצא. משתמשים בעכבר יכולים להעביר את העכבר מעל הרכיב, משתמשים במקלדת ובקורא מסך יכולים להתמקד בו, ומשתמשים במגע יכולים להקיש עליו.

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

צילום מסך של תיאור הכלי במצב כהה, שמופיע מעל הקישור block-start.

tool-tip {
  --_p-inline: 1.5ch;
  --_p-block: .75ch;
  --_triangle-size: 7px;
  --_bg: hsl(0 0% 20%);
  --_shadow-alpha: 50%;

  --_bottom-tip: conic-gradient(from -30deg at bottom, rgba(0,0,0,0), #000 1deg 60deg, rgba(0,0,0,0) 61deg) bottom / 100% 50% no-repeat;
  --_top-tip: conic-gradient(from 150deg at top, rgba(0,0,0,0), #000 1deg 60deg, rgba(0,0,0,0) 61deg) top / 100% 50% no-repeat;
  --_right-tip: conic-gradient(from -120deg at right, rgba(0,0,0,0), #000 1deg 60deg, rgba(0,0,0,0) 61deg) right / 50% 100% no-repeat;
  --_left-tip: conic-gradient(from 60deg at left, rgba(0,0,0,0), #000 1deg 60deg, rgba(0,0,0,0) 61deg) left / 50% 100% no-repeat;

  pointer-events: none;
  user-select: none;

  opacity: 0;
  transform: translateX(var(--_x, 0)) translateY(var(--_y, 0));
  transition: opacity .2s ease, transform .2s ease;

  position: absolute;
  z-index: 1;
  inline-size: max-content;
  max-inline-size: 25ch;
  text-align: start;
  font-size: 1rem;
  font-weight: normal;
  line-height: normal;
  line-height: initial;
  padding: var(--_p-block) var(--_p-inline);
  margin: 0;
  border-radius: 5px;
  background: var(--_bg);
  color: CanvasText;
  will-change: filter;
  filter:
    drop-shadow(0 3px 3px hsl(0 0% 0% / var(--_shadow-alpha)))
    drop-shadow(0 12px 12px hsl(0 0% 0% / var(--_shadow-alpha)));
}

/* create a stacking context for elements with > tool-tips */
:has(> tool-tip) {
  position: relative;
}

/* when those parent elements have focus, hover, etc */
:has(> tool-tip):is(:hover, :focus-visible, :active) > tool-tip {
  opacity: 1;
  transition-delay: 200ms;
}

/* prepend some prose for screen readers only */
tool-tip::before {
  content: "; Has tooltip: ";
  clip: rect(1px, 1px, 1px, 1px);
  clip-path: inset(50%);
  height: 1px;
  width: 1px;
  margin: -1px;
  overflow: hidden;
  padding: 0;
  position: absolute;
}

/* tooltip shape is a pseudo element so we can cast a shadow */
tool-tip::after {
  content: "";
  background: var(--_bg);
  position: absolute;
  z-index: -1;
  inset: 0;
  mask: var(--_tip);
}

/* top tooltip styles */
tool-tip:is(
  [tip-position="top"],
  [tip-position="block-start"],
  :not([tip-position]),
  [tip-position="bottom"],
  [tip-position="block-end"]
) {
  text-align: center;
}

שינויים בעיצוב

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

@media (prefers-color-scheme: light) {
  tool-tip {
    --_bg: white;
    --_shadow-alpha: 15%;
  }
}

צילום מסך של הגרסה הבהירה והגרסה הכהה של תיאור הכלי, זו לצד זו.

במצב בהיר, הרקע לבן והצללים חלשים יותר כי שקיפות הצללים מותאמת.

מימין לשמאל

כדי לתמוך במצבי קריאה מימין לשמאל, מאפיין בהתאמה אישית יאחסן את הערך של כיוון המסמך בערך של -1 או 1 בהתאמה.

tool-tip {
  --isRTL: -1;
}

tool-tip:dir(rtl) {
  --isRTL: 1;
}

אפשר להשתמש בערך הזה כדי למקם את תיאור הכלים:

tool-tip[tip-position="top"]) {
  --_x: calc(50% * var(--isRTL));
}

וגם לעזור לכם לדעת איפה המשולש נמצא:

tool-tip[tip-position="right"]::after {
  --_tip: var(--_left-tip);
}

tool-tip[tip-position="right"]:dir(rtl)::after {
  --_tip: var(--_right-tip);
}

לבסוף, אפשר להשתמש ב- גם לטרנספורמציות לוגיות ב-translateX():

--_x: calc(var(--isRTL) * -3px * -1);

מיקום ההסבר הקצר

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

יישור למעלה ולתחילת הבלוק

צילום מסך שבו רואים את ההבדל במיקום בין מיקום עליון משמאל לימין לבין מיקום עליון מימין לשמאל.

tool-tip:is([tip-position="top"], [tip-position="block-start"], :not([tip-position])) {
  inset-inline-start: 50%;
  inset-block-end: calc(100% + var(--_p-block) + var(--_triangle-size));
  --_x: calc(50% * var(--isRTL));
}

tool-tip:is([tip-position="top"], [tip-position="block-start"], :not([tip-position]))::after {
  --_tip: var(--_bottom-tip);
  inset-block-end: calc(var(--_triangle-size) * -1);
  border-block-end: var(--_triangle-size) solid transparent;
}

יישור לימין ולסוף השורה

צילום מסך שמראה את ההבדל במיקום בין מיקום מימין משמאל לימין לבין מיקום בסוף השורה מימין לשמאל.

tool-tip:is([tip-position="right"], [tip-position="inline-end"]) {
  inset-inline-start: calc(100% + var(--_p-inline) + var(--_triangle-size));
  inset-block-end: 50%;
  --_y: 50%;
}

tool-tip:is([tip-position="right"], [tip-position="inline-end"])::after {
  --_tip: var(--_left-tip);
  inset-inline-start: calc(var(--_triangle-size) * -1);
  border-inline-start: var(--_triangle-size) solid transparent;
}

tool-tip:is([tip-position="right"], [tip-position="inline-end"]):dir(rtl)::after {
  --_tip: var(--_right-tip);
}

יישור לתחתית ולסוף הבלוק

צילום מסך שמראה את ההבדל במיקום בין מיקום מלמטה משמאל לימין לבין מיקום בסוף הבלוק מימין לשמאל.

tool-tip:is([tip-position="bottom"], [tip-position="block-end"]) {
  inset-inline-start: 50%;
  inset-block-start: calc(100% + var(--_p-block) + var(--_triangle-size));
  --_x: calc(50% * var(--isRTL));
}

tool-tip:is([tip-position="bottom"], [tip-position="block-end"])::after {
  --_tip: var(--_top-tip);
  inset-block-start: calc(var(--_triangle-size) * -1);
  border-block-start: var(--_triangle-size) solid transparent;
}

יישור לשמאל ולתחילת השורה

צילום מסך שמראה את ההבדל במיקום בין מיקום משמאל לימין בצד שמאל לבין מיקום מימין לשמאל בתחילת השורה.

tool-tip:is([tip-position="left"], [tip-position="inline-start"]) {
  inset-inline-end: calc(100% + var(--_p-inline) + var(--_triangle-size));
  inset-block-end: 50%;
  --_y: 50%;
}

tool-tip:is([tip-position="left"], [tip-position="inline-start"])::after {
  --_tip: var(--_right-tip);
  inset-inline-end: calc(var(--_triangle-size) * -1);
  border-inline-end: var(--_triangle-size) solid transparent;
}

tool-tip:is([tip-position="left"], [tip-position="inline-start"]):dir(rtl)::after {
  --_tip: var(--_left-tip);
}

Animation

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

מעבר בטוח ומשמעותי לברירת מחדל

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

tool-tip {
  opacity: 0;
  transform: translateX(var(--_x, 0)) translateY(var(--_y, 0));
  transition: opacity .2s ease, transform .2s ease;
}

:has(> tool-tip):is(:hover, :focus-visible, :active) > tool-tip {
  opacity: 1;
  transition-delay: 200ms;
}

הוספת תנועה למעבר

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

@media (prefers-reduced-motion: no-preference) {
  :has(> tool-tip:is([tip-position="top"], [tip-position="block-start"], :not([tip-position]))):not(:hover):not(:focus-visible):not(:active) tool-tip {
    --_y: 3px;
  }

  :has(> tool-tip:is([tip-position="right"], [tip-position="inline-end"])):not(:hover):not(:focus-visible):not(:active) tool-tip {
    --_x: -3px;
  }

  :has(> tool-tip:is([tip-position="bottom"], [tip-position="block-end"])):not(:hover):not(:focus-visible):not(:active) tool-tip {
    --_y: -3px;
  }

  :has(> tool-tip:is([tip-position="left"], [tip-position="inline-start"])):not(:hover):not(:focus-visible):not(:active) tool-tip {
    --_x: 3px;
  }
}

שימו לב שההגדרה הזו היא של מצב 'יציאה', כי מצב 'כניסה' הוא translateX(0).

JavaScript

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

סקריפט ה-polyfill עושה שני דברים, והוא עושה אותם רק אם הדפדפן לא תומך ב-:has(). קודם כל, בודקים אם יש תמיכה ב:has():

if (!CSS.supports('selector(:has(*))')) {
  // do work
}

בשלב הבא, מאתרים את רכיבי ההורה של רכיבי <tool-tip> ונותנים להם שם מחלקה שאפשר לעבוד איתו:

if (!CSS.supports('selector(:has(*))')) {
  document.querySelectorAll('tool-tip').forEach(tooltip =>
    tooltip.parentNode.classList.add('has_tool-tip'))
}

לאחר מכן, מחדירים קבוצה של סגנונות שמשתמשים בשם המחלקה הזה, ומדמים את הבורר :has() כדי לקבל בדיוק את אותה התנהגות:

if (!CSS.supports('selector(:has(*))')) {
  document.querySelectorAll('tool-tip').forEach(tooltip =>
    tooltip.parentNode.classList.add('has_tool-tip'))

  let styles = document.createElement('style')
  styles.textContent = `
    .has_tool-tip {
      position: relative;
    }
    .has_tool-tip:is(:hover, :focus-visible, :active) > tool-tip {
      opacity: 1;
      transition-delay: 200ms;
    }
  `
  document.head.appendChild(styles)
}

זהו, עכשיו כל הדפדפנים יציגו את תיאורי הכלים אם הם לא תומכים ב-:has().

סיכום

עכשיו, אחרי שסיפרתי לך איך עשיתי את זה, איך היית עושה את זה‽ 🙂 אני ממש מחכה ל-API של popup כדי להקל על יצירת בועות מידע, ל-top layer כדי להימנע מבעיות עם z-index, ול-API של anchor כדי לשפר את המיקום של רכיבים בחלון. עד אז, אצור תיאורי כלים.

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

אפשר ליצור סרטון הדגמה, לצייץ לי קישורים, ואוסיף אותו לקטע של רמיקסים מהקהילה שבהמשך!

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

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

משאבים