محدوده بندی CSS با استفاده از Shadow DOM

آفلاین
user-avatar
عرفان حشمتی
05 شهریور 1400, خواندن در 6 دقیقه

مکانیزمی برای جلوگیری از غلبه بر استایل‌های CSS با استفاده از Shadow DOM.

به عنوان یک توسعه دهنده وب که با یک تیم بزرگ کار می‌کند، مشکل اساسی که اخیرا با آن روبرو شده‌ام، مدیریت استایل برای کامپوننت‌هاست. داشتن یک فایل استایل مشترک برای کامپوننت‌ها همیشه منجر به تضاد در یک ظاهر طراحی می‌شود، زیرا معمولا برای دو توسعه دهنده نام گذاری یک کلاس با استفاده از نام یکسان معمولا صورت می‌گیرد.

CSS خطایی برای این کار ایجاد نمی‌کند. در نتیجه من یک استایل غیرمنتظره در کامپوننت‌هایی که برای حل آنها زمان‌بر است، تجربه کردم.

تکنیکی که قصد دارم در اینجا معرفی کنم به شما یک راه حل برای جلوگیری از تداخل نام گذاری در CSS می‌دهد.

Shadow DOM چیست؟

Shadow DOM بخشی از Document Object Model است که قادر به جداسازی JavaScript و CSS می‌باشد. اگر در مورد iframes شنیده باشید، Shadow DOM نیز چیزی است که دارای قابلیت‌های مشابه است.

درست مانند iframes به طور پیش فرض استایل‌های درون Shadow DOM به بیرون نشت نکرده و استایل‌های خارج از آن نیز به داخل نفوذ نمی‌کنند.

روش‌هایی وجود دارد که در صورت لزوم برخی از استایل‌ها را در خارج از Shadow DOM به ارث ببرید.

ساختار Shadow DOM

کتابخانه‌های CSS مانند Styled-component نیز با تولید یک نام کلاس تصادفی مانند kjkgh2en3. مسئله تداخل نام را حل می‌کنند. با این حال Shadow DOM کپسوله سازی استایل را با طراحی ارائه می‌دهد.

در مرحله بعدی بیایید نگاهی به نحوه افزودن Shadow DOM بیندازیم.

آیا می‌توانیم از آن در هر پروژه‌ای استفاده کنیم؟

اگرچه مرورگرهای مدرن از Web Component Specification پشتیبانی می‌کنند، اما اگر بخواهیم از آن برای برنامه‌های موجود استفاده کنیم، چالش‌هایی به وجود می‌آید.

این بیشتر شبیه استاندارد سازی تعریف کامپوننت‌ها برای مرورگر است، جایی که می‌توانید عناصر جدیدی را همانطور که باReact ، Angular و ... انجام می‌دهید، ایجاد کنید.

بنابراین بررسی امکان پذیر بودن Shadow DOM بسته به کتابخانه‌های کامپوننتی که استفاده می‌کنید، ضروری است.

افزودن Shadow DOM

دو روش برای افزودن Shadow DOM وجود دارد.

  1. Open Mode
  2. Close Mode

Open Mode

class MyComponentOpenRoot extends HTMLElement {
   constructor() {
      super();
      this.attachShadow({ mode: 'open' });
      this.close = this.close.bind(this);
   }
}

اتصال Shadow DOM با mode: 'open' باعث می‌شود تا shadow root در element.shadowRoot ذخیره شود. بنابراین از طریق این مرجع می‌توانیم به shadow root دسترسی پیدا کنیم.

Close Mode

این برخلاف روش قبل مرجع ذخیره نمی‌کند. اگر از close mode استفاده کنیم، باید روش ذخیره سازی و بازیابی خود را با استفاده از یک Weak Map یا یک شی ایجاد کنیم.

