सीएसएस ऐंकर पोज़िशनिंग की मदद से, एलिमेंट को एक-दूसरे के साथ टेदर करना

फ़िलहाल, आप एक एलिमेंट को दूसरे एलिमेंट से कैसे टेदर करते हैं? आप उनकी स्थिति को ट्रैक करने का प्रयास कर सकते हैं या रैपर तत्व के किसी रूप का उपयोग कर सकते हैं.

<!-- index.html -->
<div class="container">
  <a href="/link" class="anchor">I’m the anchor</a>
  <div class="anchored">I’m the anchored thing</div>
</div>
/* styles.css */
.container {
  position: relative;
}
.anchored {
  position: absolute;
}

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

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

ब्राउज़र समर्थन

Chrome कैनरी में "एक्सपेरिमेंटल वेब प्लैटफ़ॉर्म सुविधाएं" फ़्लैग के पीछे, सीएसएस ऐंकर पोज़िशनिंग एपीआई का इस्तेमाल किया जा सकता है. उस फ़्लैग को चालू करने के लिए, Chrome कैनरी खोलें और chrome://flags पर जाएं. इसके बाद, "प्रयोग के तौर पर उपलब्ध वेब प्लैटफ़ॉर्म की सुविधाएं" फ़्लैग को चालू करें.

ऑडबर्ड की टीम ने डेवलपमेंट इन डेवलेप भी किया है. github.com/oddbird/css-anchor-positioning पर जाकर रेपो ज़रूर देखें.

ऐंकरिंग सहायता की जांच की जा सकती है:

@supports(anchor-name: --foo) {
  /* Styles... */
}

ध्यान दें कि इस एपीआई पर अब भी प्रयोग जारी है. इसलिए, इसमें बदलाव हो सकता है. इस लेख में अहम हिस्सों के बारे में बताया गया है. लागू किया गया मौजूदा तरीका, सीएसएस वर्किंग ग्रुप की खास जानकारी के मुताबिक भी नहीं है.

समस्या

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

इस समस्या का दूसरा हिस्सा यह है कि आप यह पक्का करना चाहते हों कि टेदर किया गया एलिमेंट व्यू में बना रहे—उदाहरण के लिए, अगर आप टूलटिप खोलते हैं और वह व्यूपोर्ट की सीमाओं की वजह से क्लिप हो जाता है, तो ऐसा हो सकता है. ऐसा हो सकता है कि यह लोगों के लिए अच्छा न हो. क्या आपको टूलटिप के ज़रिए बदलाव करना है.

मौजूदा समाधान

फ़िलहाल, इस समस्या को हल करने के कुछ अलग-अलग तरीके हैं.

सबसे पहले, "ऐंकर को रैप करें" तरीके के बारे में शुरुआती जानकारी है. दोनों एलिमेंट लें और उन्हें कंटेनर में रैप करें. इसके बाद, position का इस्तेमाल करके, टूलटिप को ऐंकर के हिसाब से रखा जा सकता है.

<div class="containing-block">
  <div class="tooltip">Anchor me!</div>
  <a class="anchor">The anchor</a>
</div>
.containing-block {
  position: relative;
}

.tooltip {
  position: absolute;
  bottom: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%);
}
देखें

कंटेनर को एक जगह से दूसरी जगह ले जाया जा सकता है. इसके बाद, ज़्यादातर आइटम वही रहेगा जहां आप उसे रखना चाहते हैं.

दूसरा तरीका यह हो सकता है कि अगर आपको अपने ऐंकर की पोज़िशन के बारे में पता हो या किसी तरह उसे ट्रैक किया जा सकता हो. कस्टम प्रॉपर्टी की मदद से, इसे टूलटिप पर भेजा जा सकता है.

<div class="tooltip">Anchor me!</div>
<a class="anchor">The anchor</a>
:root {
  --anchor-width: 120px;
  --anchor-top: 40vh;
  --anchor-left: 20vmin;
}

.anchor {
  position: absolute;
  top: var(--anchor-top);
  left: var(--anchor-left);
  width: var(--anchor-width);
}

.tooltip {
  position: absolute;
  top: calc(var(--anchor-top));
  left: calc((var(--anchor-width) * 0.5) + var(--anchor-left));
  transform: translate(-50%, calc(-100% - 10px));
}

