شروع به کار با Style Queries

قابلیت پرس‌وجوی اندازه درون‌خطی والد و مقادیر واحد پرس‌وجوی کانتینر، اخیراً در تمام موتورهای مرورگر مدرن به پشتیبانی پایدار رسیده است.

Browser Support

  • کروم: ۱۰۵.
  • لبه: ۱۰۵.
  • فایرفاکس: ۱۱۰.
  • سافاری: ۱۶.

Source

با این حال، مشخصات مربوط به مهاربندی شامل مواردی بیش از پرس‌وجوهای مربوط به اندازه است؛ همچنین امکان پرس‌وجو از مقادیر سبک والد را فراهم می‌کند. از Chromium 111، می‌توانید مهاربندی سبک را برای مقادیر ویژگی سفارشی اعمال کنید و از یک عنصر والد برای مقدار یک ویژگی سفارشی پرس‌وجو کنید.

Browser Support

  • کروم: ۱۱۱.
  • لبه: ۱۱۱.
  • فایرفاکس: ۱۵۱.
  • سافاری: ۱۸.

این یعنی ما کنترل منطقی بیشتری روی استایل‌ها در CSS داریم و جداسازی بهتر لایه منطق و داده یک برنامه از استایل‌های آن را امکان‌پذیر می‌کند.

مشخصات سطح ۳ ماژول مهار CSS، که شامل کوئری‌های اندازه و سبک است، امکان کوئری گرفتن از هر سبکی را از یک والد فراهم می‌کند، از جمله جفت‌های ویژگی و مقدار مانند font-weight: 800 با این حال، در حال حاضر، کوئری‌های سبک فقط با مقادیر ویژگی سفارشی CSS کار می‌کنند. این هنوز هم برای ترکیب سبک‌ها و جداسازی داده‌ها از طراحی بسیار مفید است. بیایید نگاهی به نحوه استفاده از کوئری‌های سبک با ویژگی‌های سفارشی CSS بیندازیم:

شروع کار با کوئری‌های استایل

فرض کنید HTML زیر را داریم:

<ul class="card-list">
  <li class="card-container">
    <div class="card">
      ...
    </div>
  </li>
</ul>

برای استفاده از کوئری‌های استایل، ابتدا باید یک عنصر نگهدارنده تنظیم کنید. این کار بسته به اینکه آیا از یک والد مستقیم یا غیرمستقیم کوئری می‌گیرید، رویکردی کمی متفاوت می‌طلبد.

پرس و جو از والدین مستقیم

نمودار یک پرس‌وجوی سبک.

برخلاف کوئری‌های استایل، برای اینکه .card بتواند استایل‌های والد مستقیم خود را کوئری کند، نیازی به اعمال محدودیت با استفاده از container-type یا ویژگی container به .card-container ندارید. با این حال، ما باید استایل‌ها (مقادیر سفارشی در این مورد) را به یک کانتینر (در این مورد .card-container ) یا هر عنصری که حاوی عنصری است که در DOM استایل‌بندی می‌کنیم، اعمال کنیم. ما نمی‌توانیم استایل‌هایی را که کوئری می‌کنیم روی عنصر مستقیمی که با استفاده از آن کوئری استایل‌بندی می‌کنیم، اعمال کنیم، زیرا این امر می‌تواند باعث حلقه‌های بی‌نهایت شود.

برای پرس و جوی مستقیم از والد، می‌توانید بنویسید:

/* styling .card based on the value of --theme on .card-container */
@container style(--theme: warm) {
  .card {
    background-color: wheat;
    border-color: brown; 
    ...
  }
}

شاید متوجه شده باشید که کوئری استایل، کوئری را با style() می‌پوشاند. این کار برای رفع ابهام از مقادیر اندازه از استایل‌ها است. برای مثال، می‌توانید یک کوئری برای عرض کانتینر به صورت @container (min-width: 200px) { … } بنویسید. این کار در صورتی که کانتینر والد حداقل ۲۰۰ پیکسل عرض داشته باشد، استایل‌ها را اعمال می‌کند. با این حال، min-width همچنین می‌تواند یک ویژگی CSS باشد و می‌توانید با استفاده از کوئری‌های استایل، مقدار CSS مربوط به min-width را جستجو کنید. به همین دلیل است که از wrapper style() برای روشن شدن تفاوت استفاده می‌کنید: @container style(min-width: 200px) { … } .

