ঘোষণামূলক ছায়া DOM

ডিক্লারেটিভ শ্যাডো DOM হল একটি স্ট্যান্ডার্ড ওয়েব প্ল্যাটফর্ম বৈশিষ্ট্য , যা 90 সংস্করণ থেকে Chrome-এ সমর্থিত হয়েছে। উল্লেখ্য যে এই বৈশিষ্ট্যটির স্পেসিফিকেশন 2023 সালে পরিবর্তিত হয়েছিল ( shadowroot থেকে shadowrootmode নামকরণ সহ), এবং সবগুলির মধ্যে সবচেয়ে আপ টু ডেট প্রমিত সংস্করণ। বৈশিষ্ট্যের অংশগুলি Chrome সংস্করণ 124-এ অবতরণ করেছে৷

ব্রাউজার সমর্থন

  • ক্রোম: 111।
  • প্রান্ত: 111।
  • ফায়ারফক্স: 123।
  • সাফারি: 16.4.

উৎস

Shadow DOM হল তিনটি ওয়েব কম্পোনেন্ট স্ট্যান্ডার্ডের মধ্যে একটি, যা HTML টেমপ্লেট এবং কাস্টম এলিমেন্ট দ্বারা বৃত্তাকার। Shadow DOM একটি নির্দিষ্ট DOM সাবট্রিতে CSS শৈলী স্কোপ করার একটি উপায় প্রদান করে এবং সেই সাবট্রিটিকে নথির বাকি অংশ থেকে বিচ্ছিন্ন করে। <slot> উপাদানটি আমাদেরকে নিয়ন্ত্রণ করার একটি উপায় দেয় যেখানে একটি কাস্টম এলিমেন্টের শিশুদের ছায়া গাছের মধ্যে সন্নিবেশ করা উচিত। এই বৈশিষ্ট্যগুলি সম্মিলিতভাবে একটি স্বয়ংসম্পূর্ণ, পুনঃব্যবহারযোগ্য উপাদানগুলি তৈরি করার জন্য একটি সিস্টেমকে সক্ষম করে যা একটি অন্তর্নির্মিত HTML উপাদানের মতো বিদ্যমান অ্যাপ্লিকেশনগুলিতে বিরামহীনভাবে সংহত করে৷

এখন পর্যন্ত, Shadow DOM ব্যবহার করার একমাত্র উপায় ছিল জাভাস্ক্রিপ্ট ব্যবহার করে একটি ছায়া রুট তৈরি করা:

const host = document.getElementById('host');
const shadowRoot = host.attachShadow({mode: 'open'});
shadowRoot.innerHTML = '<h1>Hello Shadow DOM</h1>';

এই ধরনের একটি আবশ্যিক API ক্লায়েন্ট-সাইড রেন্ডারিংয়ের জন্য ভাল কাজ করে: একই জাভাস্ক্রিপ্ট মডিউলগুলি যা আমাদের কাস্টম উপাদানগুলিকে সংজ্ঞায়িত করে তাদের শ্যাডো রুট তৈরি করে এবং তাদের সামগ্রী সেট করে। যাইহোক, অনেক ওয়েব অ্যাপ্লিকেশনকে কনটেন্ট সার্ভার-সাইডে রেন্ডার করতে হবে বা বিল্ড টাইমে স্ট্যাটিক এইচটিএমএল করতে হবে। এটি দর্শকদের যুক্তিসঙ্গত অভিজ্ঞতা প্রদানের একটি গুরুত্বপূর্ণ অংশ হতে পারে যারা JavaScript চালাতে সক্ষম নাও হতে পারে।

সার্ভার-সাইড রেন্ডারিং (SSR) এর ন্যায্যতা প্রকল্প থেকে প্রকল্পে পরিবর্তিত হয়। অ্যাক্সেসিবিলিটি নির্দেশিকাগুলি পূরণ করার জন্য কিছু ওয়েবসাইটকে অবশ্যই সম্পূর্ণ কার্যকরী সার্ভার-রেন্ডার করা HTML প্রদান করতে হবে, অন্যরা ধীর সংযোগ বা ডিভাইসে ভাল পারফরম্যান্স নিশ্চিত করার উপায় হিসাবে একটি বেসলাইন নো-জাভাস্ক্রিপ্ট অভিজ্ঞতা প্রদান করতে বেছে নেয়।

ঐতিহাসিকভাবে, সার্ভার-সাইড রেন্ডারিংয়ের সংমিশ্রণে শ্যাডো ডম ব্যবহার করা কঠিন ছিল কারণ সার্ভার-জেনারেটেড এইচটিএমএলে শ্যাডো রুট প্রকাশ করার কোনো অন্তর্নির্মিত উপায় ছিল না। DOM উপাদানগুলির সাথে শ্যাডো রুট সংযুক্ত করার সময় কার্যক্ষমতার প্রভাব রয়েছে যা ইতিমধ্যেই সেগুলি ছাড়া রেন্ডার করা হয়েছে৷ এটি পৃষ্ঠাটি লোড হওয়ার পরে লেআউট স্থানান্তরিত হতে পারে, বা শ্যাডো রুটের স্টাইলশীটগুলি লোড করার সময় সাময়িকভাবে আনস্টাইল না করা সামগ্রীর ("FOUC") একটি ফ্ল্যাশ দেখাতে পারে।

ডিক্লারেটিভ শ্যাডো ডম (ডিএসডি) এই সীমাবদ্ধতা দূর করে, শ্যাডো ডম সার্ভারে নিয়ে আসে।

একটি ঘোষণামূলক শ্যাডো রুট কীভাবে তৈরি করবেন

একটি ঘোষণামূলক শ্যাডো রুট হল একটি <template> উপাদান যার একটি shadowrootmode বৈশিষ্ট্য রয়েছে:

<host-element>
  <template shadowrootmode="open">
    <slot></slot>
  </template>
  <h2>Light content</h2>
</host-element>

shadowrootmode বৈশিষ্ট্য সহ একটি টেমপ্লেট উপাদান HTML পার্সার দ্বারা সনাক্ত করা হয় এবং অবিলম্বে এটির মূল উপাদানের ছায়া রুট হিসাবে প্রয়োগ করা হয়। উপরের নমুনা থেকে বিশুদ্ধ HTML মার্কআপ লোড করার ফলে নিম্নলিখিত DOM ট্রি দেখা যায়:

<host-element>
  #shadow-root (open)
  <slot>
    ↳
    <h2>Light content</h2>
  </slot>
</host-element>

এই কোড নমুনা ছায়া DOM বিষয়বস্তু প্রদর্শনের জন্য Chrome DevTools Elements প্যানেলের নিয়মাবলী অনুসরণ করছে। উদাহরণস্বরূপ, অক্ষরটি স্লটেড লাইট DOM বিষয়বস্তুর প্রতিনিধিত্ব করে।

