पोज़िशन के हिसाब से टूलटिप

सीएसएस ऐंकर पोज़िशनिंग की मदद से टूलटिप या पॉपओवर बनाते समय, ब्राउज़र एलिमेंट को फ़ॉलबैक पोज़िशन पर अपने-आप "फ़्लिप" कर सकता है. ऐसा तब होता है, जब एलिमेंट व्यूपोर्ट से बाहर निकल जाता है. ऐसे में, हो सकता है कि आपको पोज़िशन किए गए कॉन्टेंट की स्टाइल में बदलाव करना पड़े. उदाहरण के लिए, पोज़िशन किए गए कॉन्टेंट से ऐंकर पर ले जाने वाले ऐरो को फिर से पोज़िशन करना.

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

समस्या

मान लें कि कोई टूलटिप, डिफ़ॉल्ट रूप से अपने ऐंकर के ऊपर दिखता है. इसके सबसे नीचे, "डाउन" ऐरो होता है. अगर उपयोगकर्ता स्क्रोल करता है और टूलटिप फ़्लिप होकर ऐंकर के नीचे दिखता है, तो ऐरो अब गलत दिशा में और टूलटिप के गलत साइड पर दिखेगा.

समाधान: ऐंकर किए गए कंटेनर की क्वेरी

पोज़िशन किए गए एलिमेंट पर container-type: anchored सेट करके, उसे क्वेरी कंटेनर में बदला जा सकता है. इससे उसे अपनी ऐंकर-पोज़िशन वाली स्थिति के बारे में पता चलता है. इसके बाद, @container anchored() क्वेरी का इस्तेमाल करके, इसके डिसेंडेंट या स्यूडो-एलिमेंट को अपडेट किया जा सकता है.

1. टूलटिप और ट्रिगर बनाना

टूलटिप बनाने के लिए, Popover API का इस्तेमाल करें. popovertarget के ज़रिए पॉपओवर को शुरू करने पर, ट्रिगर बटन के साथ इंप्लिसिट ऐंकर कनेक्शन अपने-आप बन जाता है. इसलिए, साफ़ तौर पर anchor-name या position-anchor की ज़रूरत नहीं होती.

<button popovertarget="tooltip" id="anchor" aria-describedby="tooltip">anchor</button>
<div id="tooltip" popover role="tooltip"></div>

ऐंकर पोज़िशनिंग के साथ इस्तेमाल करने के लिए, पॉपओवर इनसेट और मार्जिन स्टाइल को रीसेट करें. हालांकि, ऐसा सिर्फ़ तब करें, जब ऐंकर पोज़िशनिंग की सुविधा काम करती हो.

@supports (anchor-name: --my-anchor) {
  [popover] {
    inset: auto;
    margin: unset;
  }
}

2. कंटेनर सेट अप करना

जिस एलिमेंट की पोज़िशन तय की जा रही है उस पर container-type: anchored लागू करें. इस एलिमेंट में position-try-fallbacks भी तय होना चाहिए, ताकि फ़्लिप करने की सुविधा चालू की जा सके.

#tooltip {
  position: fixed;
  position-area: block-start;
  position-try-fallbacks: flip-block;

  /* Enable anchored container queries */
  container-type: anchored;
}

3. फ़ॉलबैक के आधार पर स्टाइल

जब कोई फ़ॉलबैक चालू हो, तब स्टाइल लागू करने के लिए @container anchored(fallback: <value>) का इस्तेमाल करें.

सभी कंटेनर क्वेरी की तरह, @container सिर्फ़ कंटेनर के डिसेंडेंट को स्टाइल कर सकता है. तीर बनाने की एक सामान्य रणनीति, ::before और ::after स्यूडो-एलिमेंट का इस्तेमाल करना है. इन्हें डिसेंडेंट के तौर पर माना जाता है और इन्हें सीधे तौर पर स्टाइल किया जा सकता है. हालांकि, टूलटिप को स्टाइल करने के लिए (जैसा कि चौथे चरण में दिखाया गया है), हम टूलटिप में एक चाइल्ड एलिमेंट जोड़ेंगे और उसके ::before सूडो-एलिमेंट में ऐरो बनाएंगे.

<div id="tooltip" popover role="tooltip">
  <div class="tooltip-content">Tooltip</div>
</div>
.tooltip-content::before {
  /* Default "down" arrow for the 'top' position */
  content: "▼";
  position: absolute;
  inset-block-end: 0;
  inset-inline-start: 1rem;
}

/* Update to an "up" arrow when the 'flip-block' fallback (bottom) is active */
@container anchored(fallback: flip-block) {
  .tooltip-content::before {
    content: "▲";
    inset-block-start: 0;
    inset-block-end: auto;
  }
}

4. कंटेनर को स्टाइल करना

