<details> को स्टाइल करने के ज़्यादा विकल्प

पब्लिश किया गया: 6 नवंबर, 2024

Chrome 131 से, <details> और <summary> एलिमेंट के स्ट्रक्चर को स्टाइल करने के लिए, आपके पास ज़्यादा विकल्प उपलब्ध हैं. अब डिसक्लोज़र या अकॉर्डियन विजेट बनाते समय, इन एलिमेंट का इस्तेमाल किया जा सकता है.

खास तौर पर, Chrome 131 में किए गए बदलावों की वजह से, इन एलिमेंट पर display प्रॉपर्टी का इस्तेमाल किया जा सकता है. साथ ही, इसमें ::details-content स्यूडो-एलिमेंट जोड़ा गया है, ताकि एक्सपैंड और कोलैप्स होने वाले हिस्से को स्टाइल किया जा सके.

Browser Support

  • Chrome: 131.
  • Edge: 131.
  • Firefox: 143.
  • Safari: 18.4.

Source

<details> एलिमेंट पर display सेटिंग

पहले, <details> एलिमेंट के डिसप्ले टाइप को नहीं बदला जा सकता था. अब इस पाबंदी को हटा दिया गया है. उदाहरण के लिए, अब <details> एलिमेंट पर ग्रिड या फ़्लेक्स लेआउट का इस्तेमाल किया जा सकता है.

इस उदाहरण में, एक्सक्लूसिव अकॉर्डियन में कई <details> एलिमेंट शामिल हैं, जिन्हें एक-दूसरे के बगल में रखा गया है. <details> एलिमेंट में से किसी एक को बड़ा करने पर, उसका कॉन्टेंट <summary> के बगल में दिखता है.

डेमो

रिकॉर्डिंग

Chrome 131 में https://codepen.io/web-dot-dev/pen/VwoBQjY की रिकॉर्डिंग

इसके लिए, <details> एलिमेंट पर फ़्लेक्स लेआउट का इस्तेमाल किया जाता है. इसके लिए, यहां दी गई सीएसएस का इस्तेमाल किया जाता है:

details {
  display: flex;
  flex-direction: row;
}

grid जैसी अन्य डिसप्ले वैल्यू का भी इस्तेमाल किया जा सकता है.

display: inline का इस्तेमाल करने के बारे में नोट

display फ़ील्ड की ऐसी वैल्यू जो अनुमान के मुताबिक नहीं है वह inline है. ऐसा इसलिए नहीं है, क्योंकि यह काम नहीं करता. बल्कि, ऐसा एचटीएमएल पार्सर की सीमाओं की वजह से होता है.

किसी पैराग्राफ़ में <details> एलिमेंट रखने पर, एचटीएमएल पार्सर को सबसे पहले खुले हुए पैराग्राफ़ को बंद करना पड़ता है. इसके बारे में एचटीएमएल स्टैंडर्ड के सेक्शन 13.2.6.4.7 में बताया गया है:

एक ऐसा स्टार्ट टैग जिसका टैग नेम इनमें से कोई एक है: "address", "article", "aside", "blockquote", "center", "details", "dialog", "dir", "div", "dl", "fieldset", "figcaption", "figure", "footer", "header", "hgroup", "main", "menu", "nav", "ol", "p", "search", "section", "summary", "ul"

अगर खुले हुए एलिमेंट के स्टैक में बटन स्कोप में p एलिमेंट है, तो p एलिमेंट को बंद करें. टोकन के लिए एचटीएमएल एलिमेंट डालें.

इस वजह से, <details> ब्लॉक की दिशा में फ़्लो होता है. भले ही, आपने display: inline सेट किया हो.

उदाहरण के लिए, यह मार्कअप

<p>Hello <details>…</details> world</p>

पार्स करने के बाद यह ऐसा दिखता है:

<p>Hello </p><details>…</details> world<p></p>

Chrome DevTools का इस्तेमाल करके, पार्स किए गए मार्कअप की जांच करके, इस डेमो में खुद देखा जा सकता है.

ध्यान दें कि यह सिर्फ़ <details> को <p> में नेस्ट करने पर लागू होता है. <div> के अंदर मौजूद <details> पर display: inline का इस्तेमाल करने पर, यह ठीक से काम करता है.

::details-content स्यूडो

ब्राउज़र में, <details> एलिमेंट को शैडो DOM का इस्तेमाल करके लागू किया जाता है. इसमें एक <slot>, खास जानकारी के लिए (डिफ़ॉल्ट खास जानकारी वाले चाइल्ड के साथ) और एक <slot>, बाकी सभी कॉन्टेंट के लिए होता है. इसका मतलब है कि <summary> एलिमेंट को छोड़कर, <details> एलिमेंट के सभी चाइल्ड.