এটি আমাদেরকে স্থির HTML-এ Shadow DOM এর এনক্যাপসুলেশন এবং স্লট প্রজেকশনের সুবিধা দেয়। শ্যাডো রুট সহ পুরো ট্রি তৈরি করতে কোনো জাভাস্ক্রিপ্টের প্রয়োজন নেই।

উপাদান হাইড্রেশন

ডিক্লারেটিভ শ্যাডো DOM শৈলী এনক্যাপসুলেট বা চাইল্ড প্লেসমেন্ট কাস্টমাইজ করার উপায় হিসাবে নিজে থেকে ব্যবহার করা যেতে পারে, কিন্তু কাস্টম উপাদানগুলির সাথে ব্যবহার করা হলে এটি সবচেয়ে শক্তিশালী। কাস্টম উপাদান ব্যবহার করে নির্মিত উপাদানগুলি স্ট্যাটিক HTML থেকে স্বয়ংক্রিয়ভাবে আপগ্রেড হয়ে যায়। ডিক্লেরেটিভ শ্যাডো ডম প্রবর্তনের সাথে, এটি আপগ্রেড হওয়ার আগে একটি কাস্টম উপাদানের জন্য একটি ছায়া রুট থাকা সম্ভব।

একটি কাস্টম উপাদান HTML থেকে আপগ্রেড করা হচ্ছে যার মধ্যে একটি ঘোষণামূলক শ্যাডো রুট রয়েছে ইতিমধ্যেই সেই ছায়া রুট সংযুক্ত থাকবে৷ এর মানে হল যে উপাদানটির একটি shadowRoot প্রপার্টি ইতিমধ্যেই উপলব্ধ থাকবে যখন এটি ইনস্ট্যান্ট করা হয়, আপনার কোডটি স্পষ্টভাবে তৈরি না করে। আপনার এলিমেন্টের কনস্ট্রাক্টরে বিদ্যমান শ্যাডো রুটের জন্য this.shadowRoot চেক করা ভাল। যদি ইতিমধ্যে একটি মান থাকে, তাহলে এই উপাদানটির জন্য HTML-এ একটি ঘোষণামূলক শ্যাডো রুট অন্তর্ভুক্ত থাকে। মানটি শূন্য হলে, HTML-এ কোনো ঘোষণামূলক শ্যাডো রুট উপস্থিত ছিল না বা ব্রাউজার ঘোষণামূলক শ্যাডো DOM সমর্থন করে না।

<menu-toggle>
  <template shadowrootmode="open">
    <button>
      <slot></slot>
    </button>
  </template>
  Open Menu
</menu-toggle>
<script>
  class MenuToggle extends HTMLElement {
    constructor() {
      super();

      // Detect whether we have SSR content already:
      if (this.shadowRoot) {
        // A Declarative Shadow Root exists!
        // wire up event listeners, references, etc.:
        const button = this.shadowRoot.firstElementChild;
        button.addEventListener('click', toggle);
      } else {
        // A Declarative Shadow Root doesn't exist.
        // Create a new shadow root and populate it:
        const shadow = this.attachShadow({mode: 'open'});
        shadow.innerHTML = `<button><slot></slot></button>`;
        shadow.firstChild.addEventListener('click', toggle);
      }
    }
  }

  customElements.define('menu-toggle', MenuToggle);
</script>

কাস্টম এলিমেন্টগুলি কিছু সময়ের জন্য প্রায় ছিল, এবং এখন পর্যন্ত attachShadow() ব্যবহার করে একটি তৈরি করার আগে একটি বিদ্যমান শ্যাডো রুট পরীক্ষা করার কোন কারণ ছিল না। ডিক্লারেটিভ শ্যাডো ডিওএম-এ একটি ছোট পরিবর্তন রয়েছে যা বিদ্যমান উপাদানগুলিকে এটি সত্ত্বেও কাজ করার অনুমতি দেয়: বিদ্যমান ডিক্লারেটিভ শ্যাডো রুট সহ একটি উপাদানে attachShadow() পদ্ধতিতে কল করলে কোনও ত্রুটি হবে না । পরিবর্তে, ঘোষণামূলক শ্যাডো রুট খালি করা হয় এবং ফিরে আসে। এটি ঘোষণামূলক শ্যাডো DOM-এর জন্য নির্মিত নয় এমন পুরানো উপাদানগুলিকে কাজ চালিয়ে যাওয়ার অনুমতি দেয়, যেহেতু একটি অপরিহার্য প্রতিস্থাপন তৈরি না হওয়া পর্যন্ত ঘোষণামূলক মূলগুলি সংরক্ষণ করা হয়।

নতুন তৈরি কাস্টম এলিমেন্টের জন্য, একটি নতুন ElementInternals.shadowRoot প্রপার্টি একটি এলিমেন্টের বিদ্যমান ডিক্লারেটিভ শ্যাডো রুট, খোলা এবং বন্ধ উভয় ক্ষেত্রেই একটি রেফারেন্স পাওয়ার একটি সুস্পষ্ট উপায় প্রদান করে। এটি যেকোন ডিক্লারেটিভ শ্যাডো রুট চেক করতে এবং ব্যবহার করতে ব্যবহার করা যেতে পারে, যখন এটি প্রদান করা হয়নি এমন ক্ষেত্রে attachShadow() -এ ফিরে আসে।

class MenuToggle extends HTMLElement {
  constructor() {
    super();

    const internals = this.attachInternals();

    // check for a Declarative Shadow Root:
    let shadow = internals.shadowRoot;

    if (!shadow) {
      // there wasn't one. create a new Shadow Root:
      shadow = this.attachShadow({
        mode: 'open'
      });
      shadow.innerHTML = `<button><slot></slot></button>`;
    }

    // in either case, wire up our event listener:
    shadow.firstChild.addEventListener('click', toggle);
  }
}

customElements.define('menu-toggle', MenuToggle);

মূল প্রতি এক ছায়া

একটি ঘোষণামূলক শ্যাডো রুট শুধুমাত্র তার মূল উপাদানের সাথে যুক্ত। এর অর্থ হল ছায়া শিকড়গুলি সর্বদা তাদের সম্পর্কিত উপাদানের সাথে colocated হয়। এই নকশার সিদ্ধান্তটি নিশ্চিত করে যে ছায়া শিকড়গুলি একটি HTML নথির বাকি অংশের মতো স্ট্রিমযোগ্য। এটি প্রণয়ন এবং প্রজন্মের জন্যও সুবিধাজনক, যেহেতু একটি উপাদানে একটি শ্যাডো রুট যোগ করার জন্য বিদ্যমান শ্যাডো রুটগুলির একটি রেজিস্ট্রি বজায় রাখার প্রয়োজন হয় না।

