टूलटिप कॉम्पोनेंट बनाना

रंग के हिसाब से बदलने वाला और ऐक्सेस किया जा सकने वाला टूलटिप कस्टम एलिमेंट बनाने का बुनियादी तरीका.

इस पोस्ट में, मैं रंग के हिसाब से अडजस्ट होने वाले और ऐक्सेस किए जा सकने वाले <tool-tip> कस्टम एलिमेंट बनाने का तरीका शेयर करना चाहता/चाहती हूं. डेमो आज़माएं और सोर्स देखें!

अलग-अलग उदाहरणों और कलर स्कीम में काम करने वाला टूलटिप दिखाया गया है

अगर आपको वीडियो देखना पसंद है, तो यहां इस पोस्ट का YouTube वर्शन दिया गया है:

खास जानकारी

टूलटिप, यूज़र इंटरफ़ेस के लिए अतिरिक्त जानकारी देने वाला ऐसा ओवरले होता है जो न तो मोडल होता है, न ब्लॉक करता है और न ही इंटरैक्टिव होता है. यह डिफ़ॉल्ट रूप से छिपा होता है. हालांकि, इससे जुड़े एलिमेंट पर कर्सर घुमाने या उस पर फ़ोकस करने पर, यह दिखने लगता है. टूलटिप को सीधे तौर पर चुना या उससे इंटरैक्ट नहीं किया जा सकता. टूलटिप, लेबल या अन्य अहम जानकारी की जगह नहीं लेते. उपयोगकर्ता को टूलटिप के बिना भी अपना टास्क पूरा करना चाहिए.

ऐसा करें: अपने इनपुट को हमेशा लेबल करें.
ऐसा न करें: लेबल के बजाय टूलटिप पर भरोसा करें

टॉगलटिप बनाम टूलटिप

कई कॉम्पोनेंट की तरह, टूलटिप के बारे में अलग-अलग तरह की जानकारी दी गई है. उदाहरण के लिए, MDN, WAI ARIA, सारा हिगले, और Inclusive Components में. मुझे टूलटिप और टॉगलटिप के बीच का अंतर पसंद है. टूलटिप में ऐसी जानकारी होनी चाहिए जो इंटरैक्टिव न हो. वहीं, टॉगलटिप में इंटरैक्टिव और ज़रूरी जानकारी हो सकती है. इस फ़र्क़ की मुख्य वजह, ऐक्सेस है. उपयोगकर्ताओं को पॉप-अप पर कैसे जाना चाहिए और उसमें मौजूद जानकारी और बटन को कैसे ऐक्सेस करना चाहिए. टॉगलटिप बहुत जल्दी जटिल हो जाते हैं.

यहां Designcember साइट पर मौजूद टॉगलटिप का वीडियो दिया गया है. यह एक इंटरैक्टिव ओवरले है, जिसे उपयोगकर्ता पिन करके खोल सकता है और एक्सप्लोर कर सकता है. इसके बाद, उसे लाइट डिसमिज़ या 'बचें' बटन दबाकर बंद किया जा सकता है:

इस जीयूआई चैलेंज में, सीएसएस की मदद से ज़्यादा से ज़्यादा काम करने की कोशिश की गई है. इसे बनाने का तरीका यहां बताया गया है.

मार्कअप

मैंने कस्टम एलिमेंट <tool-tip> का इस्तेमाल करने का विकल्प चुना है. अगर लेखकों को वेब कॉम्पोनेंट में कस्टम एलिमेंट नहीं बनाने हैं, तो उन्हें ऐसा करने की ज़रूरत नहीं है. ब्राउज़र, <foo-bar> को <div> की तरह ही इस्तेमाल करेगा. किसी कस्टम एलिमेंट के बारे में सोचा जा सकता है, जैसे कि कम जानकारी वाले क्लास के नाम. इसमें JavaScript का इस्तेमाल नहीं किया जाता.

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

यह किसी ऐसे डिव की तरह है जिसमें कुछ टेक्स्ट है. [role="tooltip"] जोड़कर, हम स्क्रीन रीडर के सुलभता ट्री से जुड़ सकते हैं.

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

अब स्क्रीन रीडर के लिए, इसे टूलटिप के तौर पर पहचाना जाता है. नीचे दिए गए उदाहरण में देखें कि पहले लिंक एलिमेंट के ट्री में टूलटिप एलिमेंट कैसे मौजूद है और दूसरे में नहीं? दूसरे व्यक्ति को भूमिका नहीं दी गई है. स्टाइल सेक्शन में, हम इस ट्री व्यू को बेहतर बनाएंगे.