अगर आपको कंटेनर के फ़्लिप होने पर, उसकी प्रॉपर्टी (जैसे, margin या background-color) में बदलाव करना है, तो आपको इनर रैपर एलिमेंट का इस्तेमाल करना चाहिए.

  1. बाहरी एलिमेंट पर container-type: anchored लागू करें.
  2. @container ब्लॉक के अंदर मौजूद एलिमेंट को टारगेट करें.
@container anchored(fallback: flip-block) {
  .tooltip-content {
    border-radius: 0 0 .5rem .5rem;
    margin-block-start: 0.25rem;
  }
}

सबसे सही तरीके

  • लॉजिकल फ़ॉलबैक को प्राथमिकता दें: position-try-fallbacks में flip-block और flip-inline जैसे कीवर्ड इस्तेमाल करें. इससे आसान क्वेरी के लिए, आरटीएल और लिखने के अलग-अलग मोड अपने-आप मैनेज हो जाते हैं.
  • तीर के लिए सूडो-एलिमेंट का इस्तेमाल करें: टूलटिप के तीर सिर्फ़ सजावट के लिए होते हैं. ये ::before या ::after के लिए सबसे सही होते हैं. इन्हें बिना किसी अतिरिक्त डीओएम के, ऐंकर किए गए कंटेनर की क्वेरी की मदद से स्टाइल किया जा सकता है.

फ़ॉलबैक रणनीतियां

लागू किए गए फ़ॉलबैक के आधार पर ऐरो को पोज़िशन करना, एक परतदार वृद्धि है. फ़ॉलबैक पोज़िशन पर प्रतिक्रिया देने का कोई दूसरा तरीका नहीं है. ऐंकर पोज़िशन कंटेनर क्वेरी के साथ काम न करने वाले ब्राउज़र में ऐरो को छिपाने के लिए, @supports (container-type: anchored) की मदद से सीएसएस की जांच करें.

@supports (container-type: anchored) {
  .tooltip-content::before {
    content: "▼";
  }
}

पॉपओवर के लिए फ़ॉलबैक और ब्राउज़र की सुविधा

Popover API ज़्यादातर प्रोग्रेसिव एन्हांसमेंट है. हालांकि, इसके मुख्य व्यवहार — टॉप-लेयर प्रमोशन, लाइट-डिसमिस, और popovertarget को शुरू करना — सिर्फ़ सीएसएस के बराबर नहीं हैं. पुराने ब्राउज़र के लिए, polyfill की ज़रूरत होती है. अगर आपको polyfill का इस्तेमाल नहीं करना है, तो मैन्युअल फ़ॉलबैक की ज़रूरत होती है.

पॉलीफ़िल: पुराने ब्राउज़र में popover एट्रिब्यूट का इस्तेमाल करने के लिए, शर्त के मुताबिक @oddbird/popover-polyfill लोड करें. ज़रूरी: HTMLElement.prototype पर popover प्रॉपर्टी की जांच करके, सुविधा का पता लगाएं. साथ ही, पॉलीफ़िल को सिर्फ़ तब लोड करें, जब नेटिव सपोर्ट मौजूद न हो. इसे बिना किसी शर्त के लोड न करें.

बंडलर या इंपोर्ट मैप के साथ:

// MANDATORY: Feature detect 'popover' on HTMLElement.prototype.
if (!("popover" in HTMLElement.prototype)) {
  import("@oddbird/popover-polyfill");
}

बंडलर के बिना, <script type="module"> में सीडीएन से इंपोर्ट करें:

<script type="module">
  if (!("popover" in HTMLElement.prototype)) {
    import("https://unpkg.com/@oddbird/popover-polyfill@latest/dist/popover.min.js");
  }
</script>

स्टाइलिंग से जुड़ी चेतावनी: polyfill, असल :popover-open स्यूडो-क्लास को तय नहीं कर सकता. इसलिए, यह इसके बजाय .\:popover-open क्लास लागू करता है. ज़रूरी: दोनों को :is() या :where() के साथ जोड़ें. ऐसा न करने पर, जिन ब्राउज़र में :popover-open नहीं है वे पूरे नियम को खारिज कर देते हैं:

[popover]:is(:popover-open, .\:popover-open) {
  display: block;
}

इसके अलावा, बिना polyfill के लेगसी फ़ॉलबैक के लिए, position: fixed का इस्तेमाल करें और getBoundingClientRect() की मदद से मैन्युअल तरीके से निर्देशांकों का हिसाब लगाएं. इसके अलावा, अगर इस्तेमाल के उदाहरण के लिए यह स्वीकार्य है, तो inset: auto के साथ डिफ़ॉल्ट पोज़िशनिंग का इस्तेमाल करें.

जिन ब्राउज़र में Popover API काम नहीं करता है उनमें ऐंकर पोज़िशनिंग की सुविधा भी काम नहीं करती. इसलिए, टूलटिप स्क्रीन के बीच में दिखेगा.