শ্যাডো রুটকে তাদের প্যারেন্ট এলিমেন্টের সাথে যুক্ত করার ট্রেডঅফ হল যে একই ডিক্লেরেটিভ শ্যাডো রুট <template> > থেকে একাধিক এলিমেন্ট শুরু করা সম্ভব নয়। যাইহোক, ডিক্লারেটিভ শ্যাডো ডিওএম ব্যবহার করা হয় এমন বেশিরভাগ ক্ষেত্রে এটি গুরুত্বপূর্ণ হওয়ার সম্ভাবনা নেই, যেহেতু প্রতিটি শ্যাডো রুটের বিষয়বস্তু খুব কমই অভিন্ন। যদিও সার্ভার-রেন্ডার করা HTML-এ প্রায়শই পুনরাবৃত্ত উপাদান কাঠামো থাকে, তবে তাদের বিষয়বস্তু সাধারণত ভিন্ন হয়-উদাহরণস্বরূপ, পাঠ্য বা বৈশিষ্ট্যের সামান্য ভিন্নতা। যেহেতু একটি ক্রমিক ঘোষণামূলক শ্যাডো রুটের বিষয়বস্তু সম্পূর্ণরূপে স্থির, একটি একক ঘোষণামূলক শ্যাডো রুট থেকে একাধিক উপাদান আপগ্রেড করা শুধুমাত্র তখনই কাজ করবে যদি উপাদানগুলি অভিন্ন হয়। অবশেষে, কম্প্রেশনের প্রভাবের কারণে নেটওয়ার্ক স্থানান্তরের আকারে বারবার অনুরূপ ছায়া শিকড়ের প্রভাব তুলনামূলকভাবে ছোট।

ভবিষ্যতে, ভাগ করা ছায়া শিকড়গুলিকে পুনরায় দেখার জন্য এটি সম্ভব হতে পারে৷ যদি DOM অন্তর্নির্মিত টেমপ্লেটিং- এর জন্য সমর্থন লাভ করে, ঘোষণামূলক শ্যাডো রুটগুলিকে টেমপ্লেট হিসাবে বিবেচনা করা যেতে পারে যা একটি প্রদত্ত উপাদানের জন্য ছায়া রুট তৈরি করার জন্য তাত্ক্ষণিকভাবে তৈরি করা হয়। বর্তমান ঘোষণামূলক ছায়া DOM নকশা একটি একক উপাদানে ছায়া রুট অ্যাসোসিয়েশন সীমাবদ্ধ করে ভবিষ্যতে এই সম্ভাবনার অস্তিত্বের অনুমতি দেয়।

স্ট্রিমিং শান্ত

ডিক্লারেটিভ শ্যাডো রুটকে সরাসরি তাদের মূল উপাদানের সাথে সংযুক্ত করা সেই উপাদানটিকে আপগ্রেড করার এবং সংযুক্ত করার প্রক্রিয়াকে সহজ করে। ঘোষণামূলক শ্যাডো রুটগুলি এইচটিএমএল পার্সিংয়ের সময় সনাক্ত করা হয়, এবং তাদের খোলার <template> ট্যাগের সম্মুখীন হলে সাথে সাথে সংযুক্ত করা হয়। <template> -এর মধ্যে পার্স করা এইচটিএমএল সরাসরি শ্যাডো রুটে পার্স করা হয়, তাই এটি "স্ট্রিম করা" হতে পারে: এটি প্রাপ্ত হওয়ার সাথে সাথে রেন্ডার করা হয়।

<div id="el">
  <script>
    el.shadowRoot; // null
  </script>

  <template shadowrootmode="open">
    <!-- shadow realm -->
  </template>

  <script>
    el.shadowRoot; // ShadowRoot
  </script>
</div>

শুধুমাত্র পার্সার

ঘোষণামূলক ছায়া DOM হল HTML পার্সারের একটি বৈশিষ্ট্য। এর মানে হল যে একটি ঘোষণামূলক শ্যাডো রুট শুধুমাত্র পার্স করা হবে এবং <template> ট্যাগের জন্য shadowrootmode অ্যাট্রিবিউট সহ সংযুক্ত করা হবে যা HTML পার্সিংয়ের সময় উপস্থিত থাকে। অন্য কথায়, প্রাথমিক HTML পার্সিংয়ের সময় ঘোষণামূলক শ্যাডো রুট তৈরি করা যেতে পারে:

<some-element>
  <template shadowrootmode="open">
    shadow root content for some-element
  </template>
</some-element>

একটি <template> উপাদানের shadowrootmode বৈশিষ্ট্য সেট করা কিছুই করে না, এবং টেমপ্লেটটি একটি সাধারণ টেমপ্লেট উপাদান থেকে যায়:

const div = document.createElement('div');
const template = document.createElement('template');
template.setAttribute('shadowrootmode', 'open'); // this does nothing
div.appendChild(template);
div.shadowRoot; // null

কিছু গুরুত্বপূর্ণ নিরাপত্তা বিবেচনা এড়াতে, innerHTML বা insertAdjacentHTML() মতো খণ্ড পার্সিং API ব্যবহার করে ঘোষণামূলক শ্যাডো রুট তৈরি করা যাবে না। ডিক্লারেটিভ শ্যাডো রুট প্রয়োগ করে HTML পার্স করার একমাত্র উপায় হল setHTMLUnsafe() বা parseHTMLUnsafe() :

<script>
  const html = `
    <div>
      <template shadowrootmode="open"></template>
    </div>
  `;
  const div = document.createElement('div');
  div.innerHTML = html; // No shadow root here
  div.setHTMLUnsafe(html); // Shadow roots included
  const newDocument = Document.parseHTMLUnsafe(html); // Also here
</script>

শৈলী সহ সার্ভার-রেন্ডারিং

স্ট্যান্ডার্ড <style> এবং <link> ট্যাগ ব্যবহার করে ঘোষণামূলক শ্যাডো রুটের ভিতরে ইনলাইন এবং বাহ্যিক স্টাইলশীটগুলি সম্পূর্ণরূপে সমর্থিত:

<nineties-button>
  <template shadowrootmode="open">
    <style>
      button {
        color: seagreen;
      }
    </style>
    <link rel="stylesheet" href="/comicsans.css" />
    <button>
      <slot></slot>
    </button>
  </template>
  I'm Blue
</nineties-button>

এইভাবে নির্দিষ্ট করা শৈলীগুলিও অত্যন্ত অপ্টিমাইজ করা হয়েছে: যদি একই স্টাইল শীট একাধিক ঘোষণামূলক শ্যাডো রুটে উপস্থিত থাকে তবে এটি শুধুমাত্র একবার লোড এবং পার্স করা হয়। ব্রাউজারটি একটি একক ব্যাকিং CSSStyleSheet ব্যবহার করে যা সমস্ত ছায়া শিকড় দ্বারা ভাগ করা হয়, ডুপ্লিকেট মেমরি ওভারহেড দূর করে৷

Declarative Shadow DOM-এ নির্মাণযোগ্য স্টাইলশীট সমর্থিত নয়। এর কারণ হল, বর্তমানে, HTML-এ নির্মাণযোগ্য স্টাইলশীটগুলিকে সিরিয়ালাইজ করার কোনও উপায় নেই এবং adoptedStyleSheets পপুলেট করার সময় তাদের উল্লেখ করার কোনও উপায় নেই।

