Grid Layout در CSS
بهنام نوبخت · ۱۴۰۵/۶/۲۸
در مقاله قبل با Flexbox آشنا شدیم؛ ابزاری قدرتمند برای ساخت Layoutهای یکبعدی که در چیدمان عناصر در یک ردیف یا یک ستون بسیار کاربردی است. اما بسیاری از Layoutهای واقعی وبسایتها فقط به یک محور محدود نمیشوند. برای مثال، یک صفحه داشبورد ممکن است همزمان چند ردیف و چند ستون داشته باشد، یا یک فروشگاه اینترنتی نیاز داشته باشد محصولات را در قالب یک شبکه منظم نمایش دهد.
اینجاست که CSS Grid Layout وارد میشود.
Grid یکی از مهمترین سیستمهای Layout در CSS است که برای ساخت چیدمانهای دوبعدی بر اساس ردیف و ستون طراحی شده است. با Grid میتوانیم عناصر را در سلولها قرار دهیم، چند سلول را با هم ترکیب کنیم، Layoutهای پیچیده بسازیم و حتی ساختار کلی یک صفحه را با نامگذاری بخشها تعریف کنیم.
در این مقاله ابتدا با مفاهیم اصلی Grid آشنا میشویم و سپس به سراغ fr، repeat()، minmax()، grid-area، grid-template-areas و ساخت Layoutهای Responsive میرویم.
Grid Layout چیست؟
CSS Grid یک سیستم Layout دوبعدی است؛ یعنی میتوانیم همزمان روی دو محور زیر کنترل داشته باشیم:
ردیفها یا Rows
ستونها یا Columns
برای مثال، فرض کنید چهار کارت داریم:
┌──────────┬──────────┐
│ کارت ۱ کارت ۲
├──────────┼──────────┤
│ کارت ۳ کارت ۴
└──────────┴──────────┘
با Grid میتوانیم دقیقاً مشخص کنیم چند ستون داشته باشیم و عناصر چگونه در این شبکه قرار بگیرند.
به زبان ساده:
Flexbox بیشتر برای چیدمان در یک محور مناسب است، در حالی که Grid برای چیدمان همزمان در ردیف و ستون طراحی شده است.
البته این به معنی رقابت بین Flexbox و Grid نیست. در پروژههای واقعی معمولاً از هر دو در کنار یکدیگر استفاده میکنیم.
Grid Container و Grid Item
برای استفاده از Grid ابتدا باید یک عنصر را به عنوان Grid Container مشخص کنیم.
این کار با display: grid انجام میشود:
.container {
display: grid;
}فرزندان مستقیم این عنصر، Grid Item محسوب میشوند.
مثلاً:
<div class="container">
<div>کارت اول</div>
<div>کارت دوم</div>
<div>کارت سوم</div>
<div>کارت چهارم</div>
</div>و:
.container {
display: grid;
}در این حالت .container یک Grid Container است و چهار div داخل آن Grid Item هستند.
ساخت اولین Grid
بیایید یک Grid دو ستونه بسازیم:
<div class="container">
<div>کارت ۱</div>
<div>کارت ۲</div>
<div>کارت ۳</div>
<div>کارت ۴</div>
</div>.container {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20px;
}نتیجه:
┌──────────────┬──────────────┐
│ کارت ۱ کارت ۲
├──────────────┼──────────────┤
│ کارت ۳ کارت ۴
└──────────────┴──────────────┘
در اینجا:
grid-template-columns: 1fr 1fr;
به Grid میگوید دو ستون ایجاد کند که فضای موجود را به صورت مساوی تقسیم کنند.
تعریف ستونها با grid-template-columns
یکی از مهمترین ویژگیهای Grid، grid-template-columns است.
با این ویژگی تعداد و اندازه ستونها را مشخص میکنیم.
مثلاً:
.container {
display: grid;
grid-template-columns: 200px 300px;
}دو ستون خواهیم داشت:
┌────────────┬─────────────────┐
│ 200px │ 300px │
└────────────┴─────────────────┘میتوانیم از واحدهای مختلف نیز استفاده کنیم:
grid-template-columns: 200px 1fr;در این حالت:
ستون اول
200pxستون دوم فضای باقیمانده
را دریافت میکند.
ایجاد سه ستون مساوی
برای ایجاد سه ستون مساوی:
.container {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
}یا شکل کوتاهتر:
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
}
هر دو تقریباً یک نتیجه دارند:
┌──────────┬──────────┬──────────┐
│ ستون ۱ ستون ۲ ستون ۳
└──────────┴──────────┴──────────┘
واحد fr در Grid
واحد fr مخفف fraction است و برای تقسیم فضای آزاد Grid استفاده میشود.
مثلاً:
grid-template-columns: 1fr 1fr;یعنی فضای موجود بین دو ستون به نسبت مساوی تقسیم شود.
اما:
grid-template-columns: 1fr 2fr;یعنی:
ستون اول یک سهم
ستون دوم دو سهم
از فضای قابل تقسیم را دریافت کند.
مثلاً:
┌──────────────┬──────────────────────────┐
│ 1 سهم 2 سهم
└──────────────┴──────────────────────────┘این ویژگی برای ساخت Layoutهای منعطف بسیار کاربردی است.
ترکیب واحدهای مختلف
میتوانیم fr را با واحدهای دیگر ترکیب کنیم:
.container {
display: grid;
grid-template-columns: 250px 1fr;
}
این الگو برای Sidebar بسیار رایج است:
┌──────────────┬─────────────────────────────┐
│ Sidebar │ Content │
│ 250px │ 1fr │
└──────────────┴─────────────────────────────┘
تعریف ردیفها با grid-template-rows
همانطور که با grid-template-columns ستونها را تعریف میکنیم، با grid-template-rows نیز میتوانیم ردیفها را تعریف کنیم.
مثلاً:
.container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 100px 200px;
}در این مثال:
ردیف اول
100pxردیف دوم
200px
ارتفاع خواهد داشت.
استفاده از auto
گاهی نمیخواهیم ارتفاع یک ردیف را به صورت ثابت تعیین کنیم.
میتوانیم از auto استفاده کنیم:
.container {
grid-template-rows: auto auto;
}در این حالت اندازه ردیف میتواند بر اساس محتوا تعیین شود.
برای Layoutهای محتوایی، این روش معمولاً انعطاف بیشتری نسبت به ارتفاع ثابت دارد.
فاصله بین آیتمها با gap
برای ایجاد فاصله بین Grid Itemها میتوانیم از gap استفاده کنیم.
.container {
display: grid;
gap: 20px;
}مثلاً:
┌─────────┐ 20px ┌─────────┐
│ کارت ۱ کارت ۲
└─────────┘ └─────────┘
gap هم فاصله بین ستونها و هم فاصله بین ردیفها را تعیین میکند.
column-gap
اگر فقط فاصله بین ستونها را بخواهیم:
.container {
column-gap: 30px;
}row-gap
اگر فقط فاصله بین ردیفها را بخواهیم:
.container {
row-gap: 20px;
}ترکیب Row و Column Gap
میتوانیم هر دو را همزمان مشخص کنیم:
.container {
row-gap: 20px;
column-gap: 30px;
}یا:
.container {
gap: 20px 30px;
}در حالت دوم:
gap: row-gap column-gap;تابع repeat
وقتی تعداد زیادی ستون یا ردیف مشابه داریم، نوشتن کد به شکل زیر خستهکننده است:
grid-template-columns: 1fr 1fr 1fr 1fr;به جای آن میتوانیم بنویسیم:
grid-template-columns: repeat(4, 1fr);تابع repeat() یک الگوی مشخص را چند بار تکرار میکند.
مثلاً:
grid-template-columns: repeat(3, 200px);معادل است با:
grid-template-columns: 200px 200px 200px;تابع minmax
یکی از ویژگیهای بسیار مهم Grid برای ساخت Layoutهای منعطف، تابع minmax() است.
ساختار آن:
minmax(minimum, maximum)مثلاً:
grid-template-columns: repeat(3, minmax(200px, 1fr));یعنی هر ستون:
حداقل
200pxحداکثر یک سهم از فضای موجود
داشته باشد.
این روش برای ساخت Gridهای Responsive بسیار مفید است.
ساخت Grid کارتهای Responsive
یکی از کاربردیترین ترکیبهای Grid:
.cards {
display: grid;
grid-template-columns: repeat(
auto-fit,
minmax(250px, 1fr)
);
gap: 20px;
}با این روش نیازی نیست برای هر اندازه صفحه تعداد ستونها را دستی تعیین کنیم.
مثلاً در دسکتاپ ممکن است:
┌──────┬──────┬──────┬──────┐
│ کارت کارت کارت کارت
└──────┴──────┴──────┴──────┘
و در صفحه کوچکتر:
┌──────────────┐
│ کارت
├──────────────┤
│ کارت
├──────────────┤
│ کارت
└──────────────┘
این الگو یکی از الگوهای بسیار کاربردی برای صفحات فروشگاهی، لیست خدمات و گالری تصاویر است.
auto-fit و auto-fill
در Grid میتوانیم از:
auto-fitو:
auto-fillدر repeat استفاده کنیم.
برای مثال:
grid-template-columns:
repeat(auto-fit, minmax(250px, 1fr));این امکان را فراهم میکند که تعداد Trackهای قابل استفاده متناسب با فضای موجود تنظیم شود.
در بسیاری از Gridهای کارتمحور، auto-fit انتخاب بسیار مناسبی است؛ مخصوصاً زمانی که میخواهیم ستونها فضای موجود را به شکل منعطف پر کنند.
قرار دادن یک عنصر در چند ستون
یکی از قابلیتهای مهم Grid این است که یک عنصر میتواند چند ستون را اشغال کند.
مثلاً:
.featured {
grid-column: span 2;
}اگر Grid سه ستونه باشد:
┌──────────────┬──────────────┬──────────────┐
│ │ │ │
│ Featured │ Featured │ کارت
│ │ │ │
├──────────────┼──────────────┼──────────────┤
│ کارت کارت کارت │
└──────────────┴──────────────┴──────────────┘
عنصر featured دو ستون را اشغال کرده است.
grid-column
برای تعیین محل یک آیتم در ستونها از grid-column استفاده میکنیم.
مثلاً:
.item {
grid-column: 1 / 3;
}یعنی آیتم از خط ستون اول شروع شود و تا خط ستون سوم ادامه پیدا کند.
در نتیجه دو ستون را پوشش میدهد.
روش دیگری نیز وجود دارد:
.item {
grid-column: span 2;
}یعنی عنصر دو ستون را اشغال کند.
grid-row
مشابه grid-column، برای ردیفها میتوانیم از grid-row استفاده کنیم:
.item {
grid-row: 1 / 3;
}یا:
.item {
grid-row: span 2;
}در حالت دوم عنصر دو ردیف را اشغال میکند.
grid-column-start و grid-column-end
اگر کنترل دقیقتری نیاز داشته باشیم، میتوانیم نقطه شروع و پایان ستون را جداگانه مشخص کنیم:
.item {
grid-column-start: 1;
grid-column-end: 4;
}همین کار برای ردیف:
.item {
grid-row-start: 1;
grid-row-end: 3;
}امکانپذیر است.
grid-area
ویژگی grid-area میتواند برای تعیین محدوده یک آیتم استفاده شود.
مثلاً:
.item {
grid-area: 1 / 1 / 3 / 3;
}ترتیب مقادیر به شکل زیر است:
row-start
column-start
row-end
column-endیعنی:
grid-area: row-start / column-start / row-end / column-end;این روش برای Layoutهای دقیق کاربرد زیادی دارد.
grid-template-areas
یکی از جذابترین قابلیتهای CSS Grid، تعریف Layout با نامگذاری بخشهاست.
فرض کنید یک صفحه داریم شامل:
Header
Sidebar
Main
Footer
HTML:
<div class="layout">
<header>Header</header>
<aside>Sidebar</aside>
<main>Main Content</main>
<footer>Footer</footer>
</div>میتوانیم Layout را به صورت زیر تعریف کنیم:
.layout {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
}سپس هر عنصر را به یک Area متصل میکنیم:
header {
grid-area: header;
}
aside {
grid-area: sidebar;
}
main {
grid-area: main;
}
footer {
grid-area: footer;
}این روش باعث میشود ساختار Layout حتی از روی خود CSS نیز کاملاً قابل درک باشد.
نقطه . در grid-template-areas
میتوانیم یک سلول را خالی بگذاریم:
grid-template-areas:
"header header"
"sidebar main"
". footer";علامت . به معنای سلول خالی است.
قوانین grid-template-areas
هنگام استفاده از grid-template-areas باید چند نکته را رعایت کنیم.
مثلاً این Layout معتبر است:
grid-template-areas:
"header header"
"sidebar main"
"footer footer";اما Areaها باید شکل مستطیلی داشته باشند.
برای مثال، نمیتوان یک Area را به شکل L ایجاد کرد.
همچنین تعداد سلولهای هر ردیف باید با سایر ردیفها سازگار باشد؛ در غیر این صورت تعریف Area معتبر نخواهد بود.
Responsive کردن Layout با grid-template-areas
یکی از کاربردهای بسیار جذاب این روش، تغییر Layout در اندازههای مختلف صفحه است.
برای دسکتاپ:
.layout {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
}در موبایل میتوانیم Layout را تغییر دهیم:
@media (max-width: 768px) {
.layout {
grid-template-columns: 1fr;
grid-template-areas:
"header"
"main"
"sidebar"
"footer";
}
}بدون تغییر HTML، ساختار صفحه کاملاً تغییر میکند.
این قابلیت برای طراحی سایتهای Responsive بسیار قدرتمند است.
تراز کردن عناصر در Grid
Grid فقط برای تعیین موقعیت نیست؛ بلکه امکانات مختلفی برای تراز کردن عناصر نیز دارد.
justify-items
برای کنترل تراز آیتمها در محور Inline استفاده میشود:
.container {
justify-items: center;
}مقادیر رایج:
start
end
center
stretchalign-items
برای تراز کردن آیتمها در محور Block استفاده میشود:
.container {
align-items: center;
}place-items
اگر بخواهیم هر دو را همزمان تنظیم کنیم:
.container {
place-items: center;
}این روش برای وسطچین کردن آیتمها بسیار کاربردی است.
justify-content و align-content
این دو ویژگی با justify-items و align-items یکی نیستند.
justify-items و align-items بیشتر روی آیتمها داخل Grid Area تأثیر دارند.
اما:
justify-contentو:
align-contentبرای تراز کردن خود Grid Trackها در فضای Container استفاده میشوند؛ مخصوصاً زمانی که Grid تمام فضای Container را پر نکرده باشد.
مثلاً:
.container {
justify-content: center;
align-content: center;
}یک پروژه عملی: Grid کارتهای خدمات
حالا یک مثال نزدیک به پروژههای واقعی بسازیم.
HTML:
<section class="services">
<article class="service-card">
<h3>طراحی سایت</h3>
<p>
طراحی سایت حرفهای و Responsive
برای کسبوکارها.
</p>
</article>
<article class="service-card">
<h3>فروشگاه ساز</h3>
<p>
راهاندازی فروشگاه اینترنتی
حرفهای.
</p>
</article>
<article class="service-card">
<h3>سئو</h3>
<p>
بهینهسازی سایت برای موتورهای جستجو.
</p>
</article>
<article class="service-card">
<h3>سرور مجازی</h3>
<p>
سرورهای قدرتمند برای پروژههای شما.
</p>
</article>
</section>CSS:
.services {
display: grid;
grid-template-columns:
repeat(auto-fit, minmax(250px, 1fr));
gap: 24px;
}
.service-card {
padding: 24px;
border: 1px solid #ddd;
border-radius: 16px;
background: #fff;
}این ساختار میتواند بدون تعریف تعداد ستون برای هر Breakpoint، خودش را با فضای موجود تطبیق دهد.
یک پروژه عملی: Dashboard
Grid برای Dashboardها نیز بسیار مناسب است.
HTML:
<div class="dashboard">
<header class="dashboard-header">
Header
</header>
<aside class="dashboard-sidebar">
Sidebar
</aside>
<main class="dashboard-content">
Main Content
</main>
<footer class="dashboard-footer">
Footer
</footer>
</div>CSS:
.dashboard {
min-height: 100vh;
display: grid;
grid-template-columns: 240px 1fr;
grid-template-rows: 80px 1fr 60px;
grid-template-areas:
"header header"
"sidebar content"
"footer footer";
}
.dashboard-header {
grid-area: header;
}
.dashboard-sidebar {
grid-area: sidebar;
}
.dashboard-content {
grid-area: content;
}
.dashboard-footer {
grid-area: footer;
}ساختار نهایی:
┌──────────────────────────────────────┐
│ Header │
├───────────────┬──────────────────────┤
│ │ │
│ Sidebar │ Content │
│ │ │
├───────────────┴──────────────────────┤
│ Footer │
└──────────────────────────────────────┘
Grid در طراحی سایت فارسی و RTL
در پروژههای فارسی، معمولاً Layout به صورت RTL طراحی میشود.
مثلاً:
body {
direction: rtl;
}Grid نیز میتواند در چنین Layoutهایی استفاده شود.
اما بهتر است به جای وابستگی بیش از حد به left و right، در طراحیهای مدرن تا حد امکان از ویژگیهای Logical CSS مانند:
margin-inline
padding-inline
inset-inlineنیز استفاده کنیم.
این موضوع در مقالههای آینده، مخصوصاً هنگام طراحی حرفهای رابطهای فارسی، اهمیت بیشتری پیدا خواهد کرد.
Grid یا Flexbox؟
یکی از سؤالهای رایج این است:
چه زمانی از Grid و چه زمانی از Flexbox استفاده کنیم؟
یک قانون ساده برای شروع:
نیاز | انتخاب مناسب |
|---|---|
چیدمان یکبعدی | Flexbox |
چیدمان ردیف و ستون | Grid |
Navigation | Flexbox |
گروه دکمهها | Flexbox |
لیست کارتها | Grid |
Dashboard | Grid |
Layout اصلی صفحه | Grid |
تراز کردن عناصر داخل یک Component | Flexbox |
اما این قانون مطلق نیست.
در یک پروژه حرفهای ممکن است Layout اصلی با Grid ساخته شود و داخل هر کارت از Flexbox استفاده کنیم.
مثلاً:
.products {
display: grid;
grid-template-columns:
repeat(auto-fit, minmax(250px, 1fr));
}
.product-card {
display: flex;
flex-direction: column;
}این ترکیب بسیار رایج است.
اشتباهات رایج در استفاده از Grid
۱. استفاده از Grid برای همه چیز
Grid ابزار قدرتمندی است، اما به این معنی نیست که تمام Layout باید با Grid ساخته شود.
برای یک ردیف ساده از عناصر، Flexbox ممکن است انتخاب بهتری باشد.
۲. استفاده بیش از حد از اندازههای ثابت
مثلاً:
grid-template-columns:
300px 300px 300px 300px;ممکن است در صفحه کوچک مشکل ایجاد کند.
در بسیاری از موارد بهتر است از:
repeat()همراه با:
minmax()استفاده کنیم.
۳. فراموش کردن gap
به جای اینکه برای هر کارت Marginهای مختلف تعیین کنیم:
.card {
margin: 10px;
}در Grid معمولاً بهتر است فاصله بین آیتمها را با:
gap: 20px;مدیریت کنیم.
۴. اشتباه گرفتن items و content
این دو گروه را با هم اشتباه نگیرید:
justify-items
align-itemsدر مقابل:
justify-content
align-contentاولی بیشتر روی آیتمها در Area خودشان کار میکند و دومی روی توزیع Trackهای Grid در Container تأثیر دارد.
۵. استفاده نکردن از Grid Inspector
مرورگرهای مدرن Developer Tools امکانات بسیار خوبی برای مشاهده Grid دارند.
وقتی Grid را انتخاب میکنید، میتوانید خطوط، ستونها، ردیفها و Areaها را مشاهده کنید.
برای یادگیری Grid، استفاده از Grid Inspector یکی از بهترین روشها برای درک واقعی ساختار Layout است.
تمرینهای این مقاله
تمرین ۱ — Grid سه ستونه
یک Grid شامل ۶ کارت ایجاد کنید:
┌──────┬──────┬──────┐
│ ۱ │ ۲ │ ۳ │
├──────┼──────┼──────┤
│ ۴ │ ۵ │ ۶ │
└──────┴──────┴──────┘شرایط:
سه ستون مساوی
فاصله
20pxاستفاده از
display: grid
تمرین ۲ — کارت ویژه
یک Grid سه ستونه بسازید و کاری کنید کارت اول دو ستون را اشغال کند.
از این ویژگی استفاده کنید:
grid-column: span 2;تمرین ۳ — صفحه Dashboard
یک Dashboard بسازید که شامل:
Header
Sidebar
Main
Footer
باشد.
سپس با grid-template-areas ساختار آن را تعریف کنید.
تمرین ۴ — Responsive Grid
یک لیست ۱۲تایی از کارتها ایجاد کنید.
از این ساختار استفاده کنید:
grid-template-columns:
repeat(auto-fit, minmax(250px, 1fr));سپس اندازه مرورگر را تغییر دهید و رفتار Grid را بررسی کنید.
جمعبندی
CSS Grid یکی از قدرتمندترین ابزارهای CSS برای ساخت Layoutهای مدرن است. برخلاف Flexbox که بیشتر برای چیدمان یکبعدی طراحی شده، Grid امکان کنترل همزمان ردیفها و ستونها را فراهم میکند.
مهمترین مفاهیمی که در این مقاله یاد گرفتیم عبارتاند از:
display: grid;برای فعال کردن Grid،
grid-template-columnsبرای تعریف ستونها،
grid-template-rowsبرای تعریف ردیفها،
gapبرای فاصله بین آیتمها،
frبرای تقسیم فضای موجود،
repeat()برای تکرار الگو،
minmax()برای ایجاد Trackهای منعطف،
grid-column
grid-rowبرای تعیین موقعیت و اندازه آیتمها،
و:
grid-template-areasبرای تعریف ساختار معنایی و خوانای Layout.
یکی از الگوهای بسیار مهمی که باید از این مقاله به خاطر بسپارید نیز این است:
.cards {
display: grid;
grid-template-columns:
repeat(auto-fit, minmax(250px, 1fr));
gap: 20px;
}این الگو پایه بسیار خوبی برای ساخت Gridهای Responsive مانند کارت محصولات، خدمات، مقالات و تصاویر است.
در پروژههای حرفهای نیز معمولاً لازم نیست بین Grid و Flexbox یکی را انتخاب کنیم؛ بلکه هرکدام را در جایی که مناسبتر است به کار میبریم.
نظرات
هنوز نظری ثبت نشده است.