लेकिन, अगर आपको अपने ऐंकर की पोज़िशन के बारे में नहीं पता है, तो क्या होगा? आपको JavaScript के साथ काम करना पड़ सकता है. आप कुछ ऐसा कर सकते हैं, जो नीचे दिया गया कोड करता है, लेकिन अब इसका मतलब है कि आपकी स्टाइल, सीएसएस के बाहर और JavaScript में जाने लगी हैं.

const setAnchorPosition = (anchored, anchor) => {
  const bounds = anchor.getBoundingClientRect().toJSON();
  for (const [key, value] of Object.entries(bounds)) {
    anchored.style.setProperty(`--${key}`, value);
  }
};

const update = () => {
  setAnchorPosition(
    document.querySelector('.tooltip'),
    document.querySelector('.anchor')
  );
};

window.addEventListener('resize', update);
document.addEventListener('DOMContentLoaded', update);

इससे कुछ सवाल पूछने लगते हैं:

  • मैं शैलियों का हिसाब कब लगाऊं?
  • मैं शैलियों का हिसाब कैसे लूं?
  • मैं शैलियों को कितनी बार कैलकुलेट करता/करती हूं?

क्या इससे समस्या हल होती है? यह आपके इस्तेमाल के उदाहरण में हो सकता है, लेकिन इसमें एक समस्या है: हमारा समाधान काम नहीं करता. यह काम नहीं कर रहा है. अगर व्यूपोर्ट से मेरा ऐंकर किया गया एलिमेंट कट हो जाए, तो क्या होगा?

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

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

यहां बताया गया है कि इस समस्या के लिए एक लोकप्रिय पैकेज "floating-ui" का इस्तेमाल करने पर कोड कैसा दिख सकता है:

import {computePosition, flip, offset, autoUpdate} from 'https://cdn.jsdelivr.net/npm/@floating-ui/dom@1.2.1/+esm';

const anchor = document.querySelector('.anchor')
const tooltip = document.querySelector('.tooltip')

const updatePosition = () => {  
  computePosition(anchor, tooltip, {
    placement: 'top',
    middleware: [offset(10), flip()]
  })
    .then(({x, y}) => {
      Object.assign(tooltip.style, {
        left: `${x}px`,
        top: `${y}px`
      })
  })
};

const clean = autoUpdate(anchor, tooltip, updatePosition);

उस कोड का इस्तेमाल करने वाले इस डेमो में ऐंकर की जगह बदलकर देखें.

ऐसा हो सकता है कि "टूलटिप" आपकी उम्मीद के मुताबिक काम न करे. यह y-ऐक्सिस पर व्यूपोर्ट के बाहर जाने पर प्रतिक्रिया देता है, लेकिन x-ऐक्सिस पर नहीं. दस्तावेज़ देखें और आपको अपने लिए कारगर समाधान मिल जाएगा.

लेकिन, अपने प्रोजेक्ट के हिसाब से ऐसा पैकेज ढूंढने में बहुत ज़्यादा समय लग सकता है. इसमें ज़्यादा फ़ैसले लेने पड़ सकते हैं. अगर यह आपकी पसंद के मुताबिक न हो, तो आपको परेशानी हो सकती है.

ऐंकर पोज़िशनिंग का इस्तेमाल करना

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

  • JavaScript की ज़रूरत नहीं है.
  • ब्राउज़र को आपके दिशा-निर्देशों के हिसाब से, बेहतर तरीके से काम करने दें.
  • तीसरे पक्ष की कोई और डिपेंडेंसी नहीं है
  • कोई रैपर एलिमेंट नहीं है.
  • सबसे ऊपर मौजूद लेयर के एलिमेंट के साथ काम करता है.

आइए, ऊपर दी गई समस्या को फिर से हल करते हैं और उस समस्या को हल करते हैं. हालांकि, इसके बजाय लंगर वाली नाव जैसी चीज़ों का इस्तेमाल करें. ये ऐंकर वाले एलिमेंट और ऐंकर को दिखाते हैं. पानी का मतलब ब्लॉक को दिखाता है.

सबसे पहले, आपको ऐंकर तय करने का तरीका चुनना होगा. अपने सीएसएस में ऐसा करने के लिए, ऐंकर एलिमेंट पर anchor-name प्रॉपर्टी सेट करें. यह डैश-आइडेंट वाली वैल्यू स्वीकार करता है.