স্টাইল না করা বিষয়বস্তুর ফ্ল্যাশ কীভাবে এড়ানো যায়

ব্রাউজারগুলির একটি সম্ভাব্য সমস্যা যা এখনও ঘোষণামূলক শ্যাডো DOM সমর্থন করে না তা হল "ফ্ল্যাশ অফ আনস্টাইলড কন্টেন্ট" (FOUC) এড়ানো, যেখানে কাস্টম উপাদানগুলির জন্য কাঁচা বিষয়বস্তু দেখানো হয় যেগুলি এখনও আপগ্রেড করা হয়নি। Declarative Shadow DOM-এর আগে, FOUC এড়ানোর জন্য একটি সাধারণ কৌশল ছিল একটি display:none style নিয়ম কাস্টম এলিমেন্টগুলিতে প্রয়োগ করা যা এখনও লোড করা হয়নি, যেহেতু এগুলোর শ্যাডো রুট সংযুক্ত এবং জনবহুল হয়নি। এইভাবে, বিষয়বস্তু "প্রস্তুত" না হওয়া পর্যন্ত প্রদর্শিত হয় না:

<style>
  x-foo:not(:defined) > * {
    display: none;
  }
</style>

ঘোষণামূলক শ্যাডো ডম প্রবর্তনের সাথে, কাস্টম উপাদানগুলিকে এইচটিএমএলে রেন্ডার করা বা রচিত করা যেতে পারে যাতে ক্লায়েন্ট-সাইড কম্পোনেন্ট বাস্তবায়ন লোড হওয়ার আগে তাদের ছায়া বিষয়বস্তু যথাস্থানে এবং প্রস্তুত থাকে:

<x-foo>
  <template shadowrootmode="open">
    <style>h2 { color: blue; }</style>
    <h2>shadow content</h2>
  </template>
</x-foo>

এই ক্ষেত্রে, display:none "FOUC" নিয়ম ঘোষণামূলক শ্যাডো রুটের বিষয়বস্তু দেখানো থেকে বাধা দেবে। যাইহোক, এই নিয়মটি সরানো হলে ঘোষণামূলক শ্যাডো ডম পলিফিল লোড না হওয়া পর্যন্ত ডিক্লারেটিভ শ্যাডো ডম সমর্থন ছাড়া ব্রাউজারগুলিকে ভুল বা আনস্টাইল করা বিষয়বস্তু দেখাবে না যতক্ষণ না শ্যাডো রুট টেমপ্লেটটিকে একটি বাস্তব শ্যাডো রুটে রূপান্তরিত করে।

সৌভাগ্যবশত, FOUC শৈলীর নিয়ম পরিবর্তন করে CSS-এ এটি সমাধান করা যেতে পারে। ডিক্লারেটিভ শ্যাডো ডম সমর্থনকারী ব্রাউজারগুলিতে, <template shadowrootmode> উপাদানটি অবিলম্বে একটি ছায়া রুটে রূপান্তরিত হয়, DOM ট্রিতে কোনও <template> উপাদান থাকে না। যে ব্রাউজারগুলি ঘোষণামূলক ছায়া DOM সমর্থন করে না তারা <template> উপাদান সংরক্ষণ করে, যা আমরা FOUC প্রতিরোধ করতে ব্যবহার করতে পারি:

<style>
  x-foo:not(:defined) > template[shadowrootmode] ~ *  {
    display: none;
  }
</style>

এখনও সংজ্ঞায়িত করা হয়নি এমন কাস্টম উপাদান লুকানোর পরিবর্তে, সংশোধিত "FOUC" নিয়মটি তার সন্তানদের লুকিয়ে রাখে যখন তারা একটি <template shadowrootmode> উপাদান অনুসরণ করে। একবার কাস্টম উপাদান সংজ্ঞায়িত করা হলে, নিয়মটি আর মেলে না। ডিক্লারেটিভ শ্যাডো ডম সমর্থন করে এমন ব্রাউজারগুলিতে নিয়মটি উপেক্ষা করা হয় কারণ HTML পার্সিংয়ের সময় <template shadowrootmode> শিশুটি সরানো হয়।

বৈশিষ্ট্য সনাক্তকরণ এবং ব্রাউজার সমর্থন

ঘোষণামূলক শ্যাডো ডম ক্রোম 90 এবং এজ 91 থেকে উপলব্ধ, তবে এটি স্ট্যান্ডার্ডাইজড shadowrootmode অ্যাট্রিবিউটের পরিবর্তে shadowroot নামক একটি পুরানো অ-মানক বৈশিষ্ট্য ব্যবহার করেছে। নতুন shadowrootmode বৈশিষ্ট্য এবং স্ট্রিমিং আচরণ Chrome 111 এবং Edge 111 এ উপলব্ধ।

একটি নতুন ওয়েব প্ল্যাটফর্ম API হিসাবে, ঘোষণামূলক ছায়া DOM-এর এখনও সমস্ত ব্রাউজারে ব্যাপক সমর্থন নেই৷ HTMLTemplateElement এর প্রোটোটাইপে shadowRootMode প্রপার্টির অস্তিত্ব পরীক্ষা করে ব্রাউজার সমর্থন সনাক্ত করা যেতে পারে:

function supportsDeclarativeShadowDOM() {
  return HTMLTemplateElement.prototype.hasOwnProperty('shadowRootMode');
}

পলিফিল

ডিক্লারেটিভ শ্যাডো DOM-এর জন্য একটি সরলীকৃত পলিফিল তৈরি করা তুলনামূলকভাবে সহজ, যেহেতু একটি পলিফিলের জন্য টাইমিং সেম্যান্টিক বা পার্সার-অনলি বৈশিষ্ট্যগুলিকে পুরোপুরি প্রতিলিপি করার প্রয়োজন নেই যা একটি ব্রাউজার বাস্তবায়ন নিজেই উদ্বিগ্ন। ঘোষণামূলক শ্যাডো DOM পলিফিল করতে, আমরা সমস্ত <template shadowrootmode> উপাদানগুলি খুঁজে পেতে DOM স্ক্যান করতে পারি, তারপর তাদের মূল উপাদানে সংযুক্ত শ্যাডো রুটে রূপান্তর করতে পারি। এই প্রক্রিয়াটি একবার ডকুমেন্ট তৈরি হয়ে গেলে বা কাস্টম এলিমেন্ট লাইফসাইকেলের মতো আরও নির্দিষ্ট ইভেন্ট দ্বারা ট্রিগার করা যেতে পারে।

(function attachShadowRoots(root) {
  root.querySelectorAll("template[shadowrootmode]").forEach(template => {
    const mode = template.getAttribute("shadowrootmode");
    const shadowRoot = template.parentNode.attachShadow({ mode });

    shadowRoot.appendChild(template.content);
    template.remove();
    attachShadowRoots(shadowRoot);
  });
})(document);

