مقدمه

در درس قبل با Flexbox به عنوان یک روش مدرن برای طرح‌بندی صفحه آشنا شدیم. با این حال، Flexbox با همه‌ی قدرتی که دارد، محدودیت‌هایی هم دارد که مهمترین آنها تک‌بعدی بودن آن است. تک بعدی بودن Flexbox به این معناست که آیتم‌های flex فقط می‌توانند به صورت عمودی یا افقی مرتب شوند. اما Grid یک سیستم‌ طرح‌بندی دوبعدی است که چینش عناصر را در دو جهت افقی و عمودی به طور همزمان انجام می‌دهد. البته نباید تصور کنید که Grid یک ورژن قدرتمندتر از Flexbox است. هر کدام از این تکنولوژی‌ها کاربردهای خودش را دارد و برای شرایط مشخصی مفیدتر از دیگری است. در این درس ابتدا با مفاهیم مربوط به Grid و سپس، با روش طرح‌بندی صفحه با استفاده از Grid آشنا می‌شویم.

مفاهیم پایه مربوط به Grid

واژه‌ی Grid در گرافیک و طراحی به شبکه‌ای از خطوط افقی و عمودی گفته می‌شود که به صورت منظم در یک صفحه قرار می‌گیرند و برای سازماندهی و هم‌تراز کردن عناصر طراحی استفاده می‌شوند. قرن‌هاست که در صنعت نشر از گریدها استفاده می‌شود و حالا چند سالی است که این تکنیک به وب هم راه یافته است.

قبل از هر چیز باید بدانید که Grid بخشی از محتوای یک صفحه‌ی وب نیست، بلکه یک رویکرد سیستماتیک برای نشاندن عناصر و جاسازی آنها در صفحه است. کار کردن با Grid دارای چند مزیت عملی و زیباشناختی است. از جمله:

  • استفاده از Grid ترتیب و نظم را به نمایش عناصر صفحه اضافه می‌کند و با یک ریتم بصری مطلوب برای چشم همراه است.
  • Grid با یک یک طراحی منطقی و منسجم به کاربران کمک می‌کند که اطلاعات مورد نیازشان را پیدا کنند.
  • یک Grid که به خوبی طراحی شده باشد، دسترسی به محتوا و بخش‌های مختلف را برای افرادی که با محدودیت‌ها و معلولیت‌هایی دست و پنجه نرم می‌کنند، ساده‌تر می‌کند.
  • Grid با استقرار یک فریمورک سیستماتیک برای طرح‌بندی صفحه، سرعت فرایند توسعه را افزایش می‌دهد.

استفاده از Grid برای طرح‌بندی صفحه به این معناست که صفحه (یا بخشی از صفحه) را به عنوان یک جدول متشکل از چند سطر و ستون تصور می‌کنیم و محتوا را در خانه‌های جدول یا گرید می‌نشانیم. در مورد تعداد سطرها و ستون‌های یک ستون باید بدانید که:

  • یک Grid می‌تواند از یک یا چند سطر تشکیل شود و این چیزی است که از روی محتوای صفحه تعیین می‌شود.
  • تعداد ستون‌های یک Grid به گونه‌ای تعیین می‌شود که با بیشترین انعطاف ممکن همراه باشد. رایج‌ترین عدد برای تعداد ستون‌های یک Grid عدد 12 است؛ چون 12 عددی است که بر 2، 3، 4، و 6 بخش‌پذیر است و این کار محاسبات را ساده‌تر می‌کند.

کانتینر Grid و آیتم‌های Grid

مشابه چیزی که در مورد Flexbox دیدیم، وقتی بخواهیم layout یک عنصر را با استفاده از Grid تعیین کنیم، باید مقدار پراپرتی display را برای آن عنصر را روی grid یا inline-grid تنظیم کنیم. در این صورت، آن عنصر یک کانتینر Grid محسوب می‌شود و هر فرزند مستقیم آن یک آیتم Grid است.