.anchor {
  anchor-name: --my-anchor;
}

इसके अलावा, आपके पास anchor एट्रिब्यूट की मदद से अपने एचटीएमएल में ऐंकर को तय करने का विकल्प होता है. विशेषता का मान ऐंकर एलिमेंट का आईडी होता है. इससे इंप्लिसिट ऐंकर बन जाता है.

<a id="my-anchor" class="anchor"></a>
<div anchor="my-anchor" class="boat">I’m a boat!</div>

ऐंकर तय करने के बाद, anchor फ़ंक्शन का इस्तेमाल किया जा सकता है. anchor फ़ंक्शन में तीन आर्ग्युमेंट होते हैं:

  • एंकर एलिमेंट: इस्तेमाल करने के लिए ऐंकर का anchor-name—या implicit ऐंकर का इस्तेमाल करने के लिए, वैल्यू को छोड़ा जा सकता है. इसे एचटीएमएल रिलेशनशिप या anchor-name वैल्यू वाली anchor-default प्रॉपर्टी के ज़रिए तय किया जा सकता है.
  • एंकर साइड: उस पोज़िशन का कीवर्ड जिसका इस्तेमाल करना है. यह top, right, bottom, left, center वगैरह हो सकता है. इसके अलावा, आपके पास प्रतिशत को पास करने का विकल्प भी है. उदाहरण के लिए, 50% center के बराबर होगा.
  • फ़ॉलबैक: यह एक वैकल्पिक फ़ॉलबैक वैल्यू है. यह लंबाई या प्रतिशत के हिसाब से तय की जाती है.

anchor फ़ंक्शन का इस्तेमाल, ऐंकर किए गए एलिमेंट की इनसेट प्रॉपर्टी (top, right, bottom, left या इसके लॉजिकल एलिमेंट) की वैल्यू के तौर पर किया जा सकता है. calc में भी anchor फ़ंक्शन का इस्तेमाल किया जा सकता है:

.boat {
  bottom: anchor(--my-anchor top);
  left: calc(anchor(--my-anchor center) - (var(--boat-size) * 0.5));
}

 /* alternative with anchor-default */
.boat {
  anchor-default: --my-anchor;
  bottom: anchor(top);
  left: calc(anchor(center) - (var(--boat-size) * 0.5));
}

कोई center इनसेट प्रॉपर्टी नहीं है. इसलिए, अगर आपको ऐंकर किए गए एलिमेंट का साइज़ पता है, तो calc का इस्तेमाल करें. translate का इस्तेमाल क्यों नहीं करना चाहिए? आप इसका इस्तेमाल कर सकते हैं:

.boat {
  anchor-default: --my-anchor;
  bottom: anchor(top);
  left: anchor(center);
  translate: -50% 0;
}

हालांकि, ब्राउज़र, ऐंकर किए गए एलिमेंट के लिए बदली गई पोज़िशन पर ध्यान नहीं देता. यह साफ़ हो जाएगा कि पोज़िशन में फ़ॉलबैक और ऑटो पोज़िशनिंग को ध्यान में रखते समय यह क्यों ज़रूरी है.

देखें

आपने देखा होगा कि ऊपर दी गई कस्टम प्रॉपर्टी --boat-size का इस्तेमाल किया जाता है. हालांकि, अगर आपको ऐंकर एलिमेंट के साइज़ को ऐंकर के साइज़ के हिसाब से बनाना है, तो उस साइज़ को ऐक्सेस भी किया जा सकता है. खुद इसका हिसाब लगाने के बजाय, anchor-size फ़ंक्शन का इस्तेमाल किया जा सकता है. उदाहरण के लिए, अगर हमारी नाव को हमारे ऐंकर की चौड़ाई से चार गुना ज़्यादा बनाना है, तो:

.boat {
  width: calc(4 * anchor-size(--my-anchor width));
}

आपके पास anchor-size(--my-anchor height) के साथ ऊंचाई का ऐक्सेस भी है. साथ ही, इसका इस्तेमाल ऐक्सिस या दोनों का साइज़ सेट करने के लिए किया जा सकता है.