<details>
  ↳ #shadow-root (user-agent)
      <slot id="details-summary">
        <summary>Details</summary>
        <!-- The summary goes here -->
      </slot>
      <slot id="details-content">
        <!-- All content goes here -->
      </slot>
</details>

<details> पर ज़्यादा डिसप्ले टाइप इस्तेमाल करने के साथ-साथ, अब ::details-content स्यूडो-एलिमेंट का इस्तेमाल करके कॉन्टेंट स्लॉट को टारगेट किया जा सकता है. इस सूडो का इस्तेमाल, <details> एलिमेंट के कॉन्टेंट को रैप करने वाले कंटेनर को स्टाइल करने के लिए किया जा सकता है.

details::details-content {
  border: 5px dashed hotpink;
}

अगर आपको सेट की गई स्टाइल सिर्फ़ तब लागू करनी है, जब <details> एलिमेंट खुला हो, तो इसके आगे [open] सिलेक्टर जोड़ें.

[open]::details-content {
  border: 5px dashed hotpink;
}

हमारा सुझाव है कि <details> एलिमेंट के [open] स्टेट में होने पर ही, ::details-content स्यूडो पर स्टाइलिंग लागू करें.

डेमो

रिकॉर्डिंग

Chrome 131 में https://codepen.io/web-dot-dev/pen/oNKMEYv की रिकॉर्डिंग

UA स्टाइल शीट में, ::details-content के display टाइप को block पर सेट किया गया है. हालांकि, इससे पहले इसे display: contents पर सेट किया गया था. कुछ मामलों में, यह बदलाव आपके लिए नुकसानदेह हो सकता है. जैसे, height: 100% पर भरोसा करने वाले कॉन्टेंट का खुलासा करना. अगर आपको इससे कोई समस्या है, तो display टाइप को वापस contents पर सेट करके, इस समस्या को ठीक किया जा सकता है. जैसे: details[open]::details-content { display: contents; }.

::details-content स्यूडो एलिमेंट को ऐनिमेट करना

इस जांच को दिखाने के लिए, इसे यहां दिए गए किसी भी डेमो में शामिल नहीं किया गया है.

<details> एलिमेंट के कॉन्टेंट को बड़ा करते समय, उसे ऐनिमेट किया जा सकता है. यहां दिए गए उदाहरण में, चौड़ाई को 0px से 300px तक ऐनिमेट किया गया है.

::details-content {
  transition: width 0.5s ease, content-visibility 0.5s ease allow-discrete;
  width: 0;
}

[open]::details-content {
  width: 300px;
}

width के अलावा, content-visibility प्रॉपर्टी को भी ट्रांज़िशन करने की ज़रूरत होती है. ऐसा इसलिए होता है, क्योंकि इसकी वैल्यू, User-Agent स्टाइल शीट में तय किए गए नियमों के मुताबिक, बंद और चालू होने की स्थिति के बीच बदलती रहती है. यह प्रॉपर्टी अलग-अलग ऐनिमेशन वाली प्रॉपर्टी है. इसलिए, इसे काम करने के लिए allow-discrete कीवर्ड की ज़रूरत होती है.

पहले शेयर किए गए एक्सक्लूसिव अकॉर्डियन डेमो में जोड़ने के बाद, नतीजा यह हो जाता है:

डेमो

रिकॉर्डिंग

Chrome 131 में https://codepen.io/web-dot-dev/pen/XWvBZNo की रिकॉर्डिंग

height को ऐनिमेट भी किया जा सकता है. height: auto पर ऐनिमेशन बनाने के लिए, आपको interpolate-size या calc-size() का इस्तेमाल करना होगा. इसके अलावा, कॉन्टेंट को ::details-content स्यूडो से बाहर निकलने से रोकने के लिए, उस पर overflow: clip लागू करें.

::details-content {
    transition: height 0.5s ease, content-visibility 0.5s ease allow-discrete;
    height: 0;
    overflow: clip;
}

/* Browser supports interpolate-size */
@supports (interpolate-size: allow-keywords) {
    :root {
        interpolate-size: allow-keywords;
    }

    [open]::details-content {
        height: auto;
    }
}

/* Fallback for browsers with no interpolate-size support */
@supports not (interpolate-size: allow-keywords) {
    [open]::details-content {
        height: 150px;
        overflow-y: scroll; /* In case the contents should be taller than 150px */
    }
}