تفاوت مقدار grid و inline-grid در این است که مقدار grid یک کانتینر از نوع Block و مقدار inline-grid یک کانتینر از نوع Inline ایجاد می‌کند. Block یا Inline بودن کانتینر Grid به نمایش بیرونی کانتینر مربوط است و از نظر نمایش درونی آیتم‌های Grid تفاوتی بین این دو مقدار وجود ندارد.

خطوط Grid

خطوطی که سطرها و ستون‌های یک Grid را ایجاد می‌کنند، خطوط Grid یا Grid lines نامیده می‌شوند و خانه‌ها یا سلول‌هایی که از تقاطع خطوط افقی و عمودی ایجاد می‌شوند، شامل عناصر صفحه‌ی وب خواهند بود. در CSS برای ارجاع به مکان‌های مورد نظر در یک گرید از روش شماره‌گذاری زیر برای خطوط گرید استفاده می‌شود.

شماره گذاری خطوط گرید در CSS

البته این امکان هم وجود دارد که به ترتیب عکس به خطوط گرید ارجاع دهیم. در این صورت، شماره‌گذاری از گوشه‌ی پایین سمت راست و با مقدار -1 شروع می‌شود.

شماره‌گذاری خطوط گرید با اعداد منفی در CSS

شماره‌گذاری منفی یک مزیت مهم دارد و آن این است که می‌توانیم برای ارجاع به آخرین خط، بدون توجه به تعداد خطوط، از -1 استفاده کنیم.

ناحیه‌های Grid

یک عنصر می‌تواند درون یک خانه از گرید قرار گیرد و یا اینکه در یک ناحیه‌ی گرید (grid area) متشکل از چند حانه قرار گیرد. شکل زیر یک ناحیه‌ی ‌گرید متشکل از دو سطر و دو ستون را هایلایت کرده است. توجه داشته باشید که ناحیه‌ی گرید باید مستطیل‌شکل باشد و ما نمی‌توانیم مثلاً یک ناحیه‌ی گرید به شکل L داشته باشیم.

ناحیه‌های گرید در CSS

تعریف Grid

برای ایجاد سطرها و ستون‌های یک گرید از دو پراپرتی با نام‌های grid-template-rows و grid-template-columns استفاده می‌شود که به‌ترتیب، برای تعیین عرض سطرها و ارتفاع ستون‌های گرید کاربرد دارند. برای ایجاد فاصله بین آیتم‌های گرید هم می‌توانیم از پراپرتی gap استفاده کنیم.

 Copy Icon CSS
.container{
  display: grid;
  grid-template-columns: 10rem 10rem;
  grid-template-rows: 5rem 5rem;
  gap: 5px;
}

در این مثال، ما یک گرید ایجاد کرده‌ایم که متشکل از دو ستون به اندازه‌ی 10rem و دو سطر به ارتفاع 5rem است. به این ترتیب، ما الان دو سطر و دو ستون داریم که منجر به ایجاد چهار سلول می‌شوند و چهار آیتم را در این کانتینر قرار داده‌ایم که به طور خودکار، هر کدام در یک سلول قرار می‌گیرند. حالا اجازه دهید ببینیم چه اتفاقی رخ می‌دهد اگر آیتم‌های بیشتری به این کانتینر اضافه کنیم.

 Copy Icon CSS
.container{
  display: grid;
  grid-template-columns: 10rem 10rem;
  grid-template-rows: 5rem 5rem;
  gap: 5px;
}

اگر این کد را اجرا کنید، خواهید دید که آیتم‌های 5 و 6 به گرید اضافه شده‌اند. اما گرید ما فقط 4 سلول داشت، پس 2 سلول اضافی چطور ساخته شده و آیتم‌ها را در بر گرفته‌اند؟ در پاسخ این سوال، با مفهوم گریدهای ضمنی و صریح مواجه می‌شویم.

