برای انتخاب CSS Grid یا Flexbox، رابطه عناصر را نگاه کنید. اگر ترتیب در یک محور و توزیع فضای همان محور مهم است، Flexbox معمولاً نقطه شروع مناسبی است. اگر ستونها و ردیفها باید یک ساختار مشترک بسازند، Grid به این رابطه نزدیکتر است. مقایسه رسمی MDN همین تفاوت بنیادی را توضیح میدهد. با این حال، قاعده «Flexbox برای component و Grid برای صفحه» محدودکننده است؛ هر دو میتوانند در اندازه کوچک یا بزرگ استفاده شوند و در یک رابط کنار هم کار کنند.
یک محور و دو محور را عملی ببینید
در Flexbox، یک container جهت اصلی دارد و آیتمها در همان مسیر قرار میگیرند. اگر wrap فعال شود، چند خط ایجاد میشود، اما هر خط فضای خودش را توزیع میکند. این موضوع برای مجموعه دکمه یا tag مفید است، چون طول آیتمها متفاوت است و الزاماً قرار نیست ستونهای خطها با هم تراز باشند. اگر سه ستون ثابت میخواهید که در چند ردیف همراستا بمانند، Grid ساختار مستقیمتری میدهد. تفاوت را از رفتار محتوا بفهمید و نه از ظاهر یک ردیف خالی.
Grid trackهای ردیف و ستون را تعریف میکند و آیتمها در آن ساختار قرار میگیرند. میتوانید تعداد ستون را مشخص کنید یا اجازه دهید بر اساس فضای موجود ساخته شوند. این ابزار برای فهرست محصول مناسب است، اما میتواند داخل یک کارت هم به کار رود؛ مثلاً وقتی label و مقدارها باید در چند ردیف تراز شوند. اندازه component دلیل انتخاب نیست. مسئله این است که آیا رابطه دوبعدی مشترکی دارید یا فقط توزیع و ترتیب در یک محور لازم است.
نمونه کامل با هر دو ابزار
فایل زیر را با نام layout-demo.html ذخیره کنید و در مرورگر باز کنید. وابستگی، تصویر و JavaScript ندارد. شش کارت با Grid در فهرست قرار میگیرند و بخش اقدام هر کارت با Flexbox، دکمه و وضعیت را کنار هم میگذارد. در عرض کم تعداد ستونهای فهرست کاهش مییابد و در صورت کمبود فضا، اقدامها wrap میشوند. همه classهای CSS در HTML وجود دارند. نمونه نشان میدهد انتخاب دو ابزار میتواند در دو سطح مستقل یک صفحه انجام شود، بدون اینکه یکی را برای کل پروژه اجباری کنیم.
<!doctype html>
<html lang="fa" dir="rtl">
<head>
<meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1">
<title>Grid و Flexbox</title>
<style>
*{box-sizing:border-box}body{font-family:sans-serif;line-height:1.8;margin:0;padding:1rem;background:#f3f6fa;color:#172333}
main{max-width:70rem;margin-inline:auto}.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,16rem),1fr));gap:1rem}
.card{padding:1rem;background:#fff;border:1px solid #becbdd;border-radius:.5rem;min-width:0}.card h2{font-size:1.15rem}
.actions{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:.75rem}.status{font-size:.9rem}
button{font:inherit;padding:.35rem .75rem;background:#174b8c;color:#fff;border:0;border-radius:.3rem}:focus-visible{outline:3px solid #914200;outline-offset:3px}
</style>
</head>
<body><main><h1>فهرست پروژهها</h1><div class="cards">
<article class="card"><h2>فرم درخواست</h2><p>بازبینی متن و مسیر ارسال.</p><div class="actions"><span class="status">در حال انجام</span><button type="button">مشاهده</button></div></article>
<article class="card"><h2>صفحه محصول</h2><p>تکمیل مشخصات و شرایط تحویل.</p><div class="actions"><span class="status">آماده بازبینی</span><button type="button">مشاهده</button></div></article>
<article class="card"><h2>راهنمای خدمات</h2><p>هماهنگی عنوانها و لینکها.</p><div class="actions"><span class="status">در حال انجام</span><button type="button">مشاهده</button></div></article>
<article class="card"><h2>تنظیمات حساب</h2><p>طراحی حالت خطا و موفقیت.</p><div class="actions"><span class="status">در انتظار</span><button type="button">مشاهده</button></div></article>
<article class="card"><h2>جدول گزارش</h2><p>مرتبسازی و نمایش ستونها.</p><div class="actions"><span class="status">در حال انجام</span><button type="button">مشاهده</button></div></article>
<article class="card"><h2>صفحه معرفی</h2><p>تأیید محتوا و اطلاعات تماس.</p><div class="actions"><span class="status">آماده بازبینی</span><button type="button">مشاهده</button></div></article>
</div><p>دکمهها در این نمونه نمایشیاند و عملیاتی انجام نمیدهند.</p></main></body>
</html>
کلاس cards همان Grid Container است و هر article با کلاس card آیتم مستقیم آن است. قاعده repeat با auto-fit و minmax تعداد ستون متناسب با فضا را میسازد. حداقل عرض با min ترکیب شده تا در viewport بسیار باریک، حداقل ثابت از عرض container بزرگتر نشود. شش کارت در markup داریم و تعداد آنها با توضیح برابر است. اگر عنوان طولانیتر شود، متن باید در ستون خودش بشکند. استفاده از minmax در اینجا به مدیریت فضای واقعی کمک میکند و جای بررسی محتوا را نمیگیرد.
کلاس actions یک Flex Container جداست. فرزندان مستقیمش وضعیت و button هستند و فاصله میان آنها با gap تعریف شده است. flex-wrap اجازه میدهد وقتی جا کم است، آیتم به خط بعد برود. دکمههای نمونه فقط نمایش نقشاند و عملیات انجام نمیدهند؛ برای محصول باید رفتار واقعی و حالتهایش را اضافه کنید. CSS این بخش روی کارتهای بیرونی اثر layout ندارد. این جداسازی کمک میکند هنگام اصلاح، بدانید هدف تغییر تعداد ستون است یا ترتیب اقدام داخل کارت.
Flexbox برای فضای باقیمانده
در یک نوار ابزار، ممکن است عنوان، جستوجو و چند اقدام داشته باشید. Flexbox میتواند فضای باقیمانده را بین بخشها توزیع کند و alignment را سادهتر سازد. flex-grow و flex-shrink روی اندازه آیتمها اثر دارند و flex-basis مبنای محاسبه را تعیین میکند. این سه را بدون توضیح به یک مقدار جادویی تبدیل نکنید. اگر input باید رشد کند ولی دکمه اندازه محتوا داشته باشد، قواعد هر دو را جدا بنویسید. رابطه فرزند مستقیم با container در این تصمیم مهم است.
آیتم Flex ممکن است به دلیل min-size پیشفرض کوچکتر از محتوای خودش نشود. برای بخش متنی که باید در فضای محدود بشکند یا اسکرول داشته باشد، min-width:0 میتواند لازم باشد. این تنظیم را بر اساس رفتار انتخاب کنید؛ آن را بیهدف روی همه عناصر نپاشید. نام فایل طولانی یا URL نمونه مناسبی برای دیدن محدودیت است. اگر فقط متن کوتاه میگذارید، اشکال پنهان میماند و بعد در داده واقعی ظاهر میشود. layout باید ظرفیت محتوا را در نظر بگیرد.
justify-content و align-items به محورهای container مربوطاند. وقتی flex-direction عوض میشود، معنی دیداری این دو هم تغییر میکند. در متن RTL، شروع و پایان محور را با قرارداد جهت بخوانید و از فرض ثابت راست و چپ پرهیز کنید. خاصیتهای logical مانند margin-inline میتوانند قصد را روشنتر کنند. مقاله راهنمای عملی Flexbox برای ادامه بررسی این حالتها مناسب است. حفظ نام محور در توضیح از یادگیری چند ترکیب تصادفی مفیدتر است.
Grid برای track و تراز مشترک
اگر چند آیتم باید مرز ستون مشترک داشته باشند، trackها را تعریف کنید. مقدار fr سهمی از فضای در دسترس را نشان میدهد، اما اندازه محتوا و حداقلها هم در نتیجه دخالت دارند. برای ستون منعطف، minmax(0,1fr) در بعضی ساختارها جلوی محدودیت محتوا را میگیرد. ستون دارای label کوتاه ممکن است اندازه محتوا بخواهد و بخش توضیح سهم باقیمانده را بگیرد. انتخاب را با داده واقعی انجام دهید، نه فقط با این تصور که همه ستونها باید برابر باشند.
Template Areas میتوانند ساختار بخشهای صفحه را خواناتر کنند. نام area باید به نقش اشاره کند و عنصر متناظر داشته باشد. اگر نسخه کوچک ترتیب متفاوتی میخواهد، مراقب باشید تغییر ظاهر، ترتیب منطقی document را مخدوش نکند. Grid جای طراحی semantics را نمیگیرد. در یک صفحه اطلاعاتی، heading و navigation باید معنی خود را حفظ کنند. راهنمای ساختار صفحه W3C درباره همین جهتیابی توضیح میدهد. رابطه visual و DOM باید عمداً طراحی شود.
auto-fit و auto-fill رفتار یکسانی درباره trackهای خالی ندارند. برای انتخاب، ببینید با تعداد کم آیتم چه فضایی میخواهید. شاید کارتها باید فضای باقیمانده را بگیرند و شاید ستونهای خالی باید ساختار را حفظ کنند. مثال با یک یا دو آیتم این تفاوت را آشکار میکند. اگر فقط یک فهرست پر را میبینید، نتیجه هر دو ممکن است شبیه به نظر برسد. تعداد عناصر یکی از حالتهای مهم layout است و نباید همیشه ثابت فرض شود.
ترتیب محتوا را برای ظاهر قربانی نکنید
order در Flexbox و placement در Grid میتوانند ترتیب دیداری را عوض کنند. صفحهکلید و فناوری کمکی ممکن است همچنان ترتیب DOM را دنبال کنند. اگر کاربر از عنوان به کنترل نامرتبط میرسد، تصویر درست صفحه کافی نیست. ابتدا ترتیب منطقی محتوا را در HTML بسازید و بعد ظاهر را با آن هماهنگ کنید. اگر تفاوت اجتنابناپذیر است، مسیر تعامل را دقیق بررسی کنید. تغییر چیدمان نباید اطلاعات مهم را فقط به جای دوری ببرد که از جریان خواندن خارج است.
برای فرم، label و input باید ارتباط روشن داشته باشند، حتی اگر در Grid دو ستون قرار گرفتهاند. در نسخه کوچک، یکستونهشدن ممکن است مناسب باشد و ساختار معنایی باید باقی بماند. مقاله طراحی فرم وب ادامه این بحث را پوشش میدهد. layout یک لایه از تجربه است و اعتبارسنجی، خطا و focus لایههای دیگرند. نمیتوان با یک display:grid رفتار کامل فرم را ساخت یا با تغییر ابزار layout همه مشکلات آن را حل کرد.
Responsive را به نیاز عنصر وصل کنید
Breakpoint باید از جایی بیاید که محتوا دیگر به شکل مناسب جا نمیشود. عددهای متداول میتوانند شروع باشند، اما قانون محصول نیستند. اگر component در چند بخش صفحه استفاده میشود، Container Query ممکن است از Media Query مناسبتر باشد. مقاله CSS و Container Queries نمونه کامل این مسیر را دارد. Grid و Flexbox همچنان چیدمان را انجام میدهند؛ Query شرط فعالشدن یک قاعده را تعیین میکند. این مسئولیتها را از هم جدا بخوانید.
در نسخه کوچک، اطلاعات را صرفاً برای جاگرفتن حذف نکنید. شاید به wrap، اسکرول محدود یا ترتیب مناسبتری نیاز باشد. جدول داده را هم بدون فکر به کارت تبدیل نکنید، چون مقایسه میان ردیفها ممکن است دشوار شود. برای متن فارسی، طول عبارت و ترکیب شناسه انگلیسی را در نظر بگیرید. ارتفاع ثابت کارت فقط برای تراز ظاهری میتواند متن را پنهان کند. هدف این است که چیدمان به محتوا خدمت کند و در حالتهای مختلف قابل خواندن بماند.
انتخاب و عیبیابی را ساده نگه دارید
وقتی layout مشکل دارد، نخست container و فرزند مستقیم را پیدا کنید. قاعدهای که روی یک wrapper اشتباه آمده ممکن است هیچ اثری بر آیتم مورد نظر نگذارد. سپس اندازه، gap و حداقل محتوا را ببینید. اضافهکردن marginهای جبرانی متعدد معمولاً علت را پنهان میکند. دلیل هر سطح layout را در نام class یا یادداشت کوتاه حفظ کنید. ابزار DevTools میتواند ساختار track و محور را نشان دهد، اما فهم رابطه عناصر باید از HTML و CSS شما روشن باشد.
برای تصمیم بعدی، یک جمله درباره رابطه لازم بنویسید: «این آیتمها در یک محور فضای باقیمانده را تقسیم میکنند» یا «این ردیفها باید ستون مشترک داشته باشند». سپس ابزار مناسب را انتخاب کنید و با تعداد و طول محتوای متفاوت فکر کنید. اگر دو سطح نیاز متفاوت دارند، هر دو ابزار را به کار ببرید؛ همانطور که در نمونه، Grid فهرست و Flexbox اقدامها را مدیریت میکند. چنین توضیحی از قاعده ثابت component در برابر صفحه دقیقتر است و نگهداری انتخاب را برای تیم آسانتر میکند.
هنوز دیدگاهی ثبت نشده
اولین نفری باشید که نظر میدهد!