ابزار اصلی طراحی واکنش‌گرا: Media Queries و قانون @media

در دو درس قبل، بارها از Media Query استفاده کردیم بدون این‌که کامل بازش کنیم. حالا وقتشه این ابزار محوری رو، که پایه اصلی پیاده‌سازی Breakpointها و رویکردهای Mobile First/Desktop First است، با تمام جزئیاتش ببینیم.

Media Query چیست؟

Media Query، یک قانون CSS‌ه که اجازه می‌ده، بر اساس ویژگی‌های محیط نمایش (مثل عرض صفحه‌نمایش، جهت‌گیری دستگاه، یا حتی تنظیمات کاربر)، مجموعه‌ای از Ruleها رو، فقط در شرایط خاص، فعال کنیم.

Syntax پایه

@media (min-width: 768px) {
  .container {
    display: flex;
  }
}

قانون @media، یک شرط داخل پرانتز می‌گیره (که در این مثال، min-width: 768px)، و همه Ruleهایی که داخل آکولادش می‌نویسیم، فقط وقتی این شرط برقرار باشه، فعال می‌شن؛ در این مثال، فقط وقتی عرض Viewport، حداقل ۷۶۸ پیکسل باشه.

min-width و max-width: دو ویژگی اصلی

@media (min-width: 768px) {
  /* فعال است وقتی عرض >= 768px */
}

@media (max-width: 767px) {
  /* فعال است وقتی عرض <= 767px */
}

همون‌طور که در درس قبل دیدیم، min-width شرط رو برای عرض‌های بزرگ‌تر یا مساوی با مقدار داده‌شده فعال می‌کنه (پایه Mobile First)؛ و max-width، برای عرض‌های کوچک‌تر یا مساوی (پایه Desktop First).

ترکیب دو شرط با and: تعریف یک بازه دقیق

@media (min-width: 768px) and (max-width: 1023px) {
  .container {
    background-color: lightyellow;
  }
}

با کلیدواژه and، می‌شه چند شرط رو هم‌زمان ترکیب کرد؛ در این مثال، این Rule فقط وقتی فعاله که عرض، دقیقاً بین ۷۶۸ و ۱۰۲۳ پیکسل باشه (یعنی معمولاً بازه تبلت).

ترکیب چند Media Query با کاما: شرط OR

@media (max-width: 480px), (min-width: 1600px) {
  .container {
    font-size: 14px;
  }
}

وقتی چند Media Query رو با کاما از هم جدا کنیم، این Rule فعال می‌شه اگه هرکدوم از این شرط‌ها برقرار باشن (نه لزوماً همه‌شون)؛ در این مثال، این استایل، هم روی موبایل‌های خیلی کوچک و هم روی مانیتورهای خیلی بزرگ، فعال می‌شه.

ویژگی orientation: جهت‌گیری دستگاه

@media (orientation: portrait) {
  .gallery {
    grid-template-columns: 1fr;
  }
}

@media (orientation: landscape) {
  .gallery {
    grid-template-columns: repeat(2, 1fr);
  }
}

ویژگی orientation، مشخص می‌کنه صفحه‌نمایش، در حالت عمودی (portrait؛ ارتفاع بیشتر از عرض) است یا افقی (landscape؛ عرض بیشتر از ارتفاع). این ویژگی، مخصوصاً برای تبلت‌ها و موبایل‌هایی که کاربر می‌تونه بچرخوندشون، کاربرد داره.

prefers-color-scheme: تنظیمات تم روشن/تاریک کاربر

body {
  background-color: white;
  color: black;
}

@media (prefers-color-scheme: dark) {
  body {
    background-color: #121212;
    color: #eeeeee;
  }
}

یکی از کاربردهای مدرن Media Query، تشخیص تنظیمات سیستم‌عامل یا مرورگر کاربره؛ prefers-color-scheme، مشخص می‌کنه آیا کاربر، حالت تاریک (Dark Mode) رو ترجیح می‌ده یا نه. این Property، بخشی از دسته بزرگ‌تری از Media Queryهای مربوط به Accessibility و ترجیحات کاربره که به‌طور کامل در فصل CSS برای Accessibility بررسیش می‌کنیم.