আরও পড়া

,

ডিক্লারেটিভ শ্যাডো DOM হল একটি স্ট্যান্ডার্ড ওয়েব প্ল্যাটফর্ম বৈশিষ্ট্য , যা 90 সংস্করণ থেকে Chrome-এ সমর্থিত হয়েছে। উল্লেখ্য যে এই বৈশিষ্ট্যটির স্পেসিফিকেশন 2023 সালে পরিবর্তিত হয়েছিল ( shadowroot থেকে shadowrootmode নামকরণ সহ), এবং সবগুলির মধ্যে সবচেয়ে আপ টু ডেট প্রমিত সংস্করণ। বৈশিষ্ট্যের অংশগুলি Chrome সংস্করণ 124-এ অবতরণ করেছে৷

ব্রাউজার সমর্থন

  • ক্রোম: 111।
  • প্রান্ত: 111।
  • ফায়ারফক্স: 123।
  • সাফারি: 16.4.

উৎস

Shadow DOM হল তিনটি ওয়েব কম্পোনেন্ট স্ট্যান্ডার্ডের মধ্যে একটি, যা HTML টেমপ্লেট এবং কাস্টম এলিমেন্ট দ্বারা বৃত্তাকার। Shadow DOM একটি নির্দিষ্ট DOM সাবট্রিতে CSS শৈলী স্কোপ করার একটি উপায় প্রদান করে এবং সেই সাবট্রিটিকে নথির বাকি অংশ থেকে বিচ্ছিন্ন করে। <slot> উপাদানটি আমাদেরকে নিয়ন্ত্রণ করার একটি উপায় দেয় যেখানে একটি কাস্টম এলিমেন্টের শিশুদের ছায়া গাছের মধ্যে সন্নিবেশ করা উচিত। এই বৈশিষ্ট্যগুলি সম্মিলিতভাবে একটি স্বয়ংসম্পূর্ণ, পুনঃব্যবহারযোগ্য উপাদানগুলি তৈরি করার জন্য একটি সিস্টেমকে সক্ষম করে যা একটি অন্তর্নির্মিত HTML উপাদানের মতো বিদ্যমান অ্যাপ্লিকেশনগুলিতে বিরামহীনভাবে সংহত করে৷

এখন পর্যন্ত, Shadow DOM ব্যবহার করার একমাত্র উপায় ছিল জাভাস্ক্রিপ্ট ব্যবহার করে একটি ছায়া রুট তৈরি করা:

const host = document.getElementById('host');
const shadowRoot = host.attachShadow({mode: 'open'});
shadowRoot.innerHTML = '<h1>Hello Shadow DOM</h1>';

এই ধরনের একটি আবশ্যিক API ক্লায়েন্ট-সাইড রেন্ডারিংয়ের জন্য ভাল কাজ করে: একই জাভাস্ক্রিপ্ট মডিউলগুলি যা আমাদের কাস্টম উপাদানগুলিকে সংজ্ঞায়িত করে তাদের শ্যাডো রুট তৈরি করে এবং তাদের সামগ্রী সেট করে। যাইহোক, অনেক ওয়েব অ্যাপ্লিকেশনকে কনটেন্ট সার্ভার-সাইডে রেন্ডার করতে হবে বা বিল্ড টাইমে স্ট্যাটিক এইচটিএমএল করতে হবে। এটি দর্শকদের যুক্তিসঙ্গত অভিজ্ঞতা প্রদানের একটি গুরুত্বপূর্ণ অংশ হতে পারে যারা JavaScript চালাতে সক্ষম নাও হতে পারে।

সার্ভার-সাইড রেন্ডারিং (SSR) এর ন্যায্যতা প্রকল্প থেকে প্রকল্পে পরিবর্তিত হয়। অ্যাক্সেসিবিলিটি নির্দেশিকাগুলি পূরণ করার জন্য কিছু ওয়েবসাইটকে অবশ্যই সম্পূর্ণ কার্যকরী সার্ভার-রেন্ডার করা HTML প্রদান করতে হবে, অন্যরা ধীর সংযোগ বা ডিভাইসে ভাল পারফরম্যান্স নিশ্চিত করার উপায় হিসাবে একটি বেসলাইন নো-জাভাস্ক্রিপ্ট অভিজ্ঞতা প্রদান করতে বেছে নেয়।

ঐতিহাসিকভাবে, সার্ভার-সাইড রেন্ডারিংয়ের সংমিশ্রণে শ্যাডো ডম ব্যবহার করা কঠিন ছিল কারণ সার্ভার-জেনারেটেড এইচটিএমএলে শ্যাডো রুট প্রকাশ করার কোনো অন্তর্নির্মিত উপায় ছিল না। DOM উপাদানগুলির সাথে শ্যাডো রুট সংযুক্ত করার সময় কার্যক্ষমতার প্রভাব রয়েছে যা ইতিমধ্যেই তাদের ছাড়াই রেন্ডার করা হয়েছে। এটি পৃষ্ঠাটি লোড হওয়ার পরে লেআউট স্থানান্তরিত হতে পারে, বা শ্যাডো রুটের স্টাইলশীটগুলি লোড করার সময় সাময়িকভাবে আনস্টাইল না করা সামগ্রীর ("FOUC") একটি ফ্ল্যাশ দেখাতে পারে।

Declarative Shadow DOM (DSD) এই সীমাবদ্ধতাকে সরিয়ে দেয়, সার্ভারে Shadow DOM নিয়ে আসে।

একটি ঘোষণামূলক শ্যাডো রুট কীভাবে তৈরি করবেন

একটি ঘোষণামূলক শ্যাডো রুট হল একটি <template> উপাদান যার একটি shadowrootmode বৈশিষ্ট্য রয়েছে:

<host-element>
  <template shadowrootmode="open">
    <slot></slot>
  </template>
  <h2>Light content</h2>
</host-element>

shadowrootmode বৈশিষ্ট্য সহ একটি টেমপ্লেট উপাদান HTML পার্সার দ্বারা সনাক্ত করা হয় এবং অবিলম্বে এটির মূল উপাদানের ছায়া রুট হিসাবে প্রয়োগ করা হয়। উপরের নমুনা থেকে বিশুদ্ধ HTML মার্কআপ লোড করার ফলে নিম্নলিখিত DOM ট্রি দেখা যায়:

<host-element>
  #shadow-root (open)
  <slot>
    ↳
    <h2>Light content</h2>
  </slot>
</host-element>

এই কোড নমুনা ছায়া DOM বিষয়বস্তু প্রদর্শনের জন্য Chrome DevTools Elements প্যানেলের নিয়মাবলী অনুসরণ করছে। উদাহরণস্বরূপ, অক্ষরটি স্লটেড লাইট DOM বিষয়বস্তুর প্রতিনিধিত্ব করে।

