آموزش کامل CSS Grid

این جلسه ادامه دوره کامل آموزش CSS آوای وبه. تو جلسه هشتم Flexbox رو کامل یاد گرفتیم، که برای چیدمان یکبعدی عالیه. حالا وقتشه با CSS Grid آشنا بشیم: قدرتمندترین ابزار CSS برای چیدمان دوبعدی، یعنی کنترل همزمان ردیفها و ستونها.
آنچه در این مقاله میخوانید:
📜 چرا اصلاً به CSS Grid نیاز پیدا کردیم؟
تو روزهای اول وب، هیچ ابزار درستی برای چیدمان صفحه نبود. طراحها مجبور بودن از جدولهای HTML (که اصلاً برای نمایش داده جدولی ساخته شده بودن، نه چیدمان صفحه) استفاده کنن. بعدها float اومد، ولی اونم یه راهحل جانبی بود. بعد Flexbox اومد که خیلی کمک کرد، ولی چون یکبعدیه، برای چیدمانهای پیچیدهی دوبعدی (مثل کل صفحه یه سایت) هنوز کافی نبود. CSS Grid دقیقاً برای همین ساخته شد: اولین ابزاری که از اول مخصوص چیدمان دوبعدی طراحی شده.
🎯 اهداف یادگیری این جلسه
- تمام پراپرتیهای Grid Container و هر مقدارشون رو با مثال یاد بگیری
- تمام پراپرتیهای Grid Item رو کامل بفهمی
- فرق Explicit Grid و Implicit Grid رو درک کنی
- با grid-template-areas چیدمانهای پیچیده بسازی
- با جدیدترین ویژگیها یعنی Subgrid و Masonry آشنا بشی
📦 شروع: تبدیل یه عنصر به Grid Container
.container {
display: grid;
}بهمحض این کار، فرزندهای مستقیم به Grid Item تبدیل میشن. تا اینجا هنوز هیچ ستون یا ردیفی تعریف نکردیم، پس مرورگر فقط هر آیتم رو تو یه ردیف جدا، به عرض کامل کانتینر، میچینه — قدرت واقعی Grid با پراپرتیهای بعدی باز میشه.
🧩 Explicit Grid و Implicit Grid — مفهومی که نباید ازش رد بشی
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: 100px 100px;
}این کد یه Grid با ۳ ستون و ۲ ردیف تعریف میکنه — یعنی ۶ سلول. حالا اگه ۸ تا آیتم داخلش بذاری، ۲ تای آخری کجا میرن؟ اینجا دو مفهوم مهم پیش میاد:
- Explicit Grid (صریح): همون ۳ ستون × ۲ ردیفی که خودت مستقیم تعریف کردی.
- Implicit Grid (ضمنی): ردیفهای اضافهای که مرورگر خودش، خودکار و بدون اینکه بخوای، میسازه تا آیتمهای اضافه رو جا بده.
حالا معنی پراپرتیهای زیر روشنتر میشه: grid-auto-rows اندازهی همین ردیفهای اضافهی خودکار رو مشخص میکنه، و grid-auto-flow میگه این آیتمهای اضافه تو جهت ردیف اضافه بشن یا ستون. این دو تا رو کاملتر پایینتر میبینیم.
1️⃣ پراپرتیهای Grid Container
grid-template-columns و grid-template-rows
.container {
display: grid;
grid-template-columns: 200px 1fr 100px;
grid-template-rows: 100px auto;
}این کد میگه: ۳ ستون داریم (اولی همیشه ۲۰۰px، سومی همیشه ۱۰۰px، و دومی هرچی فضای باقیمونده هست رو میگیره) و ۲ ردیف (اولی ۱۰۰px، دومی به اندازهی محتواش).
هر واحد یا مقداری که میتونی بین اینها استفاده کنی، با توضیح ساده:
| واحد/مقدار | توضیح ساده | مثال |
|---|---|---|
px | اندازهی ثابت به پیکسل، هیچوقت تغییر نمیکنه | 200px |
% | درصدی از عرض/ارتفاع کانتینر | 50% |
fr | یعنی «سهم» یا «کسر» — سهمی از فضای باقیمونده بعد از کمکردن ستونهای ثابت | 1fr |
auto | اندازه بر اساس محتوا، ولی اگه فضای اضافه باشه هم میگیره | auto |
min-content | کوچیکترین اندازهای که محتوا بدون سرریز و بدون شکستن کلمات جا بشه | min-content |
max-content | بزرگترین اندازهی طبیعی محتوا اگه هیچ محدودیتی نداشت | max-content |
minmax(min, max) | یه بازه تعریف میکنه؛ ستون بین این دو مقدار در نوسانه | minmax(150px, 1fr) |
fit-content(v) | مثل max-content رفتار میکنه ولی سقفش از مقدار دادی بیشتر نمیشه | fit-content(300px) |
مثال ساده برای fr: اگه بنویسی grid-template-columns: 1fr 2fr;، یعنی فضای کل کانتینر رو به ۳ قسمت مساوی تقسیم کن، ستون اول ۱ قسمتش رو بگیره و ستون دوم ۲ قسمت (یعنی دوبرابر ستون اول).
repeat() — جلوگیری از تکرار دستی
.container {
grid-template-columns: repeat(4, 1fr);
}
/* دقیقاً معادل: grid-template-columns: 1fr 1fr 1fr 1fr; */
اینجا repeat(4, 1fr) یعنی «مقدار 1fr رو ۴ بار تکرار کن» — یه میانبر ساده برای وقتی چند ستون یکسان میخوای.
حالا الگوی پیچیدهتر رو با توضیح کامل ببینیم:
.container {
grid-template-columns: repeat(2, 100px 1fr);
}اینجا فرق مهمیه: بهجای اینکه فقط یه مقدار تکرار بشه، یه گروه دو-تایی (100px 1fr) داریم که کل این گروه ۲ بار تکرار میشه. یعنی مرورگر اینطوری میخونه:
/* تکرار اول: */ 100px 1fr
/* تکرار دوم: */ 100px 1fr
/* نتیجهی نهایی: */ 100px 1fr 100px 1fr
یعنی در کل ۴ تا ستون داری: ستون ۱ و ۳ همیشه ۱۰۰pxان، ستون ۲ و ۴ فضای باقیمونده رو مساوی تقسیم میکنن. این الگو برای چیدمانهایی مثل «آیکون + متن، آیکون + متن» تکراری خیلی کاربردیه.
🌟 auto-fill و auto-fit — چیدمان ریسپانسیو خودکار
.container {
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}این کد رو تیکهتیکه معنی کنیم: minmax(200px, 1fr) میگه «هر ستون حداقل ۲۰۰px باشه ولی بتونه بزرگتر هم بشه». auto-fit یا auto-fill بهجای اینکه بگی «۳ تا ستون» یا «۴ تا ستون»، میگه «بذار خود مرورگر حساب کنه چندتا ستون ۲۰۰pxی تو عرض والد جا میشه» — بدون نوشتن حتی یه Media Query.
| مقدار | وقتی جای بیشتری از تعداد آیتمها هست، چیکار میکنه؟ |
|---|---|
auto-fill | ستونهای خالی نامرئی رو نگه میداره، پس ممکنه یه فضای خالی سمت راست/چپ بمونه |
auto-fit | ستونهای خالی رو جمع میکنه و آیتمهای موجود رو کش میده تا کل عرض رو پر کنن |
📊 مقایسه بصری auto-fill و auto-fit