prefers-reduced-motion: کاهش انیمیشن برای کاربران حساس

.box {
  transition: transform 0.3s;
}

@media (prefers-reduced-motion: reduce) {
  .box {
    transition: none;
  }
}

این Media Query، تشخیص می‌ده آیا کاربر، در تنظیمات سیستم‌عامل خودش، درخواست کاهش حرکت و انیمیشن‌ها رو داده یا نه؛ که این موضوع رو هم، با جزئیات کامل، در فصل Accessibility بررسی می‌کنیم.

محل قرارگیری @media در فایل CSS

.card {
  padding: 16px;
}

@media (min-width: 768px) {
  .card {
    padding: 32px;
  }
}

یه نکته مهم که مستقیماً به فصل ۲ (Cascade و Source Order) برمی‌گرده: قانون @media، Specificity هیچ Selectorای رو تغییر نمی‌ده؛ فقط مشخص می‌کنه اون Ruleها، در چه شرایطی، اصلاً وارد محاسبه Cascade بشن یا نه. به همین دلیل، اگه دو Rule با Specificity برابر، هم داخل و هم خارج یک Media Query تعریف بشن، ترتیب نوشتن‌شون (Source Order) هنوز هم مهمه؛ برای همین، در Mobile First، معمولاً Media Queryهای min-width رو، به‌ترتیب از کوچک به بزرگ، پشت‌سرهم می‌نویسیم.

یک مثال کامل: سه Breakpoint در کنار هم

.nav {
  display: flex;
  flex-direction: column;
}

@media (min-width: 600px) {
  .nav {
    flex-direction: row;
    justify-content: space-between;
  }
}

@media (min-width: 1200px) {
  .nav {
    padding-inline: 40px;
  }
}

در این مثال، منطق کاملاً Mobile Firste: استایل پایه، برای موبایل (ستونی)؛ از ۶۰۰ پیکسل به بعد، به یک ردیف افقی تبدیل می‌شه؛ و از ۱۲۰۰ پیکسل به بعد، فقط یک فاصله اضافه‌تر در کنارها اضافه می‌شه؛ بدون این‌که چیزی از تنظیمات قبلی نیاز به Reset داشته باشه.

نکات مهم

  • min-width شرط را برای عرض‌های بزرگ‌تر یا مساوی فعال می‌کند؛ max-width برای عرض‌های کوچک‌تر یا مساوی.
  • ترکیب چند شرط با and، یک بازه دقیق تعریف می‌کند؛ جدا کردن چند Media Query با کاما، به‌معنای شرط OR است.
  • علاوه بر عرض صفحه، Media Query می‌تواند جهت‌گیری دستگاه، تم روشن/تاریک، یا ترجیح کاهش حرکت کاربر را هم تشخیص دهد.

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

  • قاطی کردن ترکیب and (شرط لازم بودن هر دو) با کاما (شرط کافی بودن یکی)، که می‌تواند رفتار کاملاً متفاوتی ایجاد کند.
  • نوشتن Media Queryها به‌ترتیب نامنظم (نه از کوچک به بزرگ در Mobile First)، که می‌تواند به‌خاطر Source Order، رفتار غیرمنتظره ایجاد کند.
  • فراموش کردن این‌که Media Query، Specificity را تغییر نمی‌دهد؛ فقط شرط فعال‌سازی را کنترل می‌کند.

جمع‌بندی

قانون @media، ابزار اصلی پیاده‌سازی طراحی واکنش‌گراست و اجازه می‌دهد مجموعه‌ای از Ruleها، بر اساس شرایط محیط نمایش (عرض صفحه، جهت‌گیری، یا حتی ترجیحات کاربر مثل تم تاریک)، فقط در شرایط خاص فعال شوند. min-width و max-width، پایه اصلی Mobile First و Desktop First هستند، و ترکیب چند شرط با and یا کاما، امکان تعریف بازه‌های دقیق یا شرط‌های چندگانه را فراهم می‌کند.