در این فصل چه میسازی#
آخر این فصل یک گالری از کارتها داری که چیدمانش را با عرضِ صفحه عوض میکند: روی موبایلِ باریک یک ستون، و روی صفحهٔ پهن سه ستون. فرقِ این فصل با فصل قبل مهم است — آنجا صفحه فقط جمع و باز میشد، اینجا واقعاً چیدمان عوض میشود. ابزارش یک قاعدهٔ تازه است به اسم media query: راهی که به CSS بگویی «این استایلها فقط وقتی اجرا شوند که عرضِ صفحه از فلان مقدار بیشتر باشد».

آخر این فصل میتوانی:
- یک
@mediaبنویسی که فقط در عرضهای مشخص اجرا شود - بگویی
breakpointچیست و کجای طرح باید گذاشته شود - فرقِ
min-widthوmax-widthرا بگویی و درست را انتخاب کنی - یک چیدمان را mobile-first بنویسی، از یک ستون به سه ستون
قبل از شروع#
- از فصل ۱ (همین ترم): meta viewport و mobile-first — این فصل مستقیم روی همانها سوار است.
- از ترم ۳:
display: grid،grid-template-columnsو واحدfr— گالری را با همین میسازیم. - از ترم ۳:
gap— فاصلهٔ بین کارتها.
مثل همیشه فقط یک مرورگر لازم داری، یا فقط همین آزمایشگاه.
۱. media query یعنی چه#
تا اینجا هر قاعدهٔ CSS ای که نوشتی همیشه اجرا میشد. media query یک شرط دور یک دسته قاعده میگذارد: «اینها را فقط وقتی اعمال کن که یک چیزی دربارهٔ صفحه درست باشد» — معمولاً یک چیز دربارهٔ عرضِ صفحه. با آن میتوانی به مرورگر بگویی «روی صفحههای پهن اینطور بچین، روی باریک آنطور».
شکلش این است: کلمهٔ @media، بعد شرط داخل پرانتز، بعد یک { } که قاعدههای معمولی داخلش میروند:
@media (min-width: 700px) {
/* har CSS injaa faghat rooye arze 700px va bishtar ejraa mishavad */
}
(min-width: 700px) یعنی «اگر عرضِ صفحه حداقل ۷۰۰ پیکسل است». هر قاعدهای که داخلِ آن { } بگذاری، فقط روی صفحههای ۷۰۰ پیکسل و پهنتر اجرا میشود؛ روی باریکتر انگار اصلاً نوشته نشده. بیرونِ @media قاعدههای همیشگی میمانند — پایهٔ کار.
۲. اولین @media: از یک ستون به سه ستون#
بیا گالری را بسازیم. اول HTML: یک <main> با شش کارت. <article> را برای کارت بهکار میبریم چون هر کارت یک تکهٔ مستقل است، همانطور که در ترم ۱ یاد گرفتی:
<main class="grid">
<article class="card">یک</article>
<article class="card">دو</article>
<article class="card">سه</article>
<article class="card">چهار</article>
<article class="card">پنج</article>
<article class="card">شش</article>
</main>
حالا استایلِ پایه. چون mobile-first کار میکنیم، حالتِ پیشفرض همان حالتِ موبایل است: یک ستون. این قاعدهها بیرونِ هر @media میمانند تا همیشه اجرا شوند:
.grid {
display: grid;
grid-template-columns: 1fr;
gap: 16px;
}
.card {
background-color: #2a6b93;
color: #ffffff;
padding: 24px;
border-radius: 8px;
text-align: center;
}
✅ چک کن: شش کارتِ آبی در یک ستونِ عمودی میبینی، زیرِ هم. این حالتِ موبایل است و باید ساده و بیعیب باشد. حالا امکانِ «صفحهٔ پهن» را رویش سوار میکنیم.
یک @media اضافه کن که فقط روی عرضِ پهن، ستونها را سهتا کند:
@media (min-width: 700px) {
.grid {
grid-template-columns: 1fr 1fr 1fr;
}
}
✅ چک کن: حالا عرضِ پیشنمایش را آرام پهن کن. تا وقتی باریک است یک ستون میماند؛ لحظهای که از ۷۰۰ پیکسل رد شد، ناگهان سه ستون میشود. باریکش کن، دوباره یک ستون. همین جهش، قلبِ media query است.
💡 نکته: داخلِ یک
@mediaهر تعداد قاعده که بخواهی میگذاری، نه فقط یکی. سرِ یک breakpoint معمولاً چند چیز با هم عوض میشوند — مثلاً هم ستونها بیشتر میشوند، همgapبازتر، هم فونتِ تیتر کمی بزرگتر. همه را کنارِ هم داخلِ همان یک@media (min-width: 700px)بنویس؛ لازم نیست برای هر property یک query جدا بسازی.
۳. breakpoint چیست#
آن عددِ ۷۰۰ که چیدمان سرِ آن عوض شد، یک اسم دارد: breakpoint. یعنی «نقطهٔ شکست» — عرضی که در آن، طرحِ صفحه از یک حالت به حالتِ دیگر میرود. هر سایتی چند breakpoint دارد؛ جاهایی که تصمیم میگیری چیدمان عوض شود.
breakpoint را از کجا انتخاب کنیم؟ بهترین راهنما خودِ محتواست، نه اندازهٔ یک گوشیِ خاص. عرضِ پیشنمایش را آرام پهن کن و ببین کجا چیدمانت شروع به بدشکلشدن میکند — مثلاً کارتها آنقدر پهن میشوند که زشتاند، یا متن خیلی کش میآید. همانجا یک breakpoint بگذار. عددهایی مثل ۶۰۰، ۷۰۰ و ۹۰۰ نقطههای شروعِ رایجاند، ولی قانونِ آسمانی نیستند.
💡 نکته:
breakpointرا با عددِ ثابتِ گوشیِ امروز گره نزن؛ گوشیها هر سال عوض میشوند. بهجای «این دقیقاً عرضِ فلان موبایل است» فکر کن «اینجا چیدمانم بد میشود، پس اینجا عوضش میکنم». اینطوری طرحت با هر دستگاهِ آینده هم جور درمیآید.
قبل از ادامه، جواب بده: اگر یک قاعده را داخلِ @media (min-width: 700px) بگذاری، روی یک موبایلِ ۳۶۰ پیکسلی اجرا میشود؟ (نه — چون ۳۶۰ کمتر از ۷۰۰ است، شرط برقرار نیست.)
۴. min-width در برابر max-width#
دو جهت برای شرط داری:
(min-width: 700px)یعنی «عرض حداقل ۷۰۰» — از ۷۰۰ به بالا. این جهتِ mobile-first است: پایه را برای موبایل مینویسی، بعد باmin-widthامکاناتِ صفحهٔ بزرگ را اضافه میکنی.(max-width: 700px)یعنی «عرض حداکثر ۷۰۰» — از ۷۰۰ به پایین. این جهتِ desktop-first است: پایه را برای دسکتاپ مینویسی، بعد برای صفحهٔ کوچک چیزها را پس میگیری.
هر دو کار میکنند، ولی در تاروپود mobile-first را انتخاب میکنیم، پس min-width ابزارِ اصلیِ توست. دلیلش همان است که فصل قبل گفتیم: از ساده به پیچیده رفتن مطمئنتر است. با min-width، پایهات سادهترین حالت است و هر @media فقط چیزی رویش میگذارد.