🗺️ grid-template-areas — طراحی چیدمان با اسم
.container {
display: grid;
grid-template-columns: 200px 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"sidebar header"
"sidebar main"
"sidebar footer";
}
.header { grid-area: header; }
.main { grid-area: main; }
.sidebar { grid-area: sidebar; }
.footer { grid-area: footer; }بذار این کد رو خطبهخط معنی کنیم برای یه مبتدی کامل: هر خط داخل grid-template-areas یه ردیف از Gridه، و هر کلمه داخلش یه سلول از همون ردیف. اینجا ۲ ستون و ۳ ردیف داریم:
- ردیف اول: ستون اول = sidebar، ستون دوم = header
- ردیف دوم: ستون اول = sidebar (دوباره!)، ستون دوم = main
- ردیف سوم: ستون اول = sidebar (سهبار!)، ستون دوم = footer
وقتی یه اسم (مثل sidebar) چند بار پشت سر هم تو ردیفهای مختلف تکرار بشه، مرورگر میفهمه که این یعنی «این عنصر باید کل این چند ردیف رو با هم اشغال کنه» — دقیقاً همون کاری که یه سایدبار باید بکنه.
برای یه سلول خالی (بدون هیچ محتوایی)، بهجای اسم، از یه نقطه استفاده کن:
grid-template-areas:
"header header"
"sidebar ."
"footer footer";اینجا سلول پایین-راست عمداً خالی میمونه، هیچچیزی توش قرار نمیگیره.
grid-template — شکل کوتاه ترکیبی
.container {
grid-template:
"header header" auto
"sidebar main" 1fr
/ 200px 1fr;
}این یه سینتکس فشردهست که همزمان سه چیز رو تعریف میکنه: قبل از علامت / همون grid-template-areas بههمراه ارتفاع هر ردیف (کنار هر رشته نوشته شده: auto و 1fr)، و بعد از / عرض ستونها (200px 1fr). برای مبتدیها معمولاً نوشتن سه پراپرتی جدا (که بالاتر دیدیم) خیلی خواناتره.
🛍️ مثال واقعی کامل: چیدمان داشبورد
.dashboard {
display: grid;
grid-template-columns: 220px 1fr;
grid-template-rows: 60px 1fr 50px;
grid-template-areas:
"sidebar header"
"sidebar main"
"sidebar footer";
min-height: 100vh;
gap: 16px;
}
.sidebar { grid-area: sidebar; }
.header { grid-area: header; }
.main { grid-area: main; }
.footer { grid-area: footer; }
gap، row-gap، column-gap
.container {
gap: 20px; /* هم بین ردیفها هم بین ستونها */
row-gap: 10px; /* فقط فاصلهی بین ردیفها */
column-gap: 30px; /* فقط فاصلهی بین ستونها */
}این فاصلهی یکنواخت بین سلولها میذاره، فقط بین آیتمها (نه دور اولی/آخری) — بدون هیچ مشکل لبهای.
justify-items و align-items — تراز محتوای هر سلول
.container {
justify-items: center;
align-items: center;
}این دو تا میگن: محتوای داخل هر سلول کجای اون سلول بشینه؟ justify-items افقیه، align-items عمودیه. هر مقدار رو با توضیح ساده ببینیم:
| مقدار | توضیح ساده |
|---|---|
stretch (پیشفرض) | محتوا کشیده میشه تا کل سلول رو پر کنه |
start | محتوا به ابتدای سلول میچسبه (چپ برای افقی، بالا برای عمودی) |
end | محتوا به انتهای سلول میچسبه |
center | محتوا دقیقاً وسط سلول قرار میگیره |
justify-content و align-content — تراز کل Grid داخل کانتینر
.container {
justify-content: center;
}⚠️ این با justify-items اشتباه گرفته نشه: این پراپرتی وقتی معنا پیدا میکنه که کل Grid (جمع همهی ستونها) از عرض کانتینر کوچیکتر باشه — یعنی میگه کل شبکهی Grid کجای فضای اضافه بشینه، نه محتوای تکتک سلولها. مقادیرش: start, end, center, space-between (فاصلهی مساوی بین ستونها)، space-around (فاصلهی مساوی دور هر ستون)، space-evenly (همهی فاصلهها کاملاً مساوی، حتی کناریها).
🆕 place-items و place-content — میانبرهای مدرن
.container {
place-items: center; /* معادل align-items: center + justify-items: center */
}این تنها یه خط، یکی از سادهترین راههای وسطچین کامل (افقی+عمودی) یه عنصر داخل والدشه.
grid-auto-columns و grid-auto-rows — اندازهی سلولهای خودکار (Implicit)
.container {
grid-auto-rows: 150px;
}یادت باشه از بخش Explicit/Implicit بالاتر: وقتی آیتمی خارج از ردیف/ستونهای ازپیشتعریفشده قرار بگیره، مرورگر خودش یه ردیف/ستون «ضمنی» میسازه. این پراپرتی میگه اون ردیف/ستونهای ضمنی چه اندازهای باشن؛ اگه ننویسیش، مرورگر بر اساس محتوا حدس میزنه.
grid-auto-flow — جهت پرشدن سلولهای خودکار
.container {
grid-auto-flow: row;
}| مقدار | توضیح |
|---|---|
row (پیشفرض) | آیتمهای اضافه، ردیفبهردیف پر میشن |
column | آیتمهای اضافه، ستونبهستون پر میشن |
dense | مرورگر تلاش میکنه فضاهای خالی قبلی رو با آیتمهای بعدی پر کنه، حتی اگه ترتیب بصری با ترتیب HTML فرق کنه |
2️⃣ پراپرتیهای Grid Item
grid-column-start / grid-column-end / grid-column
.item {
grid-column: 1 / 3;
}خطوط Grid از عدد ۱ شمرده میشن، نه سلولها (اگه ۳ ستون داری، ۴ تا خط داری: قبل ستون اول، بین ۱-۲، بین ۲-۳، و بعد ستون آخر). نکتهی مهمی که خیلیها اشتباه میکنن: grid-column-end خودِ اون خط رو شامل نمیشه. یعنی 1 / 3 یعنی «از خط ۱ شروع کن، درست قبل از خط ۳ تموم کن»، که دقیقاً یعنی ۲ تا ستون رو میگیره (نه ۳ تا).
یه راه سادهتر و رایجتر استفاده از spanه:
.item {
grid-column: span 2;
}این یعنی «هرجا این آیتم شروع میشه، ۲ تا ستون رو بگیر» — نیازی به شمردن دستی شمارهی خطوط نداری.
grid-row-start / grid-row-end / grid-row
.item {
grid-row: span 2;
}دقیقاً همون منطق grid-column، فقط برای ردیفها.
grid-area — شکل کوتاه کامل
این پراپرتی دو کاربرد داره:
/* کاربرد ۱: چهار مقدار عددی با هم (row-start / column-start / row-end / column-end) */
.item {
grid-area: 1 / 1 / 3 / 4;
}
/* کاربرد ۲: همون اسمی که تو grid-template-areas تعریف کردی */
.header {
grid-area: header;
}کاربرد دوم (با اسم) خیلی رایجتر و خواناتره؛ همونیه که تو بخش grid-template-areas بالاتر استفاده کردیم.
justify-self و align-self
.item-special {
justify-self: end;
align-self: center;
}دقیقاً مثل justify-items/align-items، فقط بهجای اثر رو همهی آیتمها، فقط رو همین یه آیتم خاص اثر میذاره.
🆕 place-self
.item {
place-self: center;
}میانبر justify-self + align-self، دقیقاً مثل place-items ولی برای یه آیتم تنها.
order — تغییر ترتیب نمایش بدون تغییر HTML
.item-1 { order: 2; }
.item-2 { order: 1; }
.item-3 { order: 3; }پیشفرض همهی آیتمها order: 0ه. مرورگر آیتمها رو بر اساس این عدد، از کوچیک به بزرگ، نمایش میده — نه بر اساس ترتیبی که تو HTML نوشتی. تو مثال بالا، با اینکه item-1 تو HTML اول اومده، چون orderش (۲) از item-2 (order: ۱) بزرگتره، تو نمایش بصری بعد از item-2 قرار میگیره.
میتونی عدد منفی هم بدی (مثلاً order: -1) تا یه آیتم رو مطمئن باشی همیشه اول از همه بیاد. نکتهی مهم: این فقط ترتیب بصری رو عوض میکنه؛ ترتیب واقعی تو کد HTML و چیزی که screen reader میخونه، بدون تغییر میمونه — پس ازش زیاد و برای تغییرات بزرگ استفاده نکن، چون میتونه بین ظاهر صفحه و تجربهی کاربر با صفحهخوان ناهماهنگی ایجاد کنه.
🌟 جدیدترین ویژگیهای CSS Grid
Subgrid — وراثت واقعی خطوط از والد
برای فهمیدن Subgrid، اول یه مشکل رو با مثال ببینیم. فرض کن یه Grid اصلی با ۴ ستون داری و داخلش چند تا کارت گذاشتی که هرکدوم خودشون هم یه Grid کوچیکتر دارن:
.main-grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
}
.card {
display: grid;
grid-column: span 4;
grid-template-columns: repeat(4, 1fr); /* بدون subgrid: خطوط مستقل خودشو داره */
}مشکل بدون Subgrid: ستونهای داخل هر کارت، کاملاً مستقل از ستونهای Grid اصلی محاسبه میشن. یعنی اگه چند تا کارت کنار هم داشته باشی، ممکنه ستونهای داخلیشون دقیقاً زیر هم نیفتن (چون هر کارت جدا حساب میکنه محتواش چقدر جا میخواد).
راهحل با Subgrid:
.card {
display: grid;
grid-column: span 4;
grid-template-columns: subgrid; /* بهجای تعریف مستقل، از والد ارث میبره */
}حالا ستونهای داخل هر کارت، دقیقاً همون خطوط Grid اصلی رو به ارث میبرن — یعنی اگه ۵ تا کارت کنار هم داری، محتوای داخلشون (مثل قیمت یا دکمه) همه دقیقاً زیر هم و همتراز میمونن، انگار همه عضو یه Grid واحد بزرگترن.
🧱 Masonry Layout — چیدمان آجری (تجربی)
.container {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-template-rows: masonry;
}تصور کن یه گالری تصاویر داری که هر عکس ارتفاع متفاوتی داره (مثل Pinterest). تو یه Grid معمولی، چون ارتفاع هر ردیف باید یکسان باشه، بین عکسهای کوتاهتر فضای خالی زشتی میمونه. با grid-template-rows: masonry، مرورگر خودش هر آیتم رو تو کوتاهترین ستون ممکن قرار میده، دقیقاً مثل چیدن آجر، بدون فضای خالی اضافه — همهی اینها فقط با CSS، بدون جاوااسکریپت.
⚠️ هشدار مهم: این ویژگی هنوز بهطور یکسان تو همهی مرورگرهای اصلی پیاده نشده و بخشی از مشخصاتش هنوز در حال تغییره. برای پروژهی واقعی امروز، هنوز باید پشتیبانی مرورگرهای هدفت رو چک کنی؛ روشهای جایگزین (مثل column-count یا کتابخانههای جاوااسکریپتی) هنوز مطمئنترن.
🖼️ مثال واقعی: گالری تصاویر ریسپانسیو
.gallery {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 12px;
}
🤔 چه زمانی از Flexbox و چه زمانی از Grid؟
اگه فقط یه ردیف یا یه ستون میچینی، Flexbox جواب میده. اگه هم ردیف هم ستون همزمان مهمن (چیدمان دوبعدی واقعی، مثل کل صفحه یا یه گالری منظم)، Grid انتخاب درسته. خیلی از پروژههای واقعی هر دو رو با هم دارن: کل صفحه با Grid، و داخل هر بخش (مثل یه navbar) با Flexbox.
🎮 تمرین تعاملی: CSS Grid Garden
برای تمرین Grid بهصورت بازیگونه، CSS Grid Garden رو امتحان کن؛ هر مرحلهاش یه چالش واقعی Grid بهت میده.
⚠️ اشتباهات رایج در کار با CSS Grid
- قاطی کردن Grid Line با شمارهی سلول: خطوط از ۱ شمرده میشن، ولی همیشه یکی بیشتر از تعداد سلولهان.
- فراموش کردن اینکه grid-column-end خودِ خط رو شامل نمیشه:
1 / 3یعنی ۲ ستون، نه ۳ تا. - اسم متفاوت تو grid-template-areas و grid-area: باید دقیقاً یکی باشن، وگرنه سلول خالی میمونه.
- استفاده از Grid برای چیدمان یکبعدی ساده: اونجا Flexbox معمولاً سادهتره.
- قاطی کردن justify-content و justify-items: یکی کل Grid رو جابهجا میکنه، اون یکی محتوای داخل هر سلول رو تراز میکنه.
📋 جدول جامع نهایی: همه پراپرتیهای CSS Grid
| دسته | پراپرتی |
|---|---|
| Container | display: grid / inline-grid |
grid-template-columns | |
grid-template-rows | |
grid-template-areas | |
grid-template (کوتاه) | |
gap / row-gap / column-gap | |
justify-items / align-items / place-items | |
justify-content / align-content / place-content | |
grid-auto-columns | |
grid-auto-rows | |
grid-auto-flow | |
grid (کوتاه کلی) | |
| Item | grid-column-start/end / grid-column |
grid-row-start/end / grid-row | |
grid-area | |
justify-self / align-self / place-self | |
order | |
| مدرن | grid-template-columns: subgrid |
grid-template-rows: masonry (تجربی) |
🧪 تمرین این جلسه
یه داشبورد با grid-template-areas بساز. بعد یه گالری ریسپانسیو با auto-fit بساز. در پایان، ۳ کارت بساز که یکیشون با order به آخر منتقل بشه و محتوای هرکدوم با place-items وسطچین بشه.
❓ سوالات متداول
فرق CSS Grid و Flexbox چیه؟
Flexbox یکبعدیه (فقط ردیف یا فقط ستون)، Grid دوبعدیه (ردیف و ستون همزمان).
فرق auto-fill و auto-fit چیه؟
auto-fill فضای خالی ستونهای استفادهنشده رو نگه میداره؛ auto-fit اون فضا رو جمع میکنه و آیتمهای موجود رو کش میده.
چرا grid-column: 1 / 3 دو ستون میگیره نه سهتا؟
چون خطوط Grid شمارش میشن نه سلولها، و خط پایانی (اینجا ۳) خودش شامل نمیشه؛ فقط فضای بین دو خط حساب میشه.
order روی ترتیب خواندهشدن صفحه توسط screen reader اثر داره؟
نه؛ order فقط ترتیب بصری رو تغییر میده، ترتیب واقعی HTML (و چیزی که صفحهخوان میخونه) بدون تغییر میمونه.
🎯 جمعبندی و قدم بعدی
حالا هر پراپرتی CSS Grid رو با مثال کامل میشناسی: از grid-template-columns تا subgrid و order. جلسه بعد میریم سراغ Responsive Design.
جلسه دهم: آموزش کامل Responsive Design در CSS ←
💬 نوبت توئه!
کدوم پراپرتی Grid برات جدید بود؟ داشبورد تمرین رو ساختی؟ سوالی داشتی همین پایین برامون بنویس 🚀