گرید صریح (explicit grid) به طور مستقیم توسط ما و با استفاده از پراپرتی‌های grid-template-columns و grid-template-rows ایجاد می‌شود. اما گرید ضمنی (implicit grid) توسط مرورگر و در زمانی ساخته می‌شود که تعداد سلول‌های گرید صریحی که تعریف کرده‌ایم از تعداد آیتم‌های گرید کمتر باشد. در این صورت، خود مرورگر سطرها و ستون‌هایی را به گرید اضافه می‌کند. پس، سطرها و ستون‌هایی که ما تعریف می‌کنیم، یک گرید صریح را می‌سازد و سطرها و ستون‌های اضافه‌شده توسط مرورگر، یک گرید ضمنی را شکل می‌دهد.

سایز آیتم‌های یک گرید ضمنی در حالت پیش‌فرض از روی محتوای آیتم‌ها تعیین می‌شود اما این رفتار پیش‌فرض را می‌توان با استفاده از پراپرتی grid-auto-rows کنترل کرد. مثال زیر را ببینید.

 Copy Icon CSS
.container{
  display: grid;
  grid-template-columns: 10rem 10rem;
  grid-template-rows: 5rem 5rem;
  grid-auto-rows: 5rem;
  gap: 5px;
}

حالا همه‌ی آیتم‌های گرید، سایز یکسانی دارند.

تعیین سایز آیتم‌های Grid

برای تعیین سایز گرید می‌توانیم از هر یک از واحدهای طولی مانند px، em و rem و یا حتی درصد استفاده کنیم. اما CSS Grid یک واحد جدید با نام fr را نیز معرفی کرده که یک واحد کسری (fractional) است که به کسر یا نسبتی از فضای خالی اشاره می‌کند. برای مثال، اگر چهار ستون داشته باشیم که همگی دارای سایز 1fr باشند، هر ستون 25% از فضای موجود را به خود اختصاص می‌دهد. مثال زیر را ببینید.

 Copy Icon CSS
.container{
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 5rem 5rem;
  grid-auto-rows: 5rem;
  gap: 5px;
  width: 30rem;
}

در اینجا سایز هر یک از ستون‌ها برابر با 1fr است و این به این معناست که فضای موجود به نسبت مساوی بین ستون‌ها تقسیم می‌شود. اگر ستون وسطی را به 2fr تغییر دهیم، نسبت به دو ستون دیگر دو برابر می‌شود.

تابع repeat

گاهی اوقات در تعیین سایز گرید، ناگزیر از تکرار مقادیر هستیم. مثلاً برای تخصیص مقدار یکسان 1fr به چهار ستون یک گرید، داریم:

Copy Icon CSS
grid-template-columns: 1fr 1fr 1fr 1fr;

در اینگونه موارد می‌توانیم از تابعی به نام repeat استفاده کنیم:

Copy Icon CSS
grid-template-columns: repeat(4, 1fr);

تابع minmax

اگر از یک سایز ثابت برای یک سطر استفاده کنیم و محتوای یک سلول در آن جا نشود، مانند مثال زیر، سرریز یا overflow رخ می‌دهد.

 Copy Icon CSS
.container{
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: 3rem 3rem;
  gap: 5px;
  width: 15rem;
}

برای حل این مشکل، می‌توانیم از تابعی به نام minmax استفاده کنیم. این تابع به ما امکان می‌دهد که حداقل و حداکثر اندازه‌ی یک سطر یا ستون گرید را تعیین کنیم. به عبارت دیگر، تابع minmax تضمین می‌کند که اندازه‌ی ستون یا ردیف از مقدار مشخصی کمتر نباشد و از مقدار دیگری بیشتر نشود.

 Copy Icon CSS
.container{
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(2, minmax(3rem, auto));
  gap: 5px;
  width: 15rem;
}

