در درس قبل با 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 برای ارجاع به
مکانهای مورد نظر در یک گرید از روش شمارهگذاری زیر برای خطوط گرید استفاده میشود.
البته این امکان هم وجود دارد که به ترتیب عکس به خطوط گرید ارجاع دهیم. در این صورت، شمارهگذاری از گوشهی
پایین سمت راست و با مقدار -1 شروع میشود.
شمارهگذاری منفی یک مزیت مهم دارد و آن این است که میتوانیم برای ارجاع به آخرین خط، بدون توجه به تعداد خطوط،
از -1 استفاده کنیم.
ناحیههای Grid
یک عنصر میتواند درون یک خانه از گرید قرار گیرد و یا اینکه در یک ناحیهی گرید (grid area) متشکل از چند حانه
قرار گیرد. شکل زیر یک ناحیهی گرید متشکل از دو سطر و دو ستون را هایلایت کرده است. توجه داشته باشید که
ناحیهی گرید باید مستطیلشکل باشد و ما نمیتوانیم مثلاً یک ناحیهی گرید به شکل L داشته باشیم.
تعریف Grid
برای ایجاد سطرها و ستونهای یک گرید از دو پراپرتی با نامهای grid-template-rows و grid-template-columns
استفاده میشود که بهترتیب، برای تعیین عرض سطرها و ارتفاع ستونهای گرید کاربرد دارند. برای ایجاد فاصله بین
آیتمهای گرید هم میتوانیم از پراپرتی gap استفاده کنیم.
در این مثال، ما یک گرید ایجاد کردهایم که متشکل از دو ستون به اندازهی 10rem و دو سطر به ارتفاع 5rem است. به
این ترتیب، ما الان دو سطر و دو ستون داریم که منجر به ایجاد چهار سلول میشوند و چهار آیتم را در این کانتینر
قرار دادهایم که به طور خودکار، هر کدام در یک سلول قرار میگیرند. حالا اجازه دهید ببینیم چه اتفاقی رخ میدهد
اگر آیتمهای بیشتری به این کانتینر اضافه کنیم.
اگر این کد را اجرا کنید، خواهید دید که آیتمهای 5 و 6 به گرید اضافه شدهاند. اما گرید ما فقط 4 سلول داشت، پس
2 سلول اضافی چطور ساخته شده و آیتمها را در بر گرفتهاند؟ در پاسخ این سوال، با مفهوم گریدهای ضمنی و صریح
مواجه میشویم.
گرید صریح (explicit grid) به طور مستقیم توسط ما و با استفاده از پراپرتیهای grid-template-columns و
grid-template-rows ایجاد میشود. اما گرید ضمنی (implicit grid) توسط مرورگر و در زمانی ساخته میشود که تعداد
سلولهای گرید صریحی که تعریف کردهایم از تعداد آیتمهای گرید کمتر باشد. در این صورت، خود مرورگر سطرها و
ستونهایی را به گرید اضافه میکند. پس، سطرها و ستونهایی که ما تعریف میکنیم، یک گرید صریح را میسازد و
سطرها و ستونهای اضافهشده توسط مرورگر، یک گرید ضمنی را شکل میدهد.
سایز آیتمهای یک گرید ضمنی در حالت پیشفرض از روی محتوای آیتمها تعیین میشود اما این رفتار پیشفرض را
میتوان با استفاده از پراپرتی grid-auto-rows کنترل کرد. مثال زیر را ببینید.
برای تعیین سایز گرید میتوانیم از هر یک از واحدهای طولی مانند px، em و rem و یا حتی درصد استفاده کنیم. اما
CSS Grid یک واحد جدید با نام fr را نیز معرفی کرده که یک واحد کسری (fractional) است که به کسر یا نسبتی از
فضای خالی اشاره میکند. برای مثال، اگر چهار ستون داشته باشیم که همگی دارای سایز 1fr باشند، هر ستون 25% از
فضای موجود را به خود اختصاص میدهد. مثال زیر را ببینید.
در اینجا سایز هر یک از ستونها برابر با 1fr است و این به این معناست که فضای موجود به نسبت مساوی بین ستونها
تقسیم میشود. اگر ستون وسطی را به 2fr تغییر دهیم، نسبت به دو ستون دیگر دو برابر میشود.
تابع repeat
گاهی اوقات در تعیین سایز گرید، ناگزیر از تکرار مقادیر هستیم. مثلاً برای تخصیص مقدار یکسان 1fr به چهار ستون
یک
گرید، داریم:
CSS
grid-template-columns: 1fr 1fr 1fr 1fr;
در اینگونه موارد میتوانیم از تابعی به نام repeat استفاده کنیم:
CSS
grid-template-columns: repeat(4, 1fr);
تابع minmax
اگر از یک سایز ثابت برای یک سطر استفاده کنیم و محتوای یک سلول در آن جا نشود، مانند مثال زیر، سرریز یا
overflow رخ میدهد.
برای حل این مشکل، میتوانیم از تابعی به نام minmax استفاده کنیم. این تابع به ما امکان میدهد که حداقل و
حداکثر اندازهی یک سطر یا ستون گرید را تعیین کنیم. به عبارت دیگر، تابع minmax تضمین میکند که اندازهی ستون
یا ردیف از مقدار مشخصی کمتر نباشد و از مقدار دیگری بیشتر نشود.
به این ترتیب، سطرها دارای حداقل ارتفاع 3rem خواهند بود اما در صورت لزوم، میتوانند بسط داده شوند تا محتوا را
در بر بگیرند.
تعیین مکان آیتمهای Grid
آیتمهای گرید به طور خودکار با شروع از اولین ستون و اولین سطر، در گرید جای میگیرند. اما گزینههایی وجود
دارد که به ما امکان میدهد که تعیین مکان آیتمهای گرید را به طور دلخواه انجام دهیم.
تعیین سطر و ستون آیتم
با استفاده از پراپرتیهای grid-row و grid-column میتوانیم رفتار پیشفرض آیتمهای گرید از نظر قرارگیری در
گرید را تغییر داده و ستون و سطر مشخصی را برای مکان یک آیتم تعیین کنیم. در مثال زیر، با استفاده از این دو
پراپرتی ترتیبی داده شده که آیتم اول در سلول حاصل از برخورد سطر دوم و ستون سوم قرار بگیرد.
با استفاده از چهار پراپرتی grid-row-start، grid-row-end، grid-column-start و grid-column-end میتوانیم یک
آیتم گرید را در بیش از یک سلول جای دهیم. این پراپرتیها به شمارهی خطوط گرید ارجاع میدهند. برای اینکه یک
آیتم، ستونهای ۳ و ۴ را پوشش دهد، باید در خط 3 شروع و در خط 5 به پایان برسد. مانند مثال زیر:
اما یک روش کوتادهتر هم برای پیادهسازی مثال بالا وجود دارد و آن این است که مثل کد زیر از پراپرتی
grid-column بهجای دو پراپرتی grid-column-start و grid-column-end استفاده کنیم.
CSS
.item1{grid-row: 2;grid-column: 3/5;}
همانطور که در مثال بالا هم میبینید، مقدار a / b برای پراپرتی grid-column به معنای انتخاب ستون a تا b-1 است.
یک روش دیگر هم برای انتخاب ستونها وجود دارد و آن استفاده از کلمه کلیدی span است. در این روش، مقدار a / span
b به این معناست که ستون a و تعداد b-1 ستون بعد از آن انتخاب شوند.
CSS
.item1{grid-row: 2;grid-column: 3 / span 2;}
نامگذاری خطوط Grid
تا الان از اندیس عددی خطوط گرید برای ارجاع به آنها استفاده کردیم اما این امکان هم وجود دارد که نامهایی را
به این خطوط اختصاص دهیم و برای ارجاع به آنها از نامشان استفاده کنیم. نام خطوط گرید در پراپرتیهای
grid-template-rows یا grid-template-columns تعیین میشود. این نامها را باید درون براکت قرار داد.
همانند خطوط گرید، ناحیههای گرید (grid areas) را هم میتوان نامگذاری کرد. این کار ما را قادر میکند که
بدون نیاز به تعیین خطوط ابتدایی و انتهایی، آیتمهای گرید را در ناحیههای دلخواه قرار دهیم. ناحیهها با
استفاده از پراپرتی grid-template-areas تعریف میشوند. اگر دو ناحیهی مجاور، نام یکسانی داشته باشند، آیتم
مورد نظر هر دو ناحیه را پوشش میدهد.
پراپرتی grid-template-areas میتواند به همراه پراپرتیهای مربوط به تعیین سایز گرید که قبلاً دیدیم، به کار
رود.
Grid نیز مانند Flexbox به ما امکان میدهد که کنترل کاملی روی چینش و قرارگیری آیتمها برای مواقعی که این
آیتمها کانتینر را پر نمیکنند، داشته باشیم. در این بخش، با تعدادی پراپرتی مربوط به این موضوع آشنا
میشویم.
پراپرتی justify-items
وقتی درون یک سلول گرید فضای اضافی وجود داشته باشد، نحوهی تراز آیتم در راستای محور سطری را میتوان با
استفاده از پراپرتی justify-items تعیین کرد. این پراپرتی روی کانتینر تعریف میشود و روی همهی آیتمهای گرید
اعمال میشود. مقادیر قابل تخصیص به پراپرتی justify-items در جدول زیر آورده شده است.
مقدار
توضیح
مثال
stretch
آیتمها در امتداد محور سطری کشیده میشوند تا سلول را پر کنند. این مقدار پیشفرض پراپرتی
justify-items است.
start
آیتمها در لبهی ابتدایی سلول در راستای محور سطری قرار میگیرند.
end
آیتمها در لبهی انتهایی سلول در راستای محور سطری قرار میگیرند.
center
آیتمها در راستای محور سطری در مرکز سلول خود قرار میگیرند.
پراپرتی align-items
نحوهی قرارگیری آیتمها در راستای محور ستونی با استفاده از پراپرتی align-items تعیین میشود. این پراپرتی
نیز همانند پراپرتی justify-items روی کانتینر تنظیم میشود و روی همهی آیتمها اعمال میشود. جدول زیر شامل
مقادیر قابل تخصیص به پراپرتی align-items است.
مقدار
توضیح
مثال
stretch
آیتمها در امتداد محور ستونی کشیده میشوند تا ارتفاع سلول را پر کنند. این مقدار پیشفرض پراپرتی
align-items است.
start
آیتمها در لبهی بالایی سلول قرار میگیرند.
end
آیتمها در لبهی پایینی سلول قرار میگیرند.
center
آیتمها در راستای محور ستونی در مرکز سلول خود قرار میگیرند.
پراپرتی justify-content
اگر سطرها یا ستونهای یک گرید با استفاده از واحدهای نسبی مانند fr سایزدهی نشده باشند، ممکن است با فضای
خالی در گرید مواجه شویم. در این صورت، با استفاده از پراپرتی justify-content میتوانیم تعیین کنیم که
آیتمهای گرید در راستای محور سطری چطور تراز شوند. مقادیر قابل تخصیص به این پراپرتی در جدول زیر آورده شده
است.
مقدار
مثال
توضیح
start
آیتمها در ابتدای محور سطری قرار میگیرند.
end
آیتمها در انتهای محور سطری قرار میگیرند.
center
آیتمها در مرکز محور سطری قرار میگیرند.
stretch
اگر ستونها روی auto تنظیم شده باشند، کشیده میشوند تا محور سطری را پر کنند.
space-around
فضای باقیمانده به نحوی تقسیم میشود که فاصلهی یکسانی بین ستونها باشد و فاصلهای که در ابتدا و
انتهای ستونهاست، نصف فاصلهی بین ستونها باشد.
space-evenly
بین ستونها و همینطو.ر ابتدا و انتهای ستونها فاصلهی یکسانی قرار میگیرد.
space-between
اولین ستون به ابتدای کانتینر و آخرین ستون به انتهای کانتینر میچسبد و فضایم وجود به مساوات بین
ستونهای دیگر تقسیم میشود.
پراپرتی align-content
پراپرتی align-content مشابه پراپرتی justify-content است اما چیزی که تعیین میکند این است که سطرهای گرید
چطور در راستای محور ستونی تراز شوند؛ کاری که پراپرتی justify-content عکسش را انجام میدهد. جدول زیر شامل
لیست مقادیر مجاز برای پراپرتی align-content است.
مقدار
توضیح
مثال
start
سطرهای گرید در ابتدای محور ستونی قرار میگیرند.
end
سطرهای گرید در انتهای محور ستونی قرار میگیرند.
center
سطرهای گرید در مرکز محور ستونی قرار میگیرند.
stretch
اگر سطرها روی auto تنظیم شده باشند، کشیده میشوند تا محور ستونی را پر کنند.
space-around
فضای باقیمانده به نحوی تقسیم میشود که فاصلهی یکسانی بین سطرها باشد و فاصلهای که در ابتدا و انتهای
سطرهاست، نصف فاصلهی بین سطرها باشد.
space-evenly
بین سطرها و همینطو.ر ابتدا و انتهای سطرها فاصلهی یکسانی قرار میگیرد.
space-between
اولین سطر به بالای کانتینر و آخرین سطر به پایین کانتینر میچسبد و فضای موجود به مساوات بین سطرهای
دیگر تقسیم میشود.
پراپرتیهای justify-self و align-delf
همانطور که دیدیم، پراپرتیهای justify-items و align-items نحوهی تراز آیتمهای گرید را بهترتیب در راستای
محور سطری و ستونی مشخص میکنند. اگر بخواهیم این تنظیمات را برای یک آیتم تغییر دهیم و اصطلاحاً مقدار آن
پراپرتی را override کنیم، باید از پراپرتیهای justify-self و align-self روی آیتم مورد نظر استفاده کنیم.
پراپرتی justify-self نحوهی تراز یا قرارگیری یک آیتم در سلول خود را در راستای محور سطری تعیین میکند و
پراپرتی align-self نحوهی تراز یک آیتم درون سلولش را در راستای محور ستونی تعیین میکند.