Chrome DevTools के सुलभता ट्री का स्क्रीनशॉट, जिसमें एचटीएमएल दिखाया गया है. &#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> "टॉप" पोज़िशन पर दिखेंगे. हालांकि, tip-position जोड़कर किसी एलिमेंट की पोज़िशन को पसंद के मुताबिक़ बनाया जा सकता है:

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

ऐसे लिंक का स्क्रीनशॉट जिसकी दाईं ओर &#39;टूलटिप&#39; लिखा हुआ है.

इस तरह की चीज़ों के लिए, मैं क्लास के बजाय एट्रिब्यूट का इस्तेमाल करता/करती हूं, ताकि <tool-tip> को एक ही समय पर कई पोज़िशन असाइन न की जा सकें. इसमें सिर्फ़ एक या कोई भी नहीं हो सकता.

आखिर में, उस एलिमेंट के अंदर <tool-tip> एलिमेंट डालें जिसके लिए आपको टूलटिप देना है. यहां मैंने <picture> एलिमेंट में एक इमेज और <tool-tip> डालकर, alt टेक्स्ट को उन उपयोगकर्ताओं के साथ शेयर किया है जो देख सकते हैं:

<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; टूलटिप वाली इमेज का स्क्रीनशॉट.

यहां मैंने <abbr> एलिमेंट के अंदर एक <tool-tip> रखा है:

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

एक पैराग्राफ का स्क्रीनशॉट, जिसमें एचटीएमएल के नाम के पहले अक्षरों को अंडरलाइन किया गया है. साथ ही, उसके ऊपर &#39;हाइपर टेक्स्ट मार्कअप लैंग्वेज&#39; लिखा हुआ टूलटिप है.

सुलभता

मैंने टूलटिप बनाने का विकल्प चुना है, न कि टॉगलटिप बनाने का. इसलिए, यह सेक्शन काफ़ी आसान है. सबसे पहले, हम आपको बताना चाहते हैं कि हमें उपयोगकर्ताओं के लिए कैसा अनुभव देना है:

  1. सीमित जगह या गड़बड़ी वाले इंटरफ़ेस में, अतिरिक्त मैसेज छिपाएं.
  2. जब कोई उपयोगकर्ता किसी एलिमेंट के साथ इंटरैक्ट करने के लिए, उस पर कर्सर घुमाता है, फ़ोकस करता है या टच का इस्तेमाल करता है, तो मैसेज दिखाएं.
  3. कर्सर घुमाने, फ़ोकस करने या टच करने की कार्रवाई खत्म होने पर, मैसेज को फिर से छिपाएं.
  4. आखिर में, पक्का करें कि अगर उपयोगकर्ता ने कम मोशन की प्राथमिकता तय की है, तो किसी भी मोशन को कम किया जाए.

हमारा लक्ष्य, मांग के हिसाब से अतिरिक्त मैसेज भेजना है. माउस या कीबोर्ड का इस्तेमाल करने वाला कोई व्यक्ति, कर्सर घुमाकर मैसेज को पढ़ सकता है. स्क्रीन रीडर का इस्तेमाल करने वाला कोई व्यक्ति, अपने टूल की मदद से मैसेज को सुन सकता है.

MacOS VoiceOver की मदद से, टूलटिप वाले लिंक को पढ़ते हुए दिखाने वाला स्क्रीनशॉट

पिछले सेक्शन में, हमने ऐक्सेसibiliy ट्री, टूलटिप की भूमिका, और इनऐक्टिव के बारे में बताया था. अब हमें इसकी जांच करनी है और यह पुष्टि करनी है कि उपयोगकर्ता को टूलटिप मैसेज सही तरीके से दिख रहा है या नहीं. जांच करने पर, यह पता नहीं चल पा रहा है कि बोलकर सुनाए जाने वाले मैसेज का कौनसा हिस्सा टूलटिप है. यह ऐक्सेसibiliy ट्री में डीबग करते समय भी देखा जा सकता है. "देखो, टूलटिप!" के साथ "टॉप" के लिंक टेक्स्ट को बिना किसी झिझक के एक साथ चलाया जाता है. स्क्रीन रीडर, टेक्स्ट को टूलटिप कॉन्टेंट के तौर पर नहीं पढ़ता या उसकी पहचान नहीं करता.