به این ترتیب، سطرها دارای حداقل ارتفاع 3rem خواهند بود اما در صورت لزوم، می‌توانند بسط داده شوند تا محتوا را در بر بگیرند.

تعیین مکان آیتم‌های Grid

آیتم‌های گرید به طور خودکار با شروع از اولین ستون و اولین سطر، در گرید جای می‌گیرند. اما گزینه‌هایی وجود دارد که به ما امکان می‌دهد که تعیین مکان آیتم‌های گرید را به طور دلخواه انجام دهیم.

تعیین سطر و ستون آیتم

با استفاده از پراپرتی‌های grid-row و grid-column می‌توانیم رفتار پیش‌فرض آیتم‌های گرید از نظر قرارگیری در گرید را تغییر داده و ستون و سطر مشخصی را برای مکان یک آیتم تعیین کنیم. در مثال زیر، با استفاده از این دو پراپرتی ترتیبی داده شده که آیتم اول در سلول حاصل از برخورد سطر دوم و ستون سوم قرار بگیرد.

 Copy Icon CSS
.item1{
  background: skyblue;
  grid-row: 2;
  grid-column: 3;
}

با استفاده از چهار پراپرتی grid-row-start، grid-row-end، grid-column-start و grid-column-end می‌توانیم یک آیتم گرید را در بیش از یک سلول جای دهیم. این پراپرتی‌ها به شماره‌ی خطوط گرید ارجاع می‌دهند. برای اینکه یک آیتم، ستون‌های ۳ و ۴ را پوشش دهد، باید در خط 3 شروع و در خط 5 به پایان برسد. مانند مثال زیر:

 Copy Icon CSS
.item1{
  background: skyblue;
  grid-row: 2;
  grid-column-start: 3;
  grid-column-end: 5;
}

اما یک روش کوتاده‌تر هم برای پیاده‌سازی مثال بالا وجود دارد و آن این است که مثل کد زیر از پراپرتی grid-column به‌جای دو پراپرتی grid-column-start و grid-column-end استفاده کنیم.

 Copy Icon CSS
.item1{
  grid-row: 2;
  grid-column: 3/5;
}

همانطور که در مثال بالا هم می‌بینید، مقدار a / b برای پراپرتی grid-column به معنای انتخاب ستون a تا b-1 است. یک روش دیگر هم برای انتخاب ستون‌ها وجود دارد و آن استفاده از کلمه کلیدی span است. در این روش، مقدار a / span b به این معناست که ستون a و تعداد b-1 ستون بعد از آن انتخاب شوند.

 Copy Icon CSS
.item1{
  grid-row: 2;
  grid-column: 3 / span 2;
}

نام‌گذاری خطوط Grid

تا الان از اندیس عددی خطوط گرید برای ارجاع به آنها استفاده کردیم اما این امکان هم وجود دارد که نام‌هایی را به این خطوط اختصاص دهیم و برای ارجاع به آنها از نامشان استفاده کنیم. نام خطوط گرید در پراپرتی‌های grid-template-rows یا grid-template-columns تعیین می‌شود. این نام‌ها را باید درون براکت قرار داد.

 Copy Icon CSS
.container{
  display: grid;
  gap: 5px;
  width: 500px;
  grid-template-rows: [header-start] 2rem [content-start] 10rem [footer-start] 2rem [footer-end];
  grid-template-columns: [sidebar-start] 5rem [content-start] 1fr [content-end];
}

.container > div{
  background: lightgray;
}

.header{
  grid-row: header-start / content-start;
  grid-column: sidebar-start / content-end;
}

.footer{
  grid-column: sidebar-start / content-end;
}

نام‌گذاری ناحیه‌های Grid

