مدیا کوئری در طراحی ریسپانسیو چگونه کار میکند؟
چرا Media Queries بدون Mobile-First و طراحی سیال، شکست میخورند؟ تحلیل عمیق مکانیزم پردازش Media Query در مرورگر از Parse تا Match، Range Syntax، Container Queries، Feature Queries، prefers-* و استراتژی Breakpoint برای تیمهای مهندسی مقیاس بزرگ.
در بازبینی یک پلتفرم SaaS که در ۲۰۲۵ با تیم سینفرهای از مهندسان فرانتاند انجام دادم، به موردی برخوردم که بهروشنی نشان میداد چرا مدیا کوئری (Media Query) همچنان یکی از کمفهمشدهترین حوزههای CSS مدرن است. تیم ادعا میکرد رابط کاملاً ریسپانسیو است، چون در تمام عرضهای ممکن DevTools کروم، صفحه «بههم نمیریخت». اما وقتی فایل CSS را باز کردم، با فاجعهای روبهرو شدم: بیش از ۴۰ مدیاکوئری با max-width، پراکنده در سراسر فایل، بدون هیچ ساختار منطقی. سه مدیاکوئری همپوشان برای بازه ۷۶۸ تا ۱۰۲۴ پیکسل وجود داشت که قواعد یکدیگر را بازنویسی میکردند. یک مدیاکوئری در انتهای فایل با یک مدیاکوئری در ابتدای فایل به یک عنصر یکسان استایل میداد، و برنده بهطور تصادفی تعیین میشد — بسته به ترتیب بارگذاری. این پرونده، هستهایترین درس من در حوزه Media Queries را خلاصه میکند: مدیا کوئری، یک ابزار شرطی است، اما اگر ساختار مشخصی نداشته باشد، خودش به منبع شکنندگی تبدیل میشود.
بر اساس دادههای Web Almanac ۲۰۲۴، میانگین تعداد مدیاکوئریها در CSS سایتهای بررسیشده حدود ۲۸ است، اما در سایتهای پیچیده این عدد به بیش از ۱۰۰ میرسد. بر اساس دادههای HTTP Archive، حدود ۷۸٪ از سایتها از Media Queries استفاده میکنند، اما تنها ۴۲٪ از آنها از رویکرد Mobile-First پیروی میکنند. بر اساس دادههای Google CrUX Report ۲۰۲۴، سایتهای با Core Web Vitals در دسته Good، ۲۴٪ نرخ تبدیل بالاتری دارند، و یکی از عوامل تعیینکننده این معیارها، پیادهسازی صحیح Media Queries است. در این تحلیل مهندسی، همان چارچوبی را میکاوم که در پروژههای واقعی برای طراحی و بازبینی Media Queries به کار میبرم.
زمینه: چرا Media Queries همچنان اشتباه استفاده میشود؟
Media Query یک قابلیت CSS است که بهظاهر ساده بهنظر میرسد: اگر شرطی درست باشد، قواعد درون آن اجرا میشوند. اما در عمل، همین سادگی، منبع اصلی خطاهای ریسپانسیو است. چهار دلیل اصلی این چالش را در پروژههای واقعی دیدهام.
دلیل اول، عدم درک مکانیزم Match: بسیاری از توسعهدهندگان نمیدانند که مدیاکوئریها در کدام مرحله از چرخه رندر ارزیابی میشوند، و چرا ترتیب مدیاکوئریها مهم است. دلیل دوم، استفاده از Desktop-First بهجای Mobile-First: نوشتن مدیاکوئریهای max-width برای موبایل، منجر به کد اضافی و شکننده میشود. دلیل سوم، استفاده نادرست از ترتیب مدیاکوئریها: در CSS، ترتیب تعیینکننده است — مدیاکوئری که بعد از دیگری میآید، در صورت تعارض، برنده میشود. دلیل چهارم، نبود ساختار منطقی: استفاده از دهها مدیاکوئری بدون ساختار مشخص، منجر به کد غیرقابل نگهداری میشود.
برای فهم بهتر این چالشها، ابتدا باید مکانیزم دقیق Media Query را بشناسیم. اگر با اصول پایه طراحی ریسپانسیو آشنا نیستید، طراحی ریسپانسیو چیست و چرا برای وب مدرن ضروری است و اصول طراحی ریسپانسیو کدامند دو نقطه شروع مناسب هستند.
Media Query ابزار شرطی است، اما ساختار پشت آن است که تعیین میکند کد شما پایدار میماند یا شکننده. تفاوت این دو، تفاوت کدی است که سالها کار میکند و کدی که در هر تغییر قالب، دوباره باید بازنویسی شود.
Media Query دقیقاً چیست؟
Media Query (به فارسی: پرسوجوی رسانه یا کوئری رسانه) یک قابلیت CSS است که به شما اجازه میدهد قواعد CSS را بر اساس شرایط محیطی کاربر اعمال کنید. این شرایط میتواند عرض viewport، ارتفاع، جهتگیری دستگاه، ترجیح کاربر برای رنگ تیره، یا توانایی hover باشد. Media Query در سال ۲۰۱۰ توسط Ethan Marcotte بهعنوان یکی از سه ستون طراحی ریسپانسیو معرفی شد و امروز یکی از پرکاربردترین ویژگیهای CSS مدرن است.
برای درک تعریف دقیق، Media queries در ویکیپدیا مرجع جامعی است. Media Query از سه جزء اصلی تشکیل شده است:
جزء اول: مدیا تایپ (Media Type)
مدیا تایپ تعیین میکند که قواعد CSS بر روی کدام نوع دستگاه اعمال شود. چهار مقدار اصلی:
- all: همه دستگاهها (پیشفرض).
- screen: صفحه نمایش (دسکتاپ، موبایل، تبلت).
- print: چاپگر.
- speech: صفحهخوان (Screen Reader).
در عمل، امروز تقریباً همیشه از all یا screen استفاده میشود، چون print بهطور خودکار از طریق @media print قابل هدفگیری است.
جزء دوم: مدیا فیچر (Media Feature)
مدیا فیچرها شرایط محیطی را توصیف میکنند. مهمترین مدیا فیچرها:
| ویژگی | توضیح | کاربرد |
|---|---|---|
| width / min-width / max-width | عرض viewport | Breakpointهای اصلی |
| height / min-height / max-height | ارتفاع viewport | Layoutهای Full-Screen |
| orientation | Portrait یا Landscape | تبلت و موبایل چرخیده |
| aspect-ratio | نسبت عرض به ارتفاع | Layoutهای خاص |
| resolution | چگالی پیکسل | Retina و HDPI |
| hover | توانایی Hover | تفکیک Touch و Mouse |
| pointer | دقت دستگاه اشاره | Coarse و Fine |
| prefers-color-scheme | ترجیح رنگ روشن/تیره | Dark Mode |
| prefers-reduced-motion | ترجیح کاهش حرکت | Accessibility |
| prefers-contrast | ترجیح کنتراست بالا | Accessibility |
| color-gamut | گام رنگی نمایشگر | Wide Gamut (P3) |
جزء سوم: عملگرها (Operators)
سه عملگر اصلی در Media Query:
- and: ترکیب منطقی AND. مثال:
(min-width: 640px) and (max-width: 1024px). - or: ترکیب منطقی OR. مثال:
(min-width: 640px) or (orientation: landscape). - not: نفی. مثال:
not (min-width: 640px).
مکانیزم Syntax و Parse در CSS
Media Query در CSS یک ساختار مشخص دارد که باید درست پیاده شود. سه سطح Syntax:
سطح اول: Syntax ساده
@media (min-width: 768px) {
.container {
max-width: 720px;
}
}
این سادهترین شکل Media Query است: اگر عرض viewport حداقل ۷۶۸ پیکسل باشد، قواعد درون آن اعمال میشوند.
سطح دوم: Syntax ترکیبی
@media (min-width: 768px) and (max-width: 1024px) {
.container {
max-width: 720px;
}
}
این Syntax، Media Query را به یک بازه مشخص محدود میکند. نکته کلیدی: در این مثال، اگر عرض viewport بین ۷۶۸ و ۱۰۲۴ پیکسل باشد، قواعد اعمال میشوند.
سطح سوم: Syntax تکی
@media (hover: hover) {
.button:hover {
background-color: var(--color-hover);
}
}
در این Syntax، هیچ مقدار مقایسهای وجود ندارد — فقط وجود یا عدم وجود ویژگی چک میشود.
نکات Parse مهم
در فرآیند Parse CSS، مرورگر Syntax Media Query را بر اساس Grammar مشخص ارزیابی میکند. اگر Syntax اشتباه باشد، کل Media Query نادیده گرفته میشود. سه اشتباه تکراری:
- فاصله اضافی در پرانتز:
( min-width: 768px )ممکن است نادیده گرفته شود. صحیح:(min-width: 768px). - استفاده از کاما بهجای and:
(min-width: 768px), (max-width: 1024px)معادل OR است، نه AND. - عدم تطابق واحد:
(min-width: 768)بدون واحد، نامعتبر است. صحیح:(min-width: 768px).
مکانیزم Match در مرورگر
برای درک عمیق Media Query، باید بدانید که مرورگر در کدام مرحله آن را ارزیابی میکند. چرخه رندر مرورگر شامل چهار مرحله است: Parse HTML و CSS، Build DOM و CSSOM، Layout، و Paint. Media Query در مرحله Parse ارزیابی میشود — یعنی قبل از Build CSSOM.
این یعنی چه؟ یعنی وقتی مرورگر فایل CSS شما را میخواند، برای هر Media Query یک Boolean Match انجام میدهد و اگر شرایط برقرار نبود، قواعد درون آن را نادیده میگیرد. به همین دلیل، Media Query بر Performance اثر منفی ندارد — قواعدی که Match نمیشوند، در CSSOM ذخیره نمیشوند.
ترتیب اعمال Media Queries
در CSS، ترتیب مدیاکوئریها تعیینکننده است. قاعده کلی: در صورت تعارض، مدیاکوئری که در فایل دیرتر ظاهر شود، برنده است — مستقل از Specificity. این قاعده بهدلیل Cascade است که ترتیب را مهمتر از Specificity میداند.
.button {
background-color: blue;
}
@media (min-width: 768px) {
.button {
background-color: green;
}
}
@media (min-width: 1024px) {
.button {
background-color: red;
}
}
در این مثال، در عرض ۱۲۰۰ پیکسل، هر سه قاعده Match میشوند و رنگ نهایی قرمز است — چون مدیاکوئری سوم دیرتر ظاهر شده.
Specificity و Media Query
نکته کلیدی: Media Query بر Specificity اثر ندارد. اگر دو قاعده با Specificity یکسان در Media Queries مختلف باشند، ترتیب تعیینکننده است. اگر یک قاعده با Specificity بالاتر در Media Query اول و یک قاعده با Specificity پایینتر در Media Query دوم باشد، Specificity برنده است — نه ترتیب.
@media (min-width: 768px) {
#header .button {
background-color: green;
}
}
@media (min-width: 1024px) {
.button {
background-color: red;
}
}
در این مثال، در عرض ۱۲۰۰ پیکسل، هر دو Match میشوند اما #header .button با Specificity بالاتر، برنده است.
Range Syntax و Media Queries Level 4
یکی از پیشرفتهای مهم در CSS Media Queries Level 4، معرفی Range Syntax است که خواناتر و کمتر مستعد خطاست:
/* روش کلاسیک */
@media (min-width: 640px) and (max-width: 1024px) { }
/* روش جدید (Range Syntax) */
@media (640px <= width <= 1024px) { }
/* Range Syntax برای بازه باز */
@media (width >= 640px) { }
@media (width < 1024px) { }
مزایای Range Syntax:
- خوانایی بالاتر: یک بازه بهجای ترکیب دو شرط.
- کمتر مستعد خطا: امکان ندارد ترتیب min و max را اشتباه بنویسید.
- پشتیبانی مرورگرها: Chrome 104+، Safari 16.4+، Firefox 102+.
اگر با طراحی ریسپانسیو آشنا نیستید، اصول طراحی ریسپانسیو کدامند راهنمای جامعی است. همچنین طراحی ریسپانسیو چیست و چرا برای وب مدرن ضروری است برای درک چارچوب کلی مفید است.
Feature Queries و prefers-*
Media Queries مدرن شامل مجموعهای از Feature Queries هستند که برای تطبیق با ترجیحات کاربر طراحی شدهاند. مهمترین این Feature Queries:
prefers-color-scheme
:root {
--bg: #ffffff;
--text: #1a1a1a;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #121212;
--text: #e0e0e0;
}
}
این Media Query، ترجیح کاربر برای رنگ روشن یا تیره را تشخیص میدهد. بر اساس دادههای Google، حدود ۸۰٪ کاربران Android از Dark Mode سیستم استفاده میکنند. اگر با Dark Mode آشنا نیستید، حالت تاریک و بهترین رویههای آن راهنمای جامعی است.
prefers-reduced-motion
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
این Media Query، ترجیح کاربر برای کاهش حرکت را تشخیص میدهد. این ترجیح، هم برای کاربران با حساسیت به حرکت (Motion Sensitivity) و هم برای کاربران با Vestibular Disorders (اختلالات تعادلی) حیاتی است. اگر با دسترسپذیری آشنا نیستید، WCAG چیست و چه کاربردی دارد راهنمای جامعی است.
prefers-contrast
@media (prefers-contrast: more) {
:root {
--color-text-primary: #000000;
--color-bg-primary: #ffffff;
--color-border: #000000;
}
}
این Media Query، ترجیح کاربر برای کنتراست بالا را تشخیص میدهد. بر اساس دادههای WCAG 2.2، کاربران با ناتوانی بینایی، اغلب این تنظیمات را فعال میکنند.
prefers-reduced-data
@media (prefers-reduced-data: reduce) {
.hero-image {
display: none;
}
.hero {
background: var(--color-bg-secondary);
}
}
این Media Query، ترجیح کاربر برای مصرف کمتر داده را تشخیص میدهد. اگرچه پشتیبانی مرورگرها محدود است، اما میتواند در آیندهای نزدیک ارزشمند باشد.
hover و pointer
@media (hover: hover) and (pointer: fine) {
.dropdown:hover .menu {
display: block;
}
}
@media (hover: none) or (pointer: coarse) {
.dropdown:focus-within .menu {
display: block;
}
}
این Media Queries، توانایی hover و دقت دستگاه اشاره را تشخیص میدهند. تفکیک بین دستگاههای hover-محور (دسکتاپ) و touch-محور (موبایل و تبلت) یکی از مهمترین اصول طراحی ریسپانسیو مدرن است.
| Media Query | معنی | کاربرد اصلی |
|---|---|---|
| prefers-color-scheme | ترجیح رنگ | Dark Mode |
| prefers-reduced-motion | ترجیح کاهش حرکت | Accessibility |
| prefers-contrast | ترجیح کنتراست بالا | Accessibility |
| prefers-reduced-data | ترجیح داده کمتر | Optimization |
| hover: hover/none | توانایی Hover | Touch vs Mouse |
| pointer: fine/coarse | دقت اشارهگر | Target Size |
| orientation | Portrait یا Landscape | Tablet Layout |
| color-gamut | گام رنگی | Wide Gamut (P3) |
| any-hover / any-pointer | وجود حداقل یک دستگاه اشاره | Hybrid Devices |
Mobile-First و استراتژی Breakpoint
یکی از مهمترین تصمیمها در استفاده از Media Queries، انتخاب استراتژی Mobile-First یا Desktop-First است. تفاوت در نوع Media Query مورد استفاده:
Mobile-First: min-width
/* Mobile styles first */
.container {
padding: 1rem;
grid-template-columns: 1fr;
}
/* Tablet (min-width) */
@media (min-width: 768px) {
.container {
padding: 2rem;
grid-template-columns: repeat(2, 1fr);
}
}
/* Desktop */
@media (min-width: 1024px) {
.container {
max-width: 1200px;
margin-inline: auto;
grid-template-columns: repeat(3, 1fr);
}
}
در Mobile-First، ابتدا استایلهای موبایل نوشته میشود (بدون Media Query)، سپس استایلهای بزرگتر با min-width اضافه میشوند.
Desktop-First: max-width
/* Desktop styles first */
.container {
max-width: 1200px;
margin-inline: auto;
padding: 2rem;
grid-template-columns: repeat(3, 1fr);
}
@media (max-width: 1023px) {
.container {
grid-template-columns: repeat(2, 1fr);
}
}
@media (max-width: 767px) {
.container {
padding: 1rem;
grid-template-columns: 1fr;
}
}
در Desktop-First، ابتدا استایلهای دسکتاپ نوشته میشود، سپس استایلهای کوچکتر با max-width اضافه میشوند.
مقایسه دو رویکرد
| معیار | Mobile-First | Desktop-First |
|---|---|---|
| Media Query | min-width | max-width |
| اولویت محتوا | محتوا محور | Layout محور |
| حجم CSS در موبایل | کم | زیاد |
| سازگاری با Mobile-First Indexing | بله | نسبی |
| پیچیدگی نگهداری | کم | زیاد |
| پشتیبانی تیمهای قدیمی | نیاز به آموزش | سادهتر |
توصیه من در پروژههای واقعی: همیشه Mobile-First. دلایل: اول، سازگاری با Mobile-First Indexing گوگل. دوم، اجبار به اولویتبندی محتوا. سوم، حجم کمتر CSS در موبایل. اگر با Mobile-First آشنا نیستید، طراحی موبایل اول چیست و چه مزایایی دارد راهنمای جامعی است.
استراتژی Breakpoint
انتخاب تعداد و مقادیر Breakpointها یکی از تصمیمهای کلیدی است. توصیه من:
- شروع با ۴ Breakpoint: ۴۸۰، ۷۶۸، ۱۰۲۴، ۱۲۸۰.
- Content-Based، نه Device-Based: Breakpoint باید جایی باشد که چیدمان میشکند، نه جایی که یک دستگاه معروف است.
- استفاده از Range Syntax: برای بازههای مشخص.
- کاهش تعداد: با استفاده از طراحی سیال (clamp، min، max)، تعداد Breakpointها کاهش مییابد.
- مستندسازی: هر Breakpoint باید دلیل مشخص داشته باشد.
طراحی سیال در برابر Media Query گسسته
یکی از پیشرفتهای مهم در CSS مدرن، امکان طراحی سیال (Fluid) بهجای Media Queries گسسته است. تفاوت:
رویکرد گسسته (Discrete)
h1 {
font-size: 24px;
}
@media (min-width: 768px) {
h1 {
font-size: 32px;
}
}
@media (min-width: 1024px) {
h1 {
font-size: 40px;
}
}
در این رویکرد، فونت در هر Breakpoint بهطور ناگهانی تغییر میکند. نتیجه: پرشهای بصری در انتقال بین Breakpointها.
رویکرد سیال (Fluid)
h1 {
font-size: clamp(1.5rem, 1rem + 3vw, 2.5rem);
}
در این رویکرد، فونت بهطور پیوسته با عرض viewport تغییر میکند. نتیجه: انتقال نرم بین عرضها، بدون نیاز به Media Query.
ترکیب دو رویکرد
توصیه عملی من: از طراحی سیال برای اندازهها و فاصلهها استفاده کنید، و از Media Queries فقط برای تغییرات ساختاری (مانند تغییر تعداد ستونها یا پنهان کردن عناصر) استفاده کنید.
.card-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
gap: clamp(1rem, 2vw, 2rem);
}
/* Media Query فقط برای تغییرات ساختاری */
@media (min-width: 1024px) {
.sidebar {
display: block;
}
}
این رویکرد، حجم CSS را کاهش میدهد و پایداری را افزایش میدهد. اگر با اصول طراحی ریسپانسیو آشنا نیستید، اصول طراحی ریسپانسیو کدامند راهنمای جامعی است. همچنین مدیا کوئری در CSS نکات دقیقی ارائه میدهد.
Container Queries و مرز بعدی
Container Queries یکی از مهمترین پیشرفتهای CSS در سالهای اخیر است که محدودیت بزرگ Media Queries را حل میکند. تفاوت کلیدی: Media Queries بر اساس عرض viewport تصمیم میگیرد؛ Container Queries بر اساس عرض container.
مشکل Media Queries در طراحی کامپوننتمحور
تصور کنید یک کامپوننت کارت دارید که در سایدبار (عرض ۳۰۰ پیکسل) و در محتوای اصلی (عرض ۸۰۰ پیکسل) قرار میگیرد. با Media Queries، در عرض viewport ۱۲۰۰ پیکسل، هر دو کارت بهعنوان دسکتاپ رندر میشوند. اما کارت در سایدبار باید چیدمان موبایل داشته باشد چون عرضش کم است، در حالی که کارت در محتوا باید چیدمان دسکتاپ داشته باشد.
Container Queries در عمل
.card-container {
container-type: inline-size;
container-name: card;
}
.card {
display: flex;
flex-direction: column;
gap: 1rem;
}
@container card (min-width: 400px) {
.card {
flex-direction: row;
align-items: center;
}
}
@container card (min-width: 700px) {
.card {
padding: 2rem;
}
.card .image {
width: 200px;
}
}
Container Queries در ۲۰۲۲ به بلوغ رسید و در ۲۰۲۶ بهطور گسترده پشتیبانی میشود. این ویژگی، ریسپانسیو را از سطح صفحه به سطح کامپوننت منتقل میکند — یک تغییر معماری قابل توجه.
Container Query Units
.card-title {
font-size: clamp(1rem, 5cqi, 2rem);
}
در این مثال، cqi به معنای Container Query Inline Size است. این واحدها به شما اجازه میدهند اندازهها را بر اساس عرض container تنظیم کنید، نه عرض viewport.
اگر با Container Queries آشنا نیستید، اصول طراحی ریسپانسیو کدامند راهنمای جامعی است. همچنین مدیا کوئری و اصول ریسپانسیو نکات عملی ارائه میدهد.
Media Queries در RTL
برای سایتهای فارسی، Media Queries چالشهای اختصاصی دارد. سه نکته کلیدی:
نکته اول: CSS Logical Properties
Media Queries بهطور مستقیم با RTL کار میکنند، اما درون آنها باید از CSS Logical Properties استفاده کنید تا چیدمان بهطور خودکار آینه شود:
@media (min-width: 768px) {
.card {
padding-inline-start: 2rem;
margin-inline-end: 1rem;
}
}
در این مثال، padding-inline-start در LTR چپ و در RTL راست است. اگر از padding-left استفاده کنید، در RTL اشتباه میشود.
نکته دوم: تست در RTL
تست Media Queries در RTL باید جداگانه انجام شود چون ممکن است رفتار در LTR و RTL متفاوت باشد. توصیه من: در CI/CD، تستهای Visual Regression را هم در LTR و هم در RTL اجرا کنید.
نکته سوم: تایپوگرافی فارسی و Breakpoint
فونتهای فارسی بهطور کلی به فضای بیشتری نیاز دارند. این یعنی Breakpointهای شما ممکن است در RTL کوچکتر باشند — یعنی در عرضی که در LTR سه ستون جای میگیرد، در RTL فقط دو ستون. توصیه: Breakpointها را در RTL جداگانه تست کنید.
اگر با RTL آشنا نیستید، آمادهسازی قالب وردپرس برای فارسی و تفاوت قالب فارسی و انگلیسی دو مقاله جامع هستند.
عملکرد و ترتیب بارگذاری
یکی از نگرانیهای رایج درباره Media Queries، تأثیر آن بر عملکرد است. پاسخ کوتاه: Media Queries بر عملکرد اثر منفی ندارد، اگر درست استفاده شود.
مکانیزم Performance
Media Query در مرحله Parse CSS ارزیابی میشود، قبل از Build CSSOM. اگر شرایط Match نباشد، قواعد درون Media Query در CSSOM ذخیره نمیشود. نتیجه: هیچ هزینه Performance اضافی ندارد.
ترتیب بارگذاری فایلهای CSS
یکی از اشتباهات رایج، استفاده از @import برای بارگذاری فایلهای Media Query جداگانه است:
/* اشتباه */
@import url("mobile.css") screen and (max-width: 768px);
@import url("desktop.css") screen and (min-width: 769px);
این رویکرد در کنار پردازش سریع، یک سریال آبشاری ایجاد میکند که منجر به تأخیر بارگذاری میشود. راهحل: استفاده از تگ <link> با Attribute media:
<link rel="stylesheet" href="mobile.css" media="screen and (max-width: 768px)">
<link rel="stylesheet" href="desktop.css" media="screen and (min-width: 769px)">
با این رویکرد، مرورگر Media Query را در ابتدای بارگذاری ارزیابی میکند و اگر Match نباشد، فایل را دانلود نمیکند. نتیجه: کاهش قابل توجه حجم بارگذاری.
Critical CSS و Media Queries
<style>
/* Critical CSS */
@media (max-width: 768px) {
.header { display: none; }
}
</style>
<link rel="stylesheet" href="non-critical.css" media="print" onload="this.media='all'">
این تکنیک، Critical CSS را درون HTML قرار میدهد و CSS غیرحیاتی را با تأخیر بارگذاری میکند. نتیجه: LCP سریعتر. اگر با Core Web Vitals آشنا نیستید، Core Web Vitals چیست و چرا گوگل بر آن تاکید دارد راهنمای جامعی است.
تست Media Queries در مرورگر
تست Media Queries بخشی جداییناپذیر از فرآیند توسعه است. سه سطح تست:
سطح اول: Chrome DevTools Device Mode
Chrome DevTools Device Mode، ابزار اصلی برای تست Media Queries در مرورگر است. نکات کلیدی:
- Responsive Mode: امکان تنظیم عرض و ارتفاع بهطور دستی.
- Device Presets: پیشتنظیمهای آماده برای دستگاههای معروف.
- Media Query Inspector: نمایش Breakpointهای Media Queries در نوار بالای Device Mode.
- Network Throttling: شبیهسازی شبکه کند.
سطح دوم: تست روی دستگاههای واقعی
شبیهساز DevTools محدودیتهای جدی دارد: عملکرد را دقیق شبیهسازی نمیکند، رفتار واقعی لمس را نشان نمیدهد، و کیبورد مجازی واقعی را نمایش نمیدهد. توصیه من: حداقل سه دستگاه واقعی — iPhone، Android میانرده، Android قدیمی.
سطح سوم: تست خودکار در CI/CD
# مثال با Playwright
const viewports = [
{ width: 320, height: 568 },
{ width: 375, height: 667 },
{ width: 768, height: 1024 },
{ width: 1024, height: 768 },
{ width: 1440, height: 900 }
];
for (const viewport of viewports) {
await page.setViewportSize(viewport);
await page.goto('https://example.com');
await expect(page).toHaveScreenshot(`home-${viewport.width}.png`);
}
این کد، Visual Regression Testing را در پنج viewport مختلف اجرا میکند. اگر تغییری در Media Queries منجر به تغییر بصری شود، CI آن را کشف میکند.
ابزارهای تست Media Queries
- Chrome DevTools: Device Mode و Media Query Inspector.
- Firefox Responsive Design Mode: ابزار مشابه در Firefox.
- Responsively App: مشاهده همزمان سایت در چند device.
- BrowserStack و Sauce Labs: تست روی دستگاههای واقعی از راه دور.
- Playwright و Cypress: Visual Regression در چند viewport.
- Lighthouse: برای تست Reflow و Responsive.
اگر با تست ریسپانسیو آشنا نیستید، تست ریسپانسیو در مرورگرها و ابزارهای تست ریسپانسیو دو مقاله جامع هستند.
الگوهای ضد در استفاده از Media Queries
در بازبینی پروژههای مختلف، الگوهای ضد تکراری دیدهام که استفاده از Media Queries را مختل میکنند:
- استفاده از max-width بهعنوان رویکرد پیشفرض: منجر به Desktop-First و حجم CSS بالا میشود.
- عدم ترتیب منطقی: مدیاکوئریها با ترتیب تصادفی، منجر به بازنویسیهای غیرمنتظره میشوند.
- Overlap در بازهها: استفاده همزمان از min-width و max-width در بازههای همپوشان.
- استفاده از @import برای Media Queries: منجر به تأخیر بارگذاری و بار اضافه میشود.
- نادیدهگرفتن Range Syntax: استفاده از روش کلاسیک در حالی که Range Syntax خواناتر و کمخطاتر است.
- Breakpoints زیاد: استفاده از دهها Breakpoint بدون ساختار مشخص.
- Device-Based Breakpoints: تعریف Breakpoint بر اساس دستگاه معروف، نه محتوا.
- نادیدهگرفتن prefers-* Queries: عدم تطبیق با ترجیحات کاربر (Dark Mode، Reduced Motion).
- نبود تست در RTL: فرض اینکه Media Queries در RTL هم یکسان کار میکند.
- استفاده از Media Query برای همه چیز: در حالی که طراحی سیال (clamp، min، max) در بسیاری موارد جایگزین بهتری است.
- نادیدهگرفتن Container Queries: استفاده از Media Queries در کامپوننتهای قابل استفاده مجدد.
- Missing Reflow در ۳۲۰px: عدم تست در حداقل عرض مورد نیاز WCAG 2.2.
اگر با اشتباهات رایج طراحی آشنا نیستید، اشتباهات رایج در طراحی وبسایت و اشتباهات رایج در طراحی ریسپانسیو دو مقاله جامع هستند.
Media Query، ابزار شرطی است، اما ساختار پشت آن است که تعیین میکند کد شما پایدار میماند یا شکننده. تفاوت این دو، تفاوت کدی است که سالها کار میکند و کدی که در هر تغییر قالب، بازنویسی میشود.
پرسشهای پرتکرار درباره Media Queries
تفاوت Media Query و Media Feature چیست؟ Media Query ساختار کلی است که شامل Media Type، Media Feature و عملگرها میشود. Media Feature یک ویژگی مشخص است — مانند width، orientation، prefers-color-scheme. Media Query میتواند یک یا چند Media Feature داشته باشد.
آیا Media Queries بر سرعت سایت اثر منفی دارند؟ نه، اگر بهدرستی استفاده شوند. Media Queries در مرحله Parse CSS ارزیابی میشوند و اگر شرایط Match نباشد، قواعد درون آنها در CSSOM ذخیره نمیشود. تنها استثنا، استفاده از @import است که منجر به تأخیر بارگذاری میشود.
Mobile-First یا Desktop-First؟ Mobile-First. دلایل: اول، سازگاری با Mobile-First Indexing گوگل. دوم، اجبار به اولویتبندی محتوا. سوم، حجم کمتر CSS در موبایل. تنها در موارد خاص — مانند پلتفرمهای سازمانی با کاربران اصلی دسکتاپ — Desktop-First منطقی است.
چند Breakpoint مناسب است؟ پاسخ استاندارد «هر تعداد که محتوا نیاز دارد» است. توصیه من: شروع با ۴ Breakpoint (۴۸۰، ۷۶۸، ۱۰۲۴، ۱۲۸۰) و افزودن Breakpointهای اضافی بر اساس محتوا. با استفاده از طراحی سیال (clamp، min، max)، تعداد Breakpointها کاهش مییابد.
آیا Media Queries بر Specificity اثر دارند؟ نه. Media Queries بر Specificity اثر ندارند. اگر دو قاعده با Specificity یکسان در Media Queries مختلف باشند، ترتیب تعیینکننده است. اگر یک قاعده با Specificity بالاتر در Media Query اول و یک قاعده با Specificity پایینتر در Media Query دوم باشد، Specificity برنده است — نه ترتیب.
آیا Container Queries جایگزین Media Queries میشود؟ نه. Container Queries و Media Queries دو ابزار مکمل هستند. Media Queries برای چیدمان کلی صفحه، Container Queries برای کامپوننتهای قابل استفاده مجدد. در پروژههای مدرن، ترکیب هر دو طبیعی است.
آیا prefers-* Queries در ایران کار میکنند؟ بله. prefers-color-scheme، prefers-reduced-motion و prefers-contrast در همه مرورگرهای مدرن — از جمله کروم، فایرفاکس و سافاری — پشتیبانی میشوند. این Media Queries از تنظیمات سیستمعامل کاربر میخوانند.
چگونه Media Queries را برای RTL بهینه کنیم؟ سه اصل: اول، استفاده از CSS Logical Properties درون Media Queries. دوم، تست در RTL کنار LTR در CI/CD. سوم، در نظر گرفتن تفاوت رفتار تایپوگرافی فارسی که ممکن است نیاز به Breakpointهای متفاوت داشته باشد.
آیا استفاده از Range Syntax توصیه میشود؟ بله. Range Syntax (مانند (640px <= width <= 1024px)) خواناتر و کمتر مستعد خطاست. پشتیبانی مرورگرها در ۲۰۲۶ گسترده است: Chrome 104+، Safari 16.4+، Firefox 102+.
آیا Media Queries میتوانند در JavaScript نیز استفاده شوند؟ بله. با window.matchMedia():
const mq = window.matchMedia("(min-width: 768px)");
if (mq.matches) {
// desktop
}
mq.addEventListener("change", (e) => {
if (e.matches) {
// desktop
} else {
// mobile
}
});
این تکنیک برای تغییر رفتار JavaScript بر اساس اندازه صفحه مفید است. توجه: ترجیحاً از CSS بهجای JavaScript استفاده کنید، چون CSS سریعتر و کارآمدتر است.
چگونه Media Queries را در CSS خود سازماندهی کنیم؟ سه رویکرد اصلی: اول، Media Queries را نزدیک به قواعد پایه (Inline) بنویسید. دوم، همه Media Queries را در انتهای فایل بنویسید. سوم، از پیشپردازندههایی مانند Sass با Mixin استفاده کنید. توصیه من: روش اول برای پروژههای کوچک، روش سوم برای پروژههای بزرگ.
آیا Media Query بر SEO اثر میگذارد؟ نه مستقیماً. اما از سال ۲۰۲۱، Mobile-First Indexing به استاندارد تبدیل شده است. اگر سایت شما در موبایل خوب نباشد — که با Media Queries تعیین میشود — رتبه SEO شما افت میکند. اگر با SEO آشنا نیستید، سئو چیست و چگونه به رشد سایت کمک میکند راهنمای جامعی است.
چگونه Media Queries را در CSS Grid بهکار ببریم؟ توصیه من: ابتدا از CSS Grid با auto-fit و minmax استفاده کنید که بهطور خودکار ریسپانسیو است. Media Query را فقط برای تغییرات ساختاری بزرگ (مانند تغییر چیدمان کلی صفحه) نگه دارید.
/* ریسپانسیو خودکار */
.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
}
/* Media Query فقط برای تغییرات ساختاری */
@media (min-width: 1024px) {
.grid-layout {
grid-template-areas:
"sidebar main"
"sidebar aside";
grid-template-columns: 250px 1fr;
}
}
نقشه راه اجرایی
اگر در حال طراحی یا بازبینی Media Queries در سازمان خود هستید، پنج گام عملی پیشنهاد میکنم:
- گام اول — Audit وضعیت فعلی: قبل از هر تغییری، وضعیت فعلی Media Queries را Audit کنید. سه سؤال: چند Media Query در CSS هست؟ آیا از Mobile-First استفاده میشود؟ آیا ترتیب منطقی است؟
- گام دوم — تعریف Breakpoints: Breakpoints را بر اساس محتوا، نه دستگاه، تعریف کنید. توصیه: شروع با ۴ Breakpoint (۴۸۰، ۷۶۸، ۱۰۲۴، ۱۲۸۰).
- گام سوم — Mobile-First بازنویسی: Media Queries را از Desktop-First (max-width) به Mobile-First (min-width) تبدیل کنید. این تغییر، حجم CSS را کاهش میدهد و پایداری را افزایش میدهد.
- گام چهارم — ادغام با طراحی سیال: برای اندازهها و فاصلهها از
clamp()،min()وmax()استفاده کنید و Media Queries را برای تغییرات ساختاری نگه دارید. - گام پنجم — تست و پایش: تست در CI/CD با Visual Regression در چند viewport. پایش مستمر در LTR و RTL.
Media Query، قلب تپنده CSS ریسپانسیو است، اما در ۲۰۲۶ دیگر تنها ابزار نیست. ترکیب Media Queries با طراحی سیال، Container Queries، Feature Queries و prefers-* Queries، یک رویکرد چندلایه ایجاد میکند که برای پروژههای مدرن ضروری است. تیمهایی که این رویکرد را جدی میگیرند، در سرعت تحویل، کیفیت محصول، دسترسپذیری و نرخ تبدیل بهطور قابل توجهی از رقبا جلوتر میشوند. اگر در پروژههای خود تجربهای از یکی از این ابعاد دارید — بهویژه در حوزههای Range Syntax، Container Queries، prefers-* یا RTL — برایم بنویسید کدام جنبه بیشترین اثر را داشت و چه چالشی را پشت سر گذاشتید. تجربه شما میتواند نقطه شروع دقیقتری برای تیم بعدی بسازد.