अगर आपको absolute पोज़िशनिंग वाले किसी एलिमेंट से ऐंकर करना है, तो क्या होगा? नियम यह है कि तत्व प्रतिरूप नहीं हो सकते. इस मामले में, ऐंकर को ऐसे कंटेनर के साथ रैप किया जा सकता है जिसमें relative पोज़िशनिंग हो. फिर आप इसमें ऐंकर कर सकते हैं.

<div class="anchor-wrapper">
  <a id="my-anchor" class="anchor"></a>
</div>
<div class="boat">I’m a boat!</div>

यह डेमो देखें. इसमें आप ऐंकर को इधर-उधर खींचकर ले जा सकते हैं. इसके बाद नाव अपने-आप आ जाएगी.

स्क्रोल की जगह को ट्रैक करना

कुछ मामलों में, आपका ऐंकर एलिमेंट, स्क्रोल करने वाले कंटेनर में हो सकता है. साथ ही, आपका ऐंकर किया गया एलिमेंट उस कंटेनर के बाहर हो सकता है. स्क्रोल करने की प्रोसेस, लेआउट से अलग थ्रेड पर होती है. इसलिए, इसे ट्रैक करने के लिए आपको कोई तरीका चाहिए. anchor-scroll प्रॉपर्टी से यह काम किया जा सकता है. आपको इसे ऐंकर एलिमेंट पर सेट करना होगा और उस ऐंकर की वैल्यू देनी होगी जिसे ट्रैक करना है.

.boat { anchor-scroll: --my-anchor; }

यह डेमो आज़माएं. यहां कोने में बने चेकबॉक्स पर क्लिक करके, anchor-scroll को चालू और बंद किया जा सकता है.

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

इस डेमो के बारे में सोचें, जिसमें स्क्रोल करने वाला एक कंटेनर है. इसमें टूलटिप की सुविधा वाले ऐंकर मौजूद हैं. हो सकता है कि पॉपओवर होने वाले टूलटिप एलिमेंट, ऐंकर के साथ एक जगह पर न रखें:

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

पोज़िशन फ़ॉलबैक और ऑटो पोज़िशनिंग

यहां ऐंकर पोज़िशनिंग पावर एक लेवल तक बढ़ जाता है. position-fallback आपके ऐंकर किए गए एलिमेंट को उन फ़ॉलबैक के सेट के आधार पर पोज़िशन कर सकता है जो आपने दिए हैं. आप अपनी स्टाइल के हिसाब से ब्राउज़र को सही जगह पर ले जाते हैं. साथ ही, स्टाइल को अपने हिसाब से सेट करते हैं.

यहां इस्तेमाल के उदाहरण में एक टूलटिप दिया गया है. इसे ऐंकर के ऊपर या नीचे दिखने के बीच फ़्लिप किया जाना चाहिए. यह व्यवहार इस बात पर आधारित होता है कि टूलटिप उसके कंटेनर में सेव होगा या नहीं. आम तौर पर, वह कंटेनर व्यूपोर्ट होता है.

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

सही position-fallback बनाने से पहले, ऐंकर पोज़िशनिंग की सुविधा से अपने-आप पोज़िशन तय करने की सुविधा भी मिलती है. आप ऐंकर फ़ंक्शन और दूसरी इनसेट प्रॉपर्टी, दोनों में auto की वैल्यू का इस्तेमाल करके बिना किसी शुल्क के इस तरह का फ़्लिप कर सकते हैं. उदाहरण के लिए, अगर bottom के लिए anchor का इस्तेमाल किया जाता है, तो top को auto पर सेट करें.

.tooltip {
  position: absolute;
  bottom: anchor(--my-anchor auto);
  top: auto;
}

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

अगर position-fallback, ऊपर दिए गए टूलटिप को दिखाने की कोशिश करता है, तो वह ऐसा दिख सकता है:

@position-fallback --top-to-bottom {
  @try {
    bottom: anchor(top);
    left: anchor(center);
  }

  @try {
    top: anchor(bottom);
    left: anchor(center);
  }
}

टूलटिप पर उसे इस तरह लागू किया जाता है:

.tooltip {
  anchor-default: --my-anchor;
  position-fallback: --top-to-bottom;
}