همانند خطوط گرید، ناحیه‌های گرید (grid areas) را هم می‌توان نام‌گذاری کرد. این کار ما را قادر می‌کند که بدون نیاز به تعیین خطوط ابتدایی و انتهایی، آیتم‌های گرید را در ناحیه‌های دلخواه قرار دهیم. ناحیه‌ها با استفاده از پراپرتی grid-template-areas تعریف می‌شوند. اگر دو ناحیه‌ی مجاور، نام یکسانی داشته باشند، آیتم مورد نظر هر دو ناحیه را پوشش می‌دهد.

پراپرتی grid-template-areas می‌تواند به همراه پراپرتی‌های مربوط به تعیین سایز گرید که قبلاً دیدیم، به کار رود.

 Copy Icon CSS
.container{
  display: grid;
  grid-template-rows: 2rem 10rem 2rem;
  grid-template-columns: 5rem 1fr;
  grid-template-areas: 'header header header' 'sidebar content content' 'footer footer footer';
  gap: 5px;
  width: 500px;
}

تراز و فاصله‌بندی آیتم‌های Grid

Grid نیز مانند Flexbox به ما امکان می‌دهد که کنترل کاملی روی چینش و قرارگیری آیتم‌ها برای مواقعی که این آیتم‌ها کانتینر را پر نمی‌کنند، داشته باشیم. در این بخش، با تعدادی پراپرتی مربوط به این موضوع آشنا می‌شویم.

پراپرتی justify-items

وقتی درون یک سلول گرید فضای اضافی وجود داشته باشد، نحوه‌ی تراز آیتم در راستای محور سطری را می‌توان با استفاده از پراپرتی justify-items تعیین کرد. این پراپرتی روی کانتینر تعریف می‌شود و روی همه‌ی آیتم‌های گرید اعمال می‌شود. مقادیر قابل تخصیص به پراپرتی justify-items در جدول زیر آورده شده است.

مقدار توضیح مثال
stretch آیتم‌ها در امتداد محور سطری کشیده می‌شوند تا سلول را پر کنند. این مقدار پیش‌فرض پراپرتی justify-items است. پراپرتی justify-items با مقدار stretch
start آیتم‌ها در لبه‌ی ابتدایی سلول در راستای محور سطری قرار می‌گیرند. پراپرتی justify-items با مقدار start
end آیتم‌ها در لبه‌ی انتهایی سلول در راستای محور سطری قرار می‌گیرند. پراپرتی justify-items با مقدار end
center آیتم‌ها در راستای محور سطری در مرکز سلول خود قرار می‌گیرند. پراپرتی justify-items با مقدار center

پراپرتی align-items

نحوه‌ی قرارگیری آیتم‌ها در راستای محور ستونی با استفاده از پراپرتی align-items تعیین می‌شود. این پراپرتی نیز همانند پراپرتی justify-items روی کانتینر تنظیم می‌شود و روی همه‌ی آیتم‌ها اعمال می‌شود. جدول زیر شامل مقادیر قابل تخصیص به پراپرتی align-items است.

مقدار توضیح مثال
stretch آیتم‌ها در امتداد محور ستونی کشیده می‌شوند تا ارتفاع سلول را پر کنند. این مقدار پیش‌فرض پراپرتی align-items است. پراپرتی align-items با مقدار stretch
start آیتم‌ها در لبه‌ی بالایی سلول قرار می‌گیرند. پراپرتی align-items با مقدار start
end آیتم‌ها در لبه‌ی پایینی سلول قرار می‌گیرند. پراپرتی align-items با مقدار end
center آیتم‌ها در راستای محور ستونی در مرکز سلول خود قرار می‌گیرند. پراپرتی align-items با مقدار center

پراپرتی justify-content

اگر سطرها یا ستون‌های یک گرید با استفاده از واحدهای نسبی مانند fr سایزدهی نشده باشند، ممکن است با فضای خالی در گرید مواجه شویم. در این صورت، با استفاده از پراپرتی justify-content می‌توانیم تعیین کنیم که آیتم‌های گرید در راستای محور سطری چطور تراز شوند. مقادیر قابل تخصیص به این پراپرتی در جدول زیر آورده شده است.