سبک دادن به والدین غیر مستقیم

اگر می‌خواهید استایل‌های مربوط به هر عنصری که والد مستقیم آن نیست را جستجو کنید، باید به آن عنصر یک container-name بدهید. برای مثال، می‌توانیم استایل‌ها را بر اساس استایل‌های .card-list به .card -list اعمال کنیم، برای این کار باید به .card-list یک container-name بدهیم و در کوئری استایل به آن ارجاع دهیم.

/* styling .card based on the value of --moreGlobalVar on .card-list */
@container cards style(--moreGlobalVar: value) {
  .card {
    ...
  }
}

به طور کلی، بهترین روش این است که برای کانتینرهای خود نام تعیین کنید تا مشخص شود چه چیزی را جستجو می‌کنید و دسترسی به آن کانتینرها را آسان‌تر کنید. یک مثال از کاربرد این روش این است که اگر می‌خواهید عناصر درون .card را مستقیماً استایل‌دهی کنید. بدون یک کانتینر نامگذاری شده در .card-container ، آنها نمی‌توانند مستقیماً از آن پرس‌وجو کنند.

اما همه اینها در عمل بسیار منطقی‌تر به نظر می‌رسند. بیایید نگاهی به چند مثال بیندازیم:

کوئری‌های استایل‌دهی در عمل

تصویر نمایشی با چندین کارت محصول، برخی با برچسب‌های «جدید» یا «موجودی کم» و کارت «موجودی کم» با پس‌زمینه قرمز.

کوئری‌های استایل به ویژه زمانی مفید هستند که شما یک کامپوننت قابل استفاده مجدد با چندین نوع مختلف دارید، یا زمانی که کنترلی بر روی همه استایل‌های خود ندارید اما نیاز به اعمال تغییرات در موارد خاص دارید. این مثال مجموعه‌ای از کارت‌های محصول را نشان می‌دهد که کامپوننت کارت یکسانی را به اشتراک می‌گذارند. برخی از کارت‌های محصول دارای جزئیات/یادداشت‌های اضافی مانند "جدید" یا "کمبود موجودی" هستند که توسط یک ویژگی سفارشی به نام --detail فعال می‌شوند. علاوه بر این، اگر محصولی در وضعیت "کمبود موجودی" باشد، یک پس‌زمینه با حاشیه قرمز پررنگ به آن داده می‌شود. این نوع اطلاعات احتمالاً توسط سرور رندر می‌شوند و می‌توانند از طریق استایل‌های درون‌خطی مانند موارد زیر به کارت‌ها اعمال شوند:

 <div class="product-list">
  <div class="product-card-container" style="--detail: new">
    <div class="product-card">
      <div class="media">
        <img .../>
      <div class="comment-block"></div>
    </div>
  </div>
  <div class="meta">
    ...
  </div>
  </div>
  <div class="product-card-container" style="--detail: low-stock">
    ...
  </div>
  <div class="product-card-container">
    ...
  </div>
  ...
</div>

با توجه به این داده‌های ساختاریافته، می‌توانید مقادیر را به --detail ارسال کنید و از این ویژگی سفارشی CSS برای اعمال استایل‌ها استفاده کنید:

@container style(--detail: new) {
  .comment-block {
    display: block;
  }
  
  .comment-block::after {
    content: 'New';
    border: 1px solid currentColor;
    background: white;
    ...
  }
}

@container style(--detail: low-stock) {
  .comment-block {
    display: block;
  }
  
  .comment-block::after {
    content: 'Low Stock';
    border: 1px solid currentColor;
    background: white;
    ...
  }
  
  .media-img {
    border: 2px solid brickred;
  }
}