const shadowRoots = new WeakMap();
class MyComponentClosedRoot extends HTMLElement {
   constructor() {
     super();
     const shadowRoot = this.attachShadow({ mode: 'closed' });
     shadowRoots.set(this, shadowRoot);
   }
   connectedCallback() {
     const shadowRoot = shadowRoots.get(this);
     shadowRoot.innerHTML = `<h1>Hello!</h1>`;
   }
}

اکنون که Shadow DOM را ایجاد کردیم، بیایید نحوه اتصال و اعمال استایل‌ها به گره‌های Shadow DOM را بررسی کنیم.

ما از اینجا به بعد از open mode استفاده خواهیم کرد.

اتصال استایل‌ها در Shadow DOM

class MyComponentOpenRoot extends HTMLElement {  
  constructor() {
    super();
    this.attachShadow({ mode: 'open' });
    this.close = this.close.bind(this);
  }
  
  connectedCallback() {
    const { shadowRoot } = this;
    shadowRoot.innerHTML = `<style>
      .wrapper {
        opacity: 0;
        transition: visibility 0s, opacity 0.25s ease-in;
      }

      .overlay {
        height: 100%;
        position: fixed;
        top: 0;
        right: 0;
      }

      button {
        cursor: pointer;
        font-size: 1.25rem;
      }
    </style>
    <div class="wrapper">
    <div class="overlay"></div>
      <div>
        <button class="close">✖️</button>
        <h1 id="title">Hello world</h1>
        <div id="content" class="content">
          <p>This is content outside of the shadow DOM</p>
        </div>
      </div>
    </div>`;
  }
}

تمام استایل‌های مورد نیاز برای گره‌های Shadow DOM را می‌توان به روش فوق مشخص کرد. این استایل‌ها فقط به گره‌های داخل Shadow DOM اعمال می‌شوند، زیرا به shadow root متصل خواهند شد.

Shadow DOM به صورت زیر در Chrome Dev Tools نشان داده می‌شود.

تا اینجا Shadow DOM بسیار جذاب به نظر می‌رسد. در ادامه راهی برای خارج کردن CSS بدون هیچ گونه ترفندی خواهیم داشت.

استفاده از Shadow DOM در عمل

  1. گزینه‌های دیگری برای Shadow DOM وجود دارد مانند styled-components. با این حال از آنجا که styled-components حاوی CSS در JS هستند، عملکرد کمتری نسبت به Shadow DOM دارد. اما اگر در پروژه خود از styled-components استفاده کرده‌اید، می‌توانید به جای آنکه برای کپسوله سازی استیل از Shadow DOM استفاده کنید، به آن پایبند باشید.
  2. حتی اگر Shadow DOM ابزارهای قدرتمندی را ارائه دهد، ما نباید همیشه از آن استفاده کنیم. به عنوان مثال اگر یک عنصر <form> در DOM خود دارید، نباید از Shadow DOM برای اجزای داخل فرم مانند input یا textarea استفاده کنید. دلیلش هم این است که شما نمی‌توانید از بیرون گره‌های داخل shadow tree را جستجو کنید. بنابراین فرم کامپوننت‌های استفاده شده از Shadow DOM را نادیده می‌گیرد.
  3. اگر می‌خواهید کامپوننت خود را با استفاده از یک شیوه نامه جهانی CSS استایل دهی کنید، باید از استفاده Shadow DOM در آن کامپوننت خاص خودداری کنید، زیرا در صورت استفاده از آن استایل‌های گلوبال اعمال نمی‌شوند.
  4. اگر از Shadow DOM در کامپوننت خود استفاده می‌کنید، باید با انتشار رویدادها با دقت رفتار کنید، زیرا استفاده از رویدادهای رابط کاربری در داخل و خارج از محدوده shadow متفاوت است.
  5. اگر از پلاگین‌ها یا ابزارهای شخص ثالث زیادی در برنامه خود استفاده می‌کنید، باید توجه داشته باشید که برخی از اینها ممکن است با کامپوننت‌های سازنده Shadow DOM کار نکنند، زیرا برای مقابله با آن ساخته نشده‌اند.
  6. Shadow DOM از عناصر <slot> پشتیبانی می‌کند که در آن می‌توانید کامپوننت‌های خود را از Light DOM به پوزیشن‌های Shadow DOM تبدیل کنید. هنگامی که از <slot> استفاده می‌شود، مرورگر کامپوزیشن را اجرا کرده و عناصر Light DOM را در اسلات‌های مربوطه در Shadow DOM رندر می‌کند.
  7. روش‌های بیشتری برای تعریف Shadow DOM وجود دارد. به عنوان مثال Declarative Shadow DOM که Shadow DOM را به سرور می‌آورد. اگر علاقه مند به کسب اطلاعات بیشتر در مورد Shadow DOM هستید، آن را حتما مورد بررسی قرار دهید.
  8. هنگام تقسیم کامپوننت‌های مختلف بین پروژه‌های وب، استفاده از ابزاری مانند Bit ضروری است. یک کامپوننت قابل استفاده مجدد باید از هرگونه تداخل نام گذاری احتمالی در محیط‌های میزبانی جلوگیری کند. به عنوان مثال styled component زیر که در Bit به اشتراک گذاشته، بدون نگرانی از تداخل‌ می‌تواند در هر پروژه‌ای استفاده شود.