anchor-default के इस्तेमाल का मतलब है कि अन्य एलिमेंट के लिए position-fallback का फिर से इस्तेमाल किया जा सकता है. anchor-default को सेट करने के लिए, स्कोप वाली कस्टम प्रॉपर्टी का भी इस्तेमाल किया जा सकता है.

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

देखें

इस बार घड़ी की दिशा में पोज़िशन पाने की कोशिश करते हुए, position-fallback ज़्यादा शब्दों में लिखा जाएगा.

.boat {
  anchor-default: --my-anchor;
  position-fallback: --compass;
}

@position-fallback --compass {
  @try {
    bottom: anchor(top);
    right: anchor(left);
  }

  @try {
    bottom: anchor(top);
    left: anchor(right);
  }

  @try {
    top: anchor(bottom);
    right: anchor(left);
  }

  @try {
    top: anchor(bottom);
    left: anchor(right);
  }
}


उदाहरण

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

संदर्भ मेन्यू

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

इसमें मार्कअप का अहम हिस्सा नहीं है. हालांकि, popovertarget का इस्तेमाल करने वाले हर बटन के पास तीन बटन हैं. इसके बाद, आपके पास popover एट्रिब्यूट का इस्तेमाल करने वाले तीन एलिमेंट होते हैं. इससे आपको बिना किसी JavaScript के संदर्भ मेन्यू खोलने की सुविधा मिलती है. वह ऐसा दिख सकता है:

<button popovertarget="context">
  Toggle Menu
</button>        
<div popover="auto" id="context">
  <ul>
    <li><button>Save to your Liked Songs</button></li>
    <li>
      <button popovertarget="playlist">
        Add to Playlist
      </button>
    </li>
    <li>
      <button popovertarget="share">
        Share
      </button>
    </li>
  </ul>
</div>
<div popover="auto" id="share">...</div>
<div popover="auto" id="playlist">...</div>

अब position-fallback तय किया जा सकता है और इसे संदर्भ मेन्यू के बीच शेयर किया जा सकता है. हम पक्का करते हैं कि पॉपओवर के लिए भी inset स्टाइल को अनसेट किया जाए.

[popovertarget="share"] {
  anchor-name: --share;
}

[popovertarget="playlist"] {
  anchor-name: --playlist;
}

[popovertarget="context"] {
  anchor-name: --context;
}

#share {
  anchor-default: --share;
  position-fallback: --aligned;
}

#playlist {
  anchor-default: --playlist;
  position-fallback: --aligned;
}

#context {
  anchor-default: --context;
  position-fallback: --flip;
}

@position-fallback --aligned {
  @try {
    top: anchor(top);
    left: anchor(right);
  }

  @try {
    top: anchor(bottom);
    left: anchor(right);
  }

  @try {
    top: anchor(top);
    right: anchor(left);
  }

  @try {
    bottom: anchor(bottom);
    left: anchor(right);
  }

  @try {
    right: anchor(left);
    bottom: anchor(bottom);
  }
}

@position-fallback --flip {
  @try {
    bottom: anchor(top);
    left: anchor(left);
  }

  @try {
    right: anchor(right);
    bottom: anchor(top);
  }

  @try {
    top: anchor(bottom);
    left: anchor(left);
  }

  @try {
    top: anchor(bottom);
    right: anchor(right);
  }
}

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

फ़ोकस करें और फ़ॉलो करें

इस डेमो में, :has() को शामिल करके, सीएसएस के प्रिमिटिव को एक साथ जोड़ा जा सकता है. इसे ऐसे input के लिए विज़ुअल इंडिकेटर में बदलाव करने की कोशिश की जा रही है, जिसमें फ़ोकस है.

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

#email {
    anchor-name: --email;
  }
  #name {
    anchor-name: --name;
  }
  #password {
    anchor-name: --password;
  }
:root:has(#email:focus) {
    --active-anchor: --email;
  }
  :root:has(#name:focus) {
    --active-anchor: --name;
  }
  :root:has(#password:focus) {
    --active-anchor: --password;
  }

:root {
    --active-anchor: --name;
    --active-left: anchor(var(--active-anchor) right);
    --active-top: calc(
      anchor(var(--active-anchor) top) +
        (
          (
              anchor(var(--active-anchor) bottom) -
                anchor(var(--active-anchor) top)
            ) * 0.5
        )
    );
  }