کد بالا به ما اجازه می‌دهد تا یک چیپ برای --detail: low-stock و --detail: new اعمال کنیم، اما ممکن است متوجه مقداری افزونگی در بلوک کد شده باشید. در حال حاضر، هیچ راهی برای جستجوی فقط وجود --detail با @container style(--detail) وجود ندارد، که امکان اشتراک‌گذاری بهتر استایل‌ها و تکرار کمتر را فراهم می‌کند. این قابلیت در حال حاضر در گروه کاری در حال بحث است.

کارت‌های آب و هوا

مثال قبلی از یک ویژگی سفارشی واحد با چندین مقدار ممکن برای اعمال سبک‌ها استفاده کرد. اما می‌توانید با استفاده و پرس‌وجو برای چندین ویژگی سفارشی، آن را با هم مخلوط کنید. به این مثال کارت آب و هوا توجه کنید:

نسخه آزمایشی کارت‌های آب و هوا.

برای استایل دادن به گرادیان‌های پس‌زمینه و آیکون‌های این کارت‌ها، به دنبال ویژگی‌های آب و هوایی مانند «ابری»، «بارانی» یا «آفتابی» باشید:

@container style(--sunny: true) {
  .weather-card {
    background: linear-gradient(-30deg, yellow, orange);
  }
  
  .weather-card:after {
    content: url(<data-uri-for-demo-brevity>);
    background: gold;
  }
}

به این ترتیب، می‌توانید هر کارت را بر اساس ویژگی‌های منحصر به فرد آن استایل‌بندی کنید. اما می‌توانید با استفاده از ترکیب‌کننده and به همان روشی که برای کوئری‌های رسانه‌ای استفاده می‌شود، برای ترکیبات مشخصه (ویژگی سفارشی) نیز استایل‌بندی کنید. به عنوان مثال، روزی که هم ابری و هم آفتابی است، به صورت زیر خواهد بود:

@container style(--sunny: true) and style(--cloudy: true) {
    .weather-card {
      background: linear-gradient(24deg, pink, violet);
    }
  
  .weather-card:after {
      content: url(<data-uri-for-demo-brevity>);
      background: violet;
  }
}

جداسازی داده‌ها از طراحی

در هر دوی این دموها، یک مزیت ساختاری در جداسازی لایه داده (DOM که روی صفحه رندر می‌شود) از استایل‌های اعمال شده وجود دارد. استایل‌ها به صورت انواع مختلفی نوشته می‌شوند که درون استایل کامپوننت‌ها قرار دارند، در حالی که یک نقطه پایانی می‌تواند داده‌هایی را ارسال کند که سپس برای استایل‌بندی کامپوننت از آنها استفاده می‌کند. می‌توانید از یک مقدار واحد، مانند مورد اول، برای به‌روزرسانی مقدار --detail ، یا از چندین متغیر، مانند مورد دوم (تنظیم --rainy یا --cloudy یا --sunny استفاده کنید. و بهترین بخش این است که می‌توانید این مقادیر را نیز ترکیب کنید، بررسی وجود هر دو --sunny و --cloudy می‌تواند استایلی تا حدودی ابری را نشان دهد.

به‌روزرسانی مقادیر ویژگی‌های سفارشی از طریق جاوا اسکریپت می‌تواند به صورت یکپارچه انجام شود، چه هنگام تنظیم مدل DOM (یعنی هنگام ساخت کامپوننت در یک چارچوب)، و چه در هر زمانی با استفاده از <parentElem>.style.setProperty('--myProperty', <value>) به‌روزرسانی شود.

در اینجا یک نسخه آزمایشی وجود دارد که در چند خط کد، --theme یک دکمه را به‌روزرسانی می‌کند و با استفاده از کوئری‌های style و آن ویژگی سفارشی ( --theme ) استایل‌ها را اعمال می‌کند:

با استفاده از کوئری‌های استایل، کارت را استایل‌دهی کنید. جاوااسکریپتی که برای به‌روزرسانی مقادیر ویژگی‌های سفارشی استفاده می‌شود، به صورت زیر است:

const themePicker = document.querySelector('#theme-picker')
const btnParent = document.querySelector('.btn-section');

themePicker.addEventListener('input', (e) => {
  btnParent.style.setProperty('--theme', e.target.value);
})

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