এটি আমাদেরকে স্থির HTML-এ Shadow DOM এর এনক্যাপসুলেশন এবং স্লট প্রজেকশনের সুবিধা দেয়। শ্যাডো রুট সহ পুরো ট্রি তৈরি করতে কোনো জাভাস্ক্রিপ্টের প্রয়োজন নেই।

উপাদান হাইড্রেশন

ডিক্লারেটিভ শ্যাডো DOM শৈলী এনক্যাপসুলেট বা চাইল্ড প্লেসমেন্ট কাস্টমাইজ করার উপায় হিসাবে নিজে থেকে ব্যবহার করা যেতে পারে, কিন্তু কাস্টম উপাদানগুলির সাথে ব্যবহার করা হলে এটি সবচেয়ে শক্তিশালী। কাস্টম উপাদান ব্যবহার করে নির্মিত উপাদানগুলি স্ট্যাটিক HTML থেকে স্বয়ংক্রিয়ভাবে আপগ্রেড হয়ে যায়। ডিক্লেরেটিভ শ্যাডো ডম প্রবর্তনের সাথে, এটি আপগ্রেড হওয়ার আগে একটি কাস্টম উপাদানের জন্য একটি ছায়া রুট থাকা সম্ভব।

একটি কাস্টম উপাদান HTML থেকে আপগ্রেড করা হচ্ছে যার মধ্যে একটি ঘোষণামূলক শ্যাডো রুট রয়েছে ইতিমধ্যেই সেই ছায়া রুট সংযুক্ত থাকবে৷ এর মানে হল যে উপাদানটির একটি shadowRoot প্রপার্টি ইতিমধ্যেই উপলব্ধ থাকবে যখন এটি ইনস্ট্যান্ট করা হয়, আপনার কোডটি স্পষ্টভাবে তৈরি না করে। আপনার এলিমেন্টের কনস্ট্রাক্টরে বিদ্যমান শ্যাডো রুটের জন্য this.shadowRoot চেক করা ভাল। যদি ইতিমধ্যে একটি মান থাকে, তাহলে এই উপাদানটির জন্য HTML-এ একটি ঘোষণামূলক শ্যাডো রুট অন্তর্ভুক্ত থাকে। মানটি শূন্য হলে, HTML-এ কোনো ঘোষণামূলক শ্যাডো রুট উপস্থিত ছিল না বা ব্রাউজার ঘোষণামূলক শ্যাডো DOM সমর্থন করে না।

<menu-toggle>
  <template shadowrootmode="open">
    <button>
      <slot></slot>
    </button>
  </template>
  Open Menu
</menu-toggle>
<script>
  class MenuToggle extends HTMLElement {
    constructor() {
      super();

      // Detect whether we have SSR content already:
      if (this.shadowRoot) {
        // A Declarative Shadow Root exists!
        // wire up event listeners, references, etc.:
        const button = this.shadowRoot.firstElementChild;
        button.addEventListener('click', toggle);
      } else {
        // A Declarative Shadow Root doesn't exist.
        // Create a new shadow root and populate it:
        const shadow = this.attachShadow({mode: 'open'});
        shadow.innerHTML = `<button><slot></slot></button>`;
        shadow.firstChild.addEventListener('click', toggle);
      }
    }
  }

  customElements.define('menu-toggle', MenuToggle);
</script>

কাস্টম এলিমেন্টগুলি কিছু সময়ের জন্য প্রায় ছিল, এবং এখন পর্যন্ত attachShadow() ব্যবহার করে একটি তৈরি করার আগে একটি বিদ্যমান শ্যাডো রুট পরীক্ষা করার কোন কারণ ছিল না। ডিক্লারেটিভ শ্যাডো ডিওএম-এ একটি ছোট পরিবর্তন রয়েছে যা বিদ্যমান উপাদানগুলিকে এটি সত্ত্বেও কাজ করার অনুমতি দেয়: বিদ্যমান ডিক্লারেটিভ শ্যাডো রুট সহ একটি উপাদানে attachShadow() পদ্ধতিতে কল করলে কোনও ত্রুটি হবে না । পরিবর্তে, ঘোষণামূলক শ্যাডো রুট খালি করা হয় এবং ফিরে আসে। এটি ঘোষণামূলক শ্যাডো DOM-এর জন্য নির্মিত নয় এমন পুরানো উপাদানগুলিকে কাজ চালিয়ে যাওয়ার অনুমতি দেয়, যেহেতু একটি অপরিহার্য প্রতিস্থাপন তৈরি না হওয়া পর্যন্ত ঘোষণামূলক মূলগুলি সংরক্ষণ করা হয়।

নতুন তৈরি কাস্টম এলিমেন্টের জন্য, একটি নতুন ElementInternals.shadowRoot প্রপার্টি একটি এলিমেন্টের বিদ্যমান ডিক্লারেটিভ শ্যাডো রুট, খোলা এবং বন্ধ উভয় ক্ষেত্রেই একটি রেফারেন্স পাওয়ার একটি সুস্পষ্ট উপায় প্রদান করে। এটি যেকোন ডিক্লারেটিভ শ্যাডো রুট চেক করতে এবং ব্যবহার করতে ব্যবহার করা যেতে পারে, যখন এটি প্রদান করা হয়নি এমন ক্ষেত্রে attachShadow() -এ ফিরে আসে।

class MenuToggle extends HTMLElement {
  constructor() {
    super();

    const internals = this.attachInternals();

    // check for a Declarative Shadow Root:
    let shadow = internals.shadowRoot;

    if (!shadow) {
      // there wasn't one. create a new Shadow Root:
      shadow = this.attachShadow({
        mode: 'open'
      });
      shadow.innerHTML = `<button><slot></slot></button>`;
    }

    // in either case, wire up our event listener:
    shadow.firstChild.addEventListener('click', toggle);
  }
}

customElements.define('menu-toggle', MenuToggle);

মূল প্রতি এক ছায়া

একটি ঘোষণামূলক শ্যাডো রুট শুধুমাত্র তার মূল উপাদানের সাথে যুক্ত। এর অর্থ হল ছায়া শিকড়গুলি সর্বদা তাদের সম্পর্কিত উপাদানের সাথে colocated হয়। এই নকশার সিদ্ধান্তটি নিশ্চিত করে যে ছায়া শিকড়গুলি একটি HTML নথির বাকি অংশের মতো স্ট্রিমযোগ্য। এটি প্রণয়ন এবং প্রজন্মের জন্যও সুবিধাজনক, যেহেতু একটি উপাদানে একটি শ্যাডো রুট যোগ করার জন্য বিদ্যমান শ্যাডো রুটগুলির একটি রেজিস্ট্রি বজায় রাখার প্রয়োজন হয় না।

