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

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

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

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

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

खास जानकारी

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

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

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

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

यहां डिज़ाइनसेंबर साइट के टॉगल का एक वीडियो दिया गया है. इंटरैक्टिविटी दिखाने वाला एक ओवरले, जिसे उपयोगकर्ता पिन करके एक्सप्लोर कर सकता है, फिर लाइट खारिज करने या एस्केप कुंजी से बंद कर सकता है:

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

मार्कअप

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

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

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

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

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


एचटीएमएल को दिखाने वाले Chrome DevTools की सुलभता ट्री का स्क्रीनशॉट. ऐसा लिंक दिखाता है
जिस पर फ़ोकस किया जा सकता है. &#39;सबसे ऊपर&#39;; इस टूलटिप में टूलटिप है: नमस्ते, एक टूलटिप!&#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 ट्री में डीबग करते समय भी देखा जा सकता है. "देखो, टूलटिप!" के साथ "टॉप" के लिंक टेक्स्ट को बिना किसी झिझक के एक साथ चलाया जाता है. स्क्रीन रीडर, टेक्स्ट को टूलटिप कॉन्टेंट के तौर पर नहीं पढ़ता या उसकी पहचान नहीं करता.

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

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

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

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

स्टाइल

<tool-tip> एलिमेंट, उस एलिमेंट का चाइल्ड एलिमेंट होगा जिसके लिए वह अतिरिक्त मैसेज दिखा रहा है. इसलिए, सबसे पहले ओवरले इफ़ेक्ट के लिए ज़रूरी चीज़ों के बारे में जानें. position absolute का इस्तेमाल करके, इसे दस्तावेज़ फ़्लो से हटाएं:

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

अगर पैरंट, स्टैकिंग कॉन्टेक्स्ट नहीं है, तो टूलटिप अपने-आप सबसे नज़दीकी स्टैकिंग कॉन्टेक्स्ट पर दिखेगा. हालांकि, हमें ऐसा नहीं करना है. ब्लॉक में एक नया सिलेक्टर दिया गया है, जिससे आपको मदद मिल सकती है, :has():

ब्राउज़र सहायता

  • Chrome: 105.
  • एज: 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;
}

ट्रांज़िशन में मोशन जोड़ना

अगर उपयोगकर्ता अपनी रफ़्तार से घूम सकता है, तो हर तरफ़ टूलटिप दिख सकता है. इसलिए, अनुवाद की जाने वाली प्रॉपर्टी को थोड़ी दूरी पर रखने के लिए सेट करें.

@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 एपीआई की मदद से, विंडो में चीज़ों को बेहतर तरीके से पोज़िशन किया जा सके. तब तक, मैं टूलटिप बना रहा हूँ.

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

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

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

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

संसाधन