Chrome DevTools के ऐक्सेसबिलिटी ट्री का स्क्रीनशॉट, जिसमें लिंक टेक्स्ट में &#39;शीर्ष 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;
}

यहां आपको सुलभता ट्री का अपडेट किया गया वर्शन दिख रहा है. इसमें अब लिंक टेक्स्ट के बाद सेमीकोलन है. साथ ही, टूलटिप के लिए "Has tooltip: " प्रॉम्प्ट है.

Chrome DevTools के सुलभता ट्री का अपडेट किया गया स्क्रीनशॉट, जिसमें लिंक टेक्स्ट के फ़्रेज़ को बेहतर बनाया गया है. जैसे, &#39;top ; Has tooltip: Hey, a tooltip!&#39;.

अब, जब स्क्रीन रीडर का इस्तेमाल करने वाला व्यक्ति लिंक पर फ़ोकस करता है, तो वह "टॉप" कहता है और थोड़ा विराम लेता है. इसके बाद, "इसमें टूलटिप है: देखें, टूलटिप" कहता है. इससे, स्क्रीन रीडर का इस्तेमाल करने वाले उपयोगकर्ता को यूज़र एक्सपीरियंस के बारे में कुछ अच्छे सुझाव मिलते हैं. इसकी मदद से, लिंक टेक्स्ट और टूलटिप के बीच काफ़ी अंतर दिखता है. इसके अलावा, अगर "टूलटिप है" का एलान किया जाता है, तो स्क्रीन रीडर का इस्तेमाल करने वाला व्यक्ति इसे आसानी से रद्द कर सकता है. ऐसा तब किया जा सकता है, जब उसने पहले ही इस एलान को सुना हो. यह थोड़ा हॉवर करने और तुरंत हटाने जैसा है, क्योंकि आपने पहले ही ज़्यादा जानकारी वाला मैसेज देख लिया है. ऐसा लगा कि यूज़र एक्सपीरियंस (यूएक्स) में कोई अंतर नहीं है.

स्टाइल

<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() के बिना काम करने वाले ब्राउज़र के लिए, ज़रूरी फ़ंक्शन को पॉलीफ़िल किया जा सके.

इसके बाद, टूलटिप को इंटरैक्टिव न बनाएं, ताकि वे अपने पैरंट एलिमेंट से पॉइंटर इवेंट न चुरा सकें:

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

ऐनिमेशन

अब तक, हमने सिर्फ़ टूलटिप की दिखने की सुविधा को टॉगल किया है. इस सेक्शन में, हम सबसे पहले सभी उपयोगकर्ताओं के लिए ऐनिमेशन के साथ ओपैसिटी को कम करेंगे. आम तौर पर, यह कम मोशन वाला ट्रांज़िशन सुरक्षित होता है. इसके बाद, हम ट्रांसफ़ॉर्म पोज़िशन को ऐनिमेट करेंगे, ताकि टूलटिप, पैरंट एलिमेंट से स्लाइड आउट करता हुआ दिखे.

सुरक्षित और काम का डिफ़ॉल्ट ट्रांज़िशन

ओपैसिटी और ट्रांसफ़ॉर्मेशन में बदलाव करने के लिए, टूलटिप एलिमेंट को स्टाइल करें. जैसे:

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() के काम न करने पर टूलटिप दिखाएंगे.

नतीजा

अब आपको पता है कि मैंने इसे कैसे किया, तो आप इसे कैसे करेंगे‽ 🙂 मुझे popup एपीआई का बेसब्री से इंतज़ार है, ताकि टॉगलटिप को आसानी से बनाया जा सके. साथ ही, टॉप लेयर की मदद से, z-index से जुड़ी समस्याओं को हल किया जा सके. इसके अलावा, anchor एपीआई की मदद से, विंडो में चीज़ों को बेहतर तरीके से पोज़िशन किया जा सके. तब तक, मैं टूलटिप बना रहा हूँ.

आइए, अलग-अलग तरीकों का इस्तेमाल करके, वेब पर कॉन्टेंट बनाने के सभी तरीके जानें.

डेमो बनाएं और मुझे ट्वीट करें लिंक भेजें. हम इसे कम्यूनिटी रीमिक्स सेक्शन में जोड़ देंगे!

कम्यूनिटी रीमिक्स

फ़िलहाल, यहां देखने के लिए कुछ नहीं है.

संसाधन