শ্যাডো রুটকে তাদের প্যারেন্ট এলিমেন্টের সাথে যুক্ত করার ট্রেডঅফ হল যে একই ডিক্লেরেটিভ শ্যাডো রুট <template> > থেকে একাধিক এলিমেন্ট শুরু করা সম্ভব নয়। যাইহোক, ডিক্লারেটিভ শ্যাডো ডিওএম ব্যবহার করা হয় এমন বেশিরভাগ ক্ষেত্রে এটি গুরুত্বপূর্ণ হওয়ার সম্ভাবনা নেই, যেহেতু প্রতিটি শ্যাডো রুটের বিষয়বস্তু খুব কমই অভিন্ন। যদিও সার্ভার-রেন্ডার করা HTML-এ প্রায়শই পুনরাবৃত্ত উপাদান কাঠামো থাকে, তবে তাদের বিষয়বস্তু সাধারণত ভিন্ন হয়-উদাহরণস্বরূপ, পাঠ্য বা বৈশিষ্ট্যের সামান্য ভিন্নতা। যেহেতু একটি ক্রমিক ঘোষণামূলক শ্যাডো রুটের বিষয়বস্তু সম্পূর্ণরূপে স্থির, একটি একক ঘোষণামূলক শ্যাডো রুট থেকে একাধিক উপাদান আপগ্রেড করা শুধুমাত্র তখনই কাজ করবে যদি উপাদানগুলি অভিন্ন হয়। অবশেষে, কম্প্রেশনের প্রভাবের কারণে নেটওয়ার্ক স্থানান্তরের আকারে বারবার অনুরূপ ছায়া শিকড়ের প্রভাব তুলনামূলকভাবে ছোট।

ভবিষ্যতে, ভাগ করা ছায়া শিকড়গুলিকে পুনরায় দেখার জন্য এটি সম্ভব হতে পারে৷ যদি DOM অন্তর্নির্মিত টেমপ্লেটিং- এর জন্য সমর্থন লাভ করে, ঘোষণামূলক শ্যাডো রুটগুলিকে টেমপ্লেট হিসাবে বিবেচনা করা যেতে পারে যা একটি প্রদত্ত উপাদানের জন্য ছায়া রুট তৈরি করার জন্য তাত্ক্ষণিকভাবে তৈরি করা হয়। বর্তমান ঘোষণামূলক ছায়া DOM নকশা একটি একক উপাদানে ছায়া রুট অ্যাসোসিয়েশন সীমাবদ্ধ করে ভবিষ্যতে এই সম্ভাবনার অস্তিত্বের অনুমতি দেয়।

স্ট্রিমিং শান্ত

ডিক্লারেটিভ শ্যাডো রুটকে সরাসরি তাদের মূল উপাদানের সাথে সংযুক্ত করা সেই উপাদানটিকে আপগ্রেড করার এবং সংযুক্ত করার প্রক্রিয়াকে সহজ করে। ঘোষণামূলক শ্যাডো রুটগুলি এইচটিএমএল পার্সিংয়ের সময় সনাক্ত করা হয়, এবং তাদের খোলার <template> ট্যাগের সম্মুখীন হলে সাথে সাথে সংযুক্ত করা হয়। <template> -এর মধ্যে পার্স করা এইচটিএমএল সরাসরি শ্যাডো রুটে পার্স করা হয়, তাই এটি "স্ট্রিম করা" হতে পারে: এটি প্রাপ্ত হওয়ার সাথে সাথে রেন্ডার করা হয়।

<div id="el">
  <script>
    el.shadowRoot; // null
  </script>

  <template shadowrootmode="open">
    <!-- shadow realm -->
  </template>

  <script>
    el.shadowRoot; // ShadowRoot
  </script>
</div>

শুধুমাত্র পার্সার

ঘোষণামূলক ছায়া DOM হল HTML পার্সারের একটি বৈশিষ্ট্য। এর মানে হল যে একটি ঘোষণামূলক শ্যাডো রুট শুধুমাত্র পার্স করা হবে এবং <template> ট্যাগের জন্য shadowrootmode অ্যাট্রিবিউট সহ সংযুক্ত করা হবে যা HTML পার্সিংয়ের সময় উপস্থিত থাকে। অন্য কথায়, প্রাথমিক HTML পার্সিংয়ের সময় ঘোষণামূলক শ্যাডো রুট তৈরি করা যেতে পারে:

<some-element>
  <template shadowrootmode="open">
    shadow root content for some-element
  </template>
</some-element>

একটি <template> উপাদানের shadowrootmode বৈশিষ্ট্য সেট করা কিছুই করে না, এবং টেমপ্লেটটি একটি সাধারণ টেমপ্লেট উপাদান থেকে যায়:

const div = document.createElement('div');
const template = document.createElement('template');
template.setAttribute('shadowrootmode', 'open'); // this does nothing
div.appendChild(template);
div.shadowRoot; // null

কিছু গুরুত্বপূর্ণ নিরাপত্তা বিবেচনা এড়াতে, innerHTML বা insertAdjacentHTML() মতো খণ্ড পার্সিং API ব্যবহার করে ঘোষণামূলক শ্যাডো রুট তৈরি করা যাবে না। ডিক্লারেটিভ শ্যাডো রুট প্রয়োগ করে HTML পার্স করার একমাত্র উপায় হল setHTMLUnsafe() বা parseHTMLUnsafe() :

<script>
  const html = `
    <div>
      <template shadowrootmode="open"></template>
    </div>
  `;
  const div = document.createElement('div');
  div.innerHTML = html; // No shadow root here
  div.setHTMLUnsafe(html); // Shadow roots included
  const newDocument = Document.parseHTMLUnsafe(html); // Also here
</script>

শৈলী সহ সার্ভার-রেন্ডারিং

স্ট্যান্ডার্ড <style> এবং <link> ট্যাগ ব্যবহার করে ঘোষণামূলক শ্যাডো রুটের ভিতরে ইনলাইন এবং বাহ্যিক স্টাইলশীটগুলি সম্পূর্ণরূপে সমর্থিত:

<nineties-button>
  <template shadowrootmode="open">
    <style>
      button {
        color: seagreen;
      }
    </style>
    <link rel="stylesheet" href="/comicsans.css" />
    <button>
      <slot></slot>
    </button>
  </template>
  I'm Blue
</nineties-button>

এইভাবে নির্দিষ্ট করা শৈলীগুলিও অত্যন্ত অপ্টিমাইজ করা হয়েছে: যদি একই স্টাইল শীট একাধিক ঘোষণামূলক শ্যাডো রুটে উপস্থিত থাকে তবে এটি শুধুমাত্র একবার লোড এবং পার্স করা হয়। ব্রাউজারটি একটি একক ব্যাকিং CSSStyleSheet ব্যবহার করে যা সমস্ত ছায়া শিকড় দ্বারা ভাগ করা হয়, ডুপ্লিকেট মেমরি ওভারহেড দূর করে৷

Declarative Shadow DOM-এ নির্মাণযোগ্য স্টাইলশীট সমর্থিত নয়। এর কারণ হল, বর্তমানে, HTML-এ নির্মাণযোগ্য স্টাইলশীটগুলিকে সিরিয়ালাইজ করার কোনও উপায় নেই এবং adoptedStyleSheets পপুলেট করার সময় তাদের উল্লেখ করার কোনও উপায় নেই।