यहां दिए गए डेमो में, कोड को ऐक्शन में देखा जा सकता है. यह Material UI के अकॉर्डियन से मिलता-जुलता है. हर <details> एलिमेंट का कॉन्टेंट, बेहतरीन तरीके से ऐनिमेट होता है.

डेमो

रिकॉर्डिंग

Chrome 131 में https://codepen.io/web-dot-dev/pen/ExqpQZM की रिकॉर्डिंग

::details-content की सुविधा के बिना काम करने वाले ब्राउज़र में भी यह कॉम्पोनेंट ठीक से काम करता है. हालांकि, वेबसाइट पर आने वाले लोगों को ऐनिमेशन नहीं दिखता.

फ़ीचर का पता लगाने की सुविधा

सीएसएस में ::details-content स्यूडो के लिए, सुविधा का पता लगाने के लिए इस स्निपेट का इस्तेमाल करें.

@supports selector(::details-content) {
  
}

इस सुविधा का इस्तेमाल करके यह भी पता लगाया जा सकता है कि वेबसाइट पर आने वाला व्यक्ति जिस ब्राउज़र का इस्तेमाल कर रहा है वह डिसप्ले की अतिरिक्त वैल्यू के साथ काम करता है या नहीं.

सुलभता से जुड़ी बातें

::details-content छद्म-तत्व को शामिल करने और डिसप्ले टाइप को बदलने की सुविधा से, <details> एलिमेंट की सुलभता पर कोई असर नहीं पड़ता.

पहले की तरह, Chromium पर आधारित ब्राउज़र और एचटीएमएल स्टैंडर्ड के मुताबिक, <details> एलिमेंट को खोजा जा सकता है. साथ ही, जब ब्राउज़र पेज पर ढूंढें, ScrollToTextFragment, और एलिमेंट फ़्रैगमेंट नेविगेशन के जवाब में इसके छिपे हुए कॉन्टेंट पर स्क्रोल करने की कोशिश करता है, तो यह अपने-आप बड़ा हो जाता है. इसमें कोई बदलाव नहीं होता.

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

मार्कर को स्टाइल करने के बारे में क्या जानकारी है?

फ़िलहाल, सूची के मार्कर की स्टाइलिंग एक-दूसरे के साथ काम नहीं करती है. इसकी वजह यह है कि इसके लिए दो अलग-अलग तरीके इस्तेमाल किए जाते हैं. पहला तरीका Gecko और (मौजूदा) Chromium इस्तेमाल करता है. वहीं, दूसरा तरीका WebKit इस्तेमाल करता है. पहले, इसे Chromium के साथ शेयर किया जाता था.

इस सुविधा के अलग-अलग प्लैटफ़ॉर्म पर काम करने के बाद, हमारा मकसद आपको मार्कर को स्टाइल करने का बेहतर कंट्रोल देना है.

ज़्यादा डेमो

आखिर में, यहां कुछ और डेमो दिए गए हैं. इन्हें देखें. ये सभी ::details-content का इस्तेमाल करते हैं.

UIKit अकॉर्डियन

डेमो

रिकॉर्डिंग

Chrome 131 में https://codepen.io/web-dot-dev/pen/rNXrJyQ की रिकॉर्डिंग

यह डेमो, UIKit Accordion के बाद बनाया गया है. यह कोड, पहले शेयर किए गए Material UI अकॉर्डियन के कोड जैसा ही है.

जानकारी ज़ाहिर करने वाला विजेट, जो कुछ हद तक खुला हो

डेमो

रिकॉर्डिंग

Chrome 131 में https://codepen.io/web-dot-dev/pen/PoMBQmW की रिकॉर्डिंग

इस डेमो में, पैसे लेकर किए गए प्रमोशन की जानकारी देने वाला विजेट दिखाया गया है. यह विजेट पूरी तरह से नहीं खुला है. इसका कॉन्टेंट पहले से ही स्क्रीन पर दिख रहा है. ऐसा करने के लिए, content-visibility को हमेशा visible पर सेट किया जाता है. height में calc-size() का इस्तेमाल करके ऐनिमेशन किया जाता है, क्योंकि इसमें कैलकुलेशन शामिल होती है.

::details-content {
  content-visibility: visible; /* Make it always visible */
    
  transition: height 0.5s ease;
  height: 150px;
  overflow: clip;
}

[open]::details-content {
  height: calc-size(auto, size + 0.5rem); /* calc-size because we need to add a length */
}

स्टाइलिंग को आसान बनाने के लिए, कॉन्टेंट को रैपर div में रैप किया जाता है. रैपर div को लेआउट स्टाइल मिलती हैं, जैसे कि padding लागू किया जाता है और ::details-content स्यूडो को ऐनिमेट किया जाता है.