.form-indicator {
    left: var(--active-left);
    top: var(--active-top);
    transition: all 0.2s;
}

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

बार चार्ट कैल्क

ऐंकर पोज़िशनिंग के साथ calc को भी जोड़ा जा सकता है. एक ऐसे चार्ट के बारे में सोचिए जिसमें आपके पास कुछ पॉपओवर हैं, जो चार्ट की व्याख्या करते हैं.

सीएसएस min और max का इस्तेमाल करके, सबसे ज़्यादा और सबसे कम वैल्यू को ट्रैक किया जा सकता है. इसका सीएसएस कुछ ऐसा दिख सकता है:

.chart__tooltip--max {
    left: anchor(--chart right);
    bottom: max(
      anchor(--anchor-1 top),
      anchor(--anchor-2 top),
      anchor(--anchor-3 top)
    );
    translate: 0 50%;
  }

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

हैंडल का साइज़ बदलें

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

आप ऐंकर पॉइंट को पसंद के मुताबिक साइज़ बदलने वाले हैंडल की तरह इस्तेमाल कर सकते हैं और inset वैल्यू का इस्तेमाल कर सकते हैं.

.container {
   position: absolute;
   inset:
     anchor(--handle-1 top)
     anchor(--handle-2 right)
     anchor(--handle-2 bottom)
     anchor(--handle-1 left);
 }

इस डेमो में, GreenSock Draggable चैनल के हैंडल को Draggable बनाता है. हालांकि, हैंडल के बीच के गैप को भरने के लिए अडजस्ट होने वाले कंटेनर को भरने के लिए, <img> एलिमेंट का साइज़ बदल जाता है.

Selectमेन्यू?

यह आखिरी सवाल इसलिए छोटा है, क्योंकि आने वाले समय में हम इसे लेकर परेशान हैं. हालांकि, फ़ोकस करने लायक पॉपओवर बनाया जा सकता है. अब इसमें ऐंकर पोज़िशनिंग की सुविधा भी मिलेगी. ऐसे <select> एलिमेंट बनाए जा सकते हैं जिन्हें अलग-अलग स्टाइल में बनाया जा सकता है.

<div class="select-menu">
<button popovertarget="listbox">
 Select option
 <svg>...</svg>
</button>
<div popover="auto" id="listbox">
   <option>A</option>
   <option>Styled</option>
   <option>Select</option>
</div>
</div>

एक इंप्लिसिट anchor यह आसान बना देगा. हालांकि, शुरुआती पॉइंट के लिए सीएसएस ऐसी दिख सकती है:

[popovertarget] {
 anchor-name: --select-button;
}
[popover] {
  anchor-default: --select-button;
  top: anchor(bottom);
  width: anchor-size(width);
  left: anchor(left);
}

पॉपओवर एपीआई की सुविधाओं को सीएसएस ऐंकर पोज़िशनिंग के साथ जोड़ें. इससे आपको नतीजे दिखाने में मदद मिलेगी.

:has() जैसी सुविधाओं को पेश करना शुरू करने पर कोई परेशानी नहीं होती है. आप मार्कर को खुले होने पर घुमा सकते हैं:

.select-menu:has(:open) svg {
  rotate: 180deg;
}

अगली बार इसे कहां ले जाया जा सकता है? इसे चालू select बनाने के लिए, हमें और क्या करना होगा? इसे हम अगले लेख में सेव करेंगे. चिंता न करें, स्टाइल के हिसाब से चुनिंदा एलिमेंट की सुविधा जल्द ही लॉन्च होने वाली है. हमारे साथ बने रहें!


बस इतना ही!

वेब प्लैटफ़ॉर्म बेहतर हो रहा है. यूज़र इंटरफ़ेस (यूआई) कंट्रोल को बेहतर बनाने के लिए, सीएसएस ऐंकर पोज़िशनिंग एक अहम हिस्सा है. यह आपको इन मुश्किल फ़ैसलों से दूर कर देगा. हालांकि, इससे आपको ऐसे कई काम करने में भी मदद मिलेगी जिन्हें पहले कभी नहीं किया जा सका. जैसे, किसी <select> एलिमेंट को शैली देना! अपने विचारों से हमें अवगत कराएं.

Unsplash पर CHUTTERSNAP की फ़ोटो