کامپوننت button به اشتراک گذاشته شده در Bit

Shadow DOM جداسازی به صورت out-of-the-box و کپسوله سازی DOM را نیز فراهم می‌کند که برای کامپوننت‌های قابل استفاده مجدد و خودکار برای رابط کاربری شما مناسب است.

سازگاری با مرورگر

اگر برنامه شما باید در اینترنت اکسپلورر اجرا شود، Shadow DOM گزینه مناسبی نیست، زیرا هیچ پشتیبانی از اینترنت اکسپلورر را ندارد. اما بقیه مرورگرهایی که معمولا استفاده می‌شوند با پشتیبانی از Shadow DOM همراه هستند.

جمع بندی

اگر بدون نگرانی در مورد تداخل نام کلاس استایل‌ها، به توسعه سازنده و کارآمد فرانت-اند علاقه مند هستید، Shadow DOM گزینه بسیار خوبی است. اینکه از Shadow DOM استفاده کنید یا از کتابخانه‌های CSS مانند styled-component کاملا به خود شما بستگی دارد.

من شخصا Shadow DOM را ترجیح می‌دهم، زیرا styled-componentها از CSS در JS استفاده می‌کنند که عملکرد کمتری دارد. اما با بهره گیری از Shadow DOM توسعه دهندگان کنترل کاملی در مورد نحوه ارائه کامپوننت خود دارند.

اگر می‌خواهید از مفاهیم پیشرفته Shadow DOM اطلاعات بیشتری کسب کنید، در بخش نظرات زیر به ما اطلاع دهید. Shadow DOM موضوعی گسترده با مفاهیم زیادی برای یادگیری و کاوش است.

امیدوارم از طریق این مقاله اهمیت Shadow DOM را فرا گرفته باشید.

منبع

چه امتیازی به این مقاله می دید؟
خیلی بد
بد
متوسط
خوب
عالی

دیدگاه‌ها و پرسش‌ها

برای ارسال دیدگاه لازم است، ابتدا وارد سایت شوید.

در حال دریافت نظرات از سرور، لطفا منتظر بمانید

در حال دریافت نظرات از سرور، لطفا منتظر بمانید

آفلاین
user-avatar
عرفان حشمتی @heshmati74
مهندس معماری سیستم های کامپیوتری، طراح و توسعه دهنده وب سایت
دنبال کردن

گفتگو‌ برنامه نویسان

بخشی برای حل مشکلات برنامه‌نویسی و مباحث پیرامون آن وارد شو