۵. وقتی دو query دعوا میکنند#
حالا یک اشتباهِ رایج و آموزنده. فرض کن بهجای mobile-first، بخواهی هر دو حالت را جدا با query بنویسی — یکی برای باریک، یکی برای پهن — و هر دو را روی همان عددِ ۷۰۰ بگذاری:
@media (max-width: 700px) {
.grid { grid-template-columns: 1fr; }
}
@media (min-width: 700px) {
.grid { grid-template-columns: 1fr 1fr 1fr; }
}
بهنظر منطقی میآید: زیرِ ۷۰۰ یک ستون، بالای ۷۰۰ سه ستون. ولی عرضِ پیشنمایش را دقیقاً روی ۷۰۰ بگذار. یک مشکلِ ظریف هست: در دقیقاً ۷۰۰ پیکسل، هر دو شرط برقرارند — max-width: 700 یعنی «۷۰۰ یا کمتر» و min-width: 700 یعنی «۷۰۰ یا بیشتر»، و ۷۰۰ در هر دو میگنجد. پس هر دو قاعده اجرا میشوند و آنکه در فایل پایینتر است برنده میشود. مرزِ دو query روی هم افتاده.
🔧 اگر کار نکرد: روی عددِ مرزی رفتارِ عجیب دیدی، یا مطمئن نیستی کدام قاعده برنده است؟ علتش همین همپوشانیِ
min-width: 700وmax-width: 700روی یک عددِ یکسان است. راهِ درست این نیست که مرز را با اعشار جابهجا کنی؛ راهِ تمیز این است که اصلاً دو query نگذاری. mobile-first بنویس: پایه را یکستونه بگذار (بیهیچ query) و فقط یک@media (min-width: 700px)برای سهستونه اضافه کن. حالا هیچ دو شرطی نیست که سرِ مرز دعوا کنند — و همان کدِ بخش ۲ است.
کد کاملِ این فصل#
این هم دو فایلِ کامل، یکجا. اول index.html:
<!-- index.html -->
<!DOCTYPE html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>چیدمان responsive</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<main class="grid">
<article class="card">یک</article>
<article class="card">دو</article>
<article class="card">سه</article>
<article class="card">چهار</article>
<article class="card">پنج</article>
<article class="card">شش</article>
</main>
</body>
</html>
و styles.css — دقت کن که فقط یک @media با min-width داریم، دقیقاً همان راهِ تمیزِ mobile-first:
/* styles.css */
* {
box-sizing: border-box;
}
body {
background-color: #f6edda;
margin: 0;
padding: 16px;
}
.grid {
display: grid;
grid-template-columns: 1fr;
gap: 16px;
}
.card {
background-color: #2a6b93;
color: #ffffff;
padding: 24px;
border-radius: 8px;
text-align: center;
}
@media (min-width: 700px) {
.grid {
grid-template-columns: 1fr 1fr 1fr;
}
}
✅ چک کن: روی صفحه شش کارتِ آبی میبینی که روی باریک یکستونه و روی پهن سهستونهاند. عرضِ پیشنمایش را از باریک تا پهن بکش و لحظهٔ جهش روی ۷۰۰ را ببین.
🤖 با AI: از دستیار AI ات بپرس «یک
media queryبنویس که این گالری روی صفحهٔ متوسط دو ستون و روی صفحهٔ پهن سه ستون شود». جوابش را خطبهخط بخوان: چند تا@mediaگذاشته؟min-widthاست یاmax-width؟ آیا mobile-first است؟ بعد همان کد را در آزمایشگاه بگذار و عرض را بکش تا با چشمت ببینی سرِ مرزها درست جهش میکند یا نه — AI دربارهٔ layout با اطمینان اشتباه میگوید.
واژههای تازهٔ این فصل#
| کلمه | تلفظ به حروف فارسی | یعنی چه |
|---|---|---|
| media query | مدیا کوئری | شرطی که یک دسته قاعدهٔ CSS را فقط در وضعیتِ مشخصی از صفحه اجرا میکند |
@media |
اَت-مدیا | کلمهای که یک media query را شروع میکند |
| breakpoint | بریکپوینت | عرضی که در آن چیدمانِ صفحه از یک حالت به حالتِ دیگر میرود |
min-width |
مین-ویدث | شرطِ «عرض حداقل اینقدر»؛ جهتِ mobile-first |
max-width |
مکس-ویدث | شرطِ «عرض حداکثر اینقدر»؛ جهتِ desktop-first |
تمرینها
اول خودت فکر کن یا امتحان کن — بعد اینجا را باز کن.
در فصل بعد#
الان میتوانی چیدمانِ صفحه را با عرض عوض کنی. ولی یک چیزِ مهم هنوز جا مانده: تصویرها. یک عکس بهطور پیشفرض به media query گوش نمیدهد و میتواند از جعبهاش بیرون بزند یا بدشکل شود. فصل بعد سراغِ همین میرویم: با max-width: 100%، object-fit و srcset یاد میگیری تصویرها را هم مثل بقیهٔ صفحه responsive کنی.
به آخر این فصل رسیدی!
اگر ساختی و جواب داد، این دکمه مال توست.