স্টাইল না করা বিষয়বস্তুর ফ্ল্যাশ কীভাবে এড়ানো যায়

ব্রাউজারগুলির একটি সম্ভাব্য সমস্যা যা এখনও ঘোষণামূলক শ্যাডো DOM সমর্থন করে না তা হল "ফ্ল্যাশ অফ আনস্টাইলড কন্টেন্ট" (FOUC) এড়ানো, যেখানে কাস্টম উপাদানগুলির জন্য কাঁচা বিষয়বস্তু দেখানো হয় যেগুলি এখনও আপগ্রেড করা হয়নি। Declarative Shadow DOM-এর আগে, FOUC এড়ানোর জন্য একটি সাধারণ কৌশল ছিল একটি display:none style নিয়ম কাস্টম এলিমেন্টগুলিতে প্রয়োগ করা যা এখনও লোড করা হয়নি, যেহেতু এগুলোর শ্যাডো রুট সংযুক্ত এবং জনবহুল হয়নি। এইভাবে, বিষয়বস্তু "প্রস্তুত" না হওয়া পর্যন্ত প্রদর্শিত হয় না:

<style>
  x-foo:not(:defined) > * {
    display: none;
  }
</style>

ঘোষণামূলক শ্যাডো ডম প্রবর্তনের সাথে, কাস্টম উপাদানগুলিকে এইচটিএমএলে রেন্ডার করা বা রচিত করা যেতে পারে যাতে ক্লায়েন্ট-সাইড কম্পোনেন্ট বাস্তবায়ন লোড হওয়ার আগে তাদের ছায়া বিষয়বস্তু যথাস্থানে এবং প্রস্তুত থাকে:

<x-foo>
  <template shadowrootmode="open">
    <style>h2 { color: blue; }</style>
    <h2>shadow content</h2>
  </template>
</x-foo>

এই ক্ষেত্রে, display:none "FOUC" নিয়ম ঘোষণামূলক শ্যাডো রুটের বিষয়বস্তু দেখানো থেকে বাধা দেবে। যাইহোক, এই নিয়মটি সরানো হলে ঘোষণামূলক শ্যাডো ডম পলিফিল লোড না হওয়া পর্যন্ত ডিক্লারেটিভ শ্যাডো ডম সমর্থন ছাড়া ব্রাউজারগুলিকে ভুল বা আনস্টাইল করা বিষয়বস্তু দেখাবে না যতক্ষণ না শ্যাডো রুট টেমপ্লেটটিকে একটি বাস্তব শ্যাডো রুটে রূপান্তরিত করে।

সৌভাগ্যবশত, FOUC শৈলীর নিয়ম পরিবর্তন করে CSS-এ এটি সমাধান করা যেতে পারে। ডিক্লারেটিভ শ্যাডো ডম সমর্থনকারী ব্রাউজারগুলিতে, <template shadowrootmode> উপাদানটি অবিলম্বে একটি ছায়া রুটে রূপান্তরিত হয়, DOM ট্রিতে কোনও <template> উপাদান থাকে না। যে ব্রাউজারগুলি ঘোষণামূলক ছায়া DOM সমর্থন করে না তারা <template> উপাদান সংরক্ষণ করে, যা আমরা FOUC প্রতিরোধ করতে ব্যবহার করতে পারি:

<style>
  x-foo:not(:defined) > template[shadowrootmode] ~ *  {
    display: none;
  }
</style>

এখনও সংজ্ঞায়িত করা হয়নি এমন কাস্টম উপাদান লুকানোর পরিবর্তে, সংশোধিত "FOUC" নিয়মটি তার সন্তানদের লুকিয়ে রাখে যখন তারা একটি <template shadowrootmode> উপাদান অনুসরণ করে। একবার কাস্টম উপাদান সংজ্ঞায়িত করা হলে, নিয়মটি আর মেলে না। ডিক্লারেটিভ শ্যাডো ডম সমর্থন করে এমন ব্রাউজারগুলিতে নিয়মটি উপেক্ষা করা হয় কারণ HTML পার্সিংয়ের সময় <template shadowrootmode> শিশুটি সরানো হয়।

বৈশিষ্ট্য সনাক্তকরণ এবং ব্রাউজার সমর্থন

ঘোষণামূলক শ্যাডো ডম ক্রোম 90 এবং এজ 91 থেকে উপলব্ধ, তবে এটি স্ট্যান্ডার্ডাইজড shadowrootmode অ্যাট্রিবিউটের পরিবর্তে shadowroot নামক একটি পুরানো অ-মানক বৈশিষ্ট্য ব্যবহার করেছে। নতুন shadowrootmode বৈশিষ্ট্য এবং স্ট্রিমিং আচরণ Chrome 111 এবং Edge 111 এ উপলব্ধ।

একটি নতুন ওয়েব প্ল্যাটফর্ম API হিসাবে, ঘোষণামূলক ছায়া DOM-এর এখনও সমস্ত ব্রাউজারে ব্যাপক সমর্থন নেই৷ HTMLTemplateElement এর প্রোটোটাইপে shadowRootMode প্রপার্টির অস্তিত্ব পরীক্ষা করে ব্রাউজার সমর্থন সনাক্ত করা যেতে পারে:

function supportsDeclarativeShadowDOM() {
  return HTMLTemplateElement.prototype.hasOwnProperty('shadowRootMode');
}

পলিফিল

ডিক্লারেটিভ শ্যাডো DOM-এর জন্য একটি সরলীকৃত পলিফিল তৈরি করা তুলনামূলকভাবে সহজ, যেহেতু একটি পলিফিলের জন্য টাইমিং সেম্যান্টিক বা পার্সার-অনলি বৈশিষ্ট্যগুলিকে পুরোপুরি প্রতিলিপি করার প্রয়োজন নেই যা একটি ব্রাউজার বাস্তবায়ন নিজেই উদ্বিগ্ন। ঘোষণামূলক শ্যাডো DOM পলিফিল করতে, আমরা সমস্ত <template shadowrootmode> উপাদানগুলি খুঁজে পেতে DOM স্ক্যান করতে পারি, তারপর তাদের মূল উপাদানে সংযুক্ত শ্যাডো রুটে রূপান্তর করতে পারি। এই প্রক্রিয়াটি একবার ডকুমেন্ট তৈরি হয়ে গেলে বা কাস্টম এলিমেন্ট লাইফসাইকেলের মতো আরও নির্দিষ্ট ইভেন্ট দ্বারা ট্রিগার করা যেতে পারে।

(function attachShadowRoots(root) {
  root.querySelectorAll("template[shadowrootmode]").forEach(template => {
    const mode = template.getAttribute("shadowrootmode");
    const shadowRoot = template.parentNode.attachShadow({ mode });

    shadowRoot.appendChild(template.content);
    template.remove();
    attachShadowRoots(shadowRoot);
  });
})(document);

আরও পড়া