در حال بارگذاری...

Feature Queries در CSS

کوئری کانتینر می‌پرسد عرض والد چقدر است. مدیا کوئری سراغ viewport می‌رود. Feature query سؤال دیگری دارد: این مرورگر اصلاً این CSS را می‌فهمد؟ با @supports یک پایهٔ مطمئن می‌گذارید، بعد فقط جایی که موتور قابلیت را دارد، لایهٔ مدرن را باز می‌کنید.

بهبود تدریجی، نه قمار

Feature query یک دروازهٔ قابلیت است. استایل قدیمی را پاک نمی‌کنید — چیدمانی نگه می‌دارید که همه‌جا کار کند، بعد داخل @supports لایهٔ غنی‌تر را اضافه می‌کنید وقتی موتور بتواند همان ویژگی را پارس کند (مثلاً display: grid یا gap روی فلکس).

شکل سادهٔ @supports

رایج‌ترین شکل، یک جفت ویژگی–مقدار را می‌آزماید. اگر مرورگر آن اعلان را بفهمد، قانون‌های داخل بلاک اعمال می‌شوند:

Unlock Grid only when Grid is understood

css
.card-list {
display: block;
}

.card-list .card {
margin-bottom: 1rem;
padding: 1rem;
border: 1px solid #e2e8f0;
border-radius: 0.75rem;
background: #fff;
}

@supports (display: grid) {
.card-list {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
gap: 1rem;
}

.card-list .card {
margin-bottom: 0;
}
}

بیرون بلاک، کارت‌ها با فاصلهٔ ساده روی هم می‌نشینند. داخل @supports (display: grid) همان فهرست گرید منعطف می‌شود — موتورهای قدیمی همان پشته را نگه می‌دارند؛ موتورهای جدید گرید می‌گیرند.

ترکیب شرط‌ها: and و or و not

می‌توانید چند قابلیت را با هم بخواهید، بین گزینه‌ها یکی را بپذیرید، یا شرط را برعکس کنید:

and, or, and not in feature queries

css
@supports (display: grid) and (gap: 1rem) {
.toolbar {
display: grid;
grid-auto-flow: column;
gap: 0.75rem;
align-items: center;
}
}

