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

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

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

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

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

סקירה כללית

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

מומלץ: תמיד לסמן את הקלט.
לא מומלץ: להסתמך על תיאורים מפורטים במקום על תוויות

Toggletip לעומת הסבר קצר

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

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

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

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

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

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

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

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

<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;The GUI Challenges skull logo&#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 שקורא קישור עם תיאור קצר

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

צילום מסך של עץ הנגישות בכלי הפיתוח ל-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;.

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

סגנונות

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

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

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

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

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

מקור

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

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

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

צילום מסך של תיאור הכלי במצב כהה, מרחף מעל הקישור &#39;block-start&#39;.

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

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

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

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

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

שימו לב שהקוד הזה מגדיר את המצב 'out', כי המצב 'in' נמצא ב-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 כדי שיהיה קל יותר ליצור טיפים להפעלה/השבתה, ל-שכבת-על כדי שלא תצטרכו להילחם עם z-index, ול-API של anchor כדי למקם דברים בחלון בצורה טובה יותר. עד אז, אמשיך ליצור תוויות עזר.

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

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

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

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

משאבים