آکادمی بنو/آموزش CSS

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
stretch

align-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 یکی را انتخاب کنیم؛ بلکه هرکدام را در جایی که مناسب‌تر است به کار می‌بریم.

۱۰

نظرات

کد در دسترس نیست

هنوز نظری ثبت نشده است.