مقدار مثال توضیح
start آیتم‌ها در ابتدای محور سطری قرار می‌گیرند. پراپرتی justify-content با مقدار start
end آیتم‌ها در انتهای محور سطری قرار می‌گیرند. پراپرتی justify-content با مقدار end
center آیتم‌ها در مرکز محور سطری قرار می‌گیرند. پراپرتی justify-content با مقدار center
stretch اگر ستون‌ها روی auto تنظیم شده باشند، کشیده می‌شوند تا محور سطری را پر کنند. پراپرتی justify-content با مقدار stretch
space-around فضای باقیمانده به نحوی تقسیم می‌شود که فاصله‌ی یکسانی بین ستون‌ها باشد و فاصله‌ای که در ابتدا و انتهای ستون‌هاست، نصف فاصله‌ی بین ستون‌ها باشد. پراپرتی justify-content با مقدار space-around
space-evenly بین ستون‌ها و همینطو.ر ابتدا و انتهای ستون‌ها فاصله‌ی یکسانی قرار می‌گیرد. پراپرتی justify-content با مقدار space-evenly
space-between اولین ستون به ابتدای کانتینر و آخرین ستون به انتهای کانتینر می‌چسبد و فضایم وجود به مساوات بین ستون‌های دیگر تقسیم می‌شود. پراپرتی justify-content با مقدار space-between

پراپرتی align-content

پراپرتی align-content مشابه پراپرتی justify-content است اما چیزی که تعیین می‌کند این است که سطرهای گرید چطور در راستای محور ستونی تراز شوند؛ کاری که پراپرتی justify-content عکسش را انجام می‌دهد. جدول زیر شامل لیست مقادیر مجاز برای پراپرتی align-content است.

مقدار توضیح مثال
start سطرهای گرید در ابتدای محور ستونی قرار می‌گیرند. پراپرتی align-content با مقدار start
end سطرهای گرید در انتهای محور ستونی قرار می‌گیرند. پراپرتی align-content با مقدار end
center سطرهای گرید در مرکز محور ستونی قرار می‌گیرند. پراپرتی align-content با مقدار center
stretch اگر سطرها روی auto تنظیم شده باشند، کشیده می‌شوند تا محور ستونی را پر کنند. پراپرتی align-content با مقدار stretch
space-around فضای باقیمانده به نحوی تقسیم می‌شود که فاصله‌ی یکسانی بین سطرها باشد و فاصله‌ای که در ابتدا و انتهای سطرهاست، نصف فاصله‌ی بین سطرها باشد. پراپرتی align-content با مقدار space-around
space-evenly بین سطرها و همینطو.ر ابتدا و انتهای سطرها فاصله‌ی یکسانی قرار می‌گیرد. پراپرتی align-content با مقدار space-evenly
space-between اولین سطر به بالای کانتینر و آخرین سطر به پایین کانتینر می‌چسبد و فضای موجود به مساوات بین سطرهای دیگر تقسیم می‌شود. پراپرتی align-content با مقدار space-between

پراپرتی‌های justify-self و align-delf

همانطور که دیدیم، پراپرتی‌های justify-items و align-items نحوه‌ی تراز آیتم‌های گرید را به‌ترتیب در راستای محور سطری و ستونی مشخص می‌کنند. اگر بخواهیم این تنظیمات را برای یک آیتم تغییر دهیم و اصطلاحاً مقدار آن پراپرتی را override کنیم، باید از پراپرتی‌های justify-self و align-self روی آیتم مورد نظر استفاده کنیم.

پراپرتی justify-self نحوه‌ی تراز یا قرارگیری یک آیتم در سلول خود را در راستای محور سطری تعیین می‌کند و پراپرتی align-self نحوه‌ی تراز یک آیتم درون سلولش را در راستای محور ستونی تعیین می‌کند.