@supports (display: flex) or (display: grid) {
.cluster {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
}

@supports not (display: grid) {
.card-list .card {
max-width: 36rem;
}
}

and دروازه را تنگ می‌کند (هر دو باید پاس شوند). or بازترش می‌کند. not مسیر عدم پشتیبانی را استایل می‌دهد — برای فال‌بک عمدی به‌درد می‌خورد، به شرطی که آن فال‌بک واقعاً خوانا و کامل باشد.

سلکتور را با selector() بیازمایید

بعضی قابلیت‌ها سلکتورند، نه ویژگی. آن‌ها را داخل selector() بگذارید تا سؤال این باشد: «این سلکتور را بلدی پارس کنی؟»

Gate styles that need :has()

css
.nav a {
color: #0f172a;
text-decoration: none;
}

@supports selector(:has(*)) {
.nav:has(a:focus-visible) {
outline: 2px solid #2563eb;
outline-offset: 4px;
}

.card:has(img) .title {
font-weight: 700;
}
}

بدون selector()، گذاشتن خامِ :has() داخل @supports الگوی قابل‌اتکایی نیست. با آن، مرورگری که :has() ندارد فقط لایهٔ پیشرفته را رد می‌کند و استایل پایهٔ لینک‌ها می‌ماند.

هر ابزار کدام سؤال را می‌پرسد؟

📊 Media, container, and feature queries

سؤال شما ترجیح ابزار رایج
عرض viewport / زمینهٔ دستگاه چقدر است؟ پوستهٔ صفحه، بریک‌پوینت @media (…)
عرض همین والد دور کامپوننت چقدر است؟ کارت در جاهای نابرابر @container (…) بعد از container-type
آیا مرورگر این CSS را پشتیبانی می‌کند؟ بهبود تدریجی @supports (…) / selector(…)

این سه تا کنار هم خوب کار می‌کنند: مدیا برای صفحه، کانتینر برای جایگاه، @supports برای قابلیت. با @supports بریک‌پوینت جعلی نسازید و با @media قابلیت را چک نکنید.

اول پایه، بعد ارتقا

الگوی عملی این است که ظاهر مشترک بیرون دروازه بماند و چیدمان ارتقایافته داخلش بیاید:

Shared skin outside; enhanced layout inside

css
.feature-panel {
padding: 1.25rem;
border-radius: 0.75rem;
background: #f8fafc;
color: #0f172a;
}

.feature-panel .lead {
margin: 0 0 0.75rem;
font-size: 1.125rem;
line-height: 1.5;
}

.feature-panel .actions {
display: block;
}

.feature-panel .actions a {
display: inline-block;
margin: 0.25rem 0.5rem 0.25rem 0;
padding: 0.5rem 0.875rem;
border-radius: 0.5rem;
background: #e2e8f0;
color: inherit;
text-decoration: none;
}

@supports (display: flex) and (gap: 0.5rem) {
.feature-panel .actions {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}

.feature-panel .actions a {
margin: 0;
}
}

هر مرورگری پدینگ، تایپ و لینک قابل‌کلیک می‌گیرد. فلکس و gap فقط وقتی هر دو فهمیده شوند ظاهر می‌شوند — اگر یکی نباشد، صفحه سوراخ خالی نمی‌ماند.

Nesting کنار @supports

قطعه‌های Modern Toolkit با هم جمع می‌شوند. Nesting سلکتورها را مرتب می‌کند؛ دروازهٔ قابلیت هنوز مال @supports است:

Nesting inside a support block

css
.pricing {
padding: 1rem;
border: 1px solid #e2e8f0;
}

@supports (display: grid) {
.pricing {
display: grid;
gap: 1rem;

& .tier {
padding: 1rem;
background: #fff;
}

& .tier .price {
font-size: 1.5rem;
font-weight: 700;
}
}
}

اگر خود nesting پشتیبانی نشود، معادل تخت بیرون بگذارید یا بپذیرید شکل تو‌در‌تو بخشی از مسیر ارتقاست — همان ذهنیت بهبود تدریجی.

خودتان امتحان کنید

  1. فهرستی را ساده و ستونی استایل کنید؛ بعد چیدمان Grid را داخل @supports (display: grid) بپیچید.
  2. با and هم gap را بخواهید تا فاصلهٔ فلکس/گرید نصفه اعمال نشود.
  3. @supports not (display: grid) را با یک max-width واضح بنویسید — هر دو مسیر باید عمدی به نظر برسند.
  4. یک قانون :has() را با @supports selector(:has(*)) قفل کنید.
  5. همهٔ ظاهر بصری را داخل @supports نبرید؛ رنگ برند و تایپ را در پایه نگه دارید.

اشتباه‌های رایج

  • گذاشتن تنها چیدمان قابل‌استفاده داخل @supports بدون پایه — مرورگر بدون پشتیبانی صفحه را خراب می‌بیند
  • نوشتن @supports (display) بدون مقدار — feature query به جفت ویژگی–مقدار نیاز دارد (یا selector(…))
  • به‌جای @media از @supports استفاده کردن (یا برعکس) — قابلیت ≠ عرض viewport
  • آزمودن ویژگی‌ای که پایه از قبل به آن وابسته است — فقط ارتقا را دروازه کنید
  • پشته‌های تو‌در‌توی @supports برای بردهای کوچک — یک لایهٔ ارتقای روشن بهتر است

خلاصه

  • @supports CSS را بر اساس قابلیت مرورگر دروازه می‌کند (feature queries)
  • با (property: value) بیازمایید، با and / or / not ترکیب کنید، و برای سلکتور از selector() استفاده کنید
  • پایهٔ محکم بگذارید؛ وقتی پشتیبانی هست ارتقا دهید
  • سه‌تایی را یادتان بماند: @media → viewport، @container → اندازهٔ والد، @supports → قابلیت
  • Modern Toolkit اینجا تمام می‌شود — ماژول بعد: دسترس‌پذیری و جمع‌بندی (accessibility)

🧠 دانش خود را بیازمایید

آماده شروع

دانش خود را بیازمایید

خود را با این آزمون تعاملی به چالش بکشید و ببینید موضوع را چقدر خوب درک کرده‌اید

❓
6
سوالات
🎯
70%
برای قبولی
♾️
∞
زمان
🔄
∞
تلاش‌ها

📝 دستورالعمل‌ها

  • هر سوال را با دقت بخوانید
  • بهترین پاسخ را برای هر سوال انتخاب کنید
  • می‌توانید آزمون را هر چند بار که می‌خواهید تکرار کنید
  • پیشرفت شما در بالا نمایش داده می‌شود