توسعه فرانت‌اند

Flexbox: راهنمای عملی با مثال‌های واقعی

راهنمای Flexbox با والد و فرزند، grow و shrink، RTL و Overflow؛ نمونه کامل نوار ابزار، سه کارت و Footer همراه روش اجرا.

1404/11/21 3 دقیقه مطالعه 2,094 بازدید

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

شروع عملی این است که Container، فرزند مستقیم و محور اصلی را مشخص کنید. بیشتر خطاهای ابتدایی از نسبت دادن یک property به عنصر نامناسب می‌آیند. display:flex روی والد، فرزندان مستقیم را Flex Item می‌کند؛ نوه‌های آن خودکار همان آیتم‌ها نیستند. اگر دکمه داخل یک wrapper است، رفتار wrapper با رفتار دکمه یکی نیست. قبل از تغییر چند property، ساختار HTML را بخوانید و مشخص کنید کدام عنصر باید فضا بگیرد یا جمع شود.

محور اصلی را با جهت نوشتار ببینید

مفاهیم پایه Flexbox در MDN محور اصلی و محور متقاطع را توضیح می‌دهد. flex-direction مشخص می‌کند توزیع اصلی در جهت row یا column باشد. justify-content روی محور اصلی عمل می‌کند و align-items روی محور متقاطع. بنابراین center همیشه به معنی مرکز افقی نیست؛ در column، محور اصلی مسیر عمودی دارد. اگر این رابطه روشن باشد، تغییر جهت به آزمون‌وخطای propertyها تبدیل نمی‌شود.

در متن RTL، row از ابتدای inline شروع می‌شود که معمولاً سمت راست است. row-reverse را فقط برای فارسی بودن اضافه نکنید، چون ممکن است جهت را دوباره معکوس کنید. از مفهوم start و end و propertyهای منطقی استفاده کنید تا کد به چپ و راست فیزیکی وابسته نماند. ترتیب HTML باید ترتیب معنی‌دار محتوا را نگه دارد. ناوبری فارسی نباید با یک وارونگی بصری، مسیر خواندن ابزار کمکی یا حرکت صفحه‌کلید را از ظاهر جدا کند.

توزیع فضا با اندازه محتوا فرق دارد

justify-content فقط وقتی فضای آزاد مربوط وجود دارد اثر مورد انتظار را دارد. اگر آیتم‌ها همه فضای محور را گرفته‌اند، space-between ممکن است تفاوتی نشان ندهد. برای یک کنترل در انتهای ردیف، Auto Margin می‌تواند نقش مشخص‌تری داشته باشد. gap فاصله میان آیتم‌ها را تعریف می‌کند و مانند padding دور Container نیست. ترکیب gap، padding و توزیع فضای آزاد باید آگاهانه باشد تا فاصله‌ها در عرض‌های مختلف غیرقابل پیش‌بینی نشوند.

align-items:stretch می‌تواند آیتم‌ها را در محور متقاطع کش بدهد، اما همه محتوای داخلی آن‌ها را خودکار هم‌تراز نمی‌کند. در کارت‌های با متن متفاوت، جای دکمه ممکن است همچنان تغییر کند. یک کارت column و Auto Margin برای بخش اقدام می‌تواند این رابطه را روشن کند. هم‌ارتفاع بودن کارت و قرار گرفتن همه دکمه‌ها در یک خط، دو نیاز مرتبط اما متفاوت‌اند. برای هر کدام باید Container و بخش مسئول را مشخص کنید.

flex-grow، flex-shrink و flex-basis را جدا بفهمید

مرجع flex shorthand و ارتباط سه بخش را توضیح می‌دهد. basis اندازه پایه در محاسبه محور اصلی است، grow سهم رشد در فضای آزاد مثبت و shrink سهم جمع شدن در کمبود فضا را تعیین می‌کند. یک مقدار عددی برای grow به تنهایی عرض نهایی را تضمین نمی‌کند، چون basis و محدودیت‌های محتوا هم اثر دارند. برای آموزش بهتر است ابتدا هر سه مقدار را صریح بنویسید.

در نمونه کارت‌ها، flex:1 1 18rem یعنی اندازه پایه ۱۸rem و امکان رشد و جمع شدن وجود دارد. این قرارداد تعداد ستون ثابت را تضمین نمی‌کند. تعداد آیتم‌ها در هر ردیف با عرض ظرف و فاصله‌ها تعیین می‌شود. اگر دقیقاً سه ستون هم‌اندازه با رابطه دو بعدی لازم است، Grid را بررسی کنید. مقاله Grid و Flexbox درباره این انتخاب توضیح بیشتری دارد؛ استفاده از wrap، مدل Flexbox را به Grid تبدیل نمی‌کند.

محدودیت ذاتی محتوا را در Overflow ببینید

یک رشته بلند، جدول یا قطعه کد می‌تواند آیتم را از اندازه مورد انتظار بزرگ‌تر نگه دارد. اضافه کردن flex-shrink همیشه کافی نیست، چون حداقل اندازه خودکار هم نقش دارد. min-inline-size:0 روی آیتم مناسب می‌تواند امکان جمع شدن را فراهم کند. سپس رفتار خود محتوا را تعیین کنید: متن شکسته شود، Scroll داشته باشد یا با روش دیگری نمایش داده شود. پنهان کردن Overflow بدون تصمیم درباره اطلاعات ضروری، فقط مشکل را از دید خارج می‌کند.

برای نام محصول بلند، شکستن کلمه شاید مناسب باشد؛ برای شماره حساب یا کد، حذف بخشی از متن ممکن است خطرناک باشد. اگر Ellipsis استفاده می‌کنید، مسیر مشاهده مقدار کامل وجود داشته باشد. مقاله جدول داده درباره نمایش داده بلند زمینه بیشتری دارد. مسئله را با نمونه محتوای واقعی بررسی کنید، نه فقط با سه عنوان هم‌اندازه. Layout باید بتواند تفاوت طول فارسی و انگلیسی را بدون خروج کنترل‌ها از صفحه تحمل کند.

نمونه کامل: نوار ابزار، سه کارت و Footer

فایل زیر را flex-demo.html ذخیره و مستقیم در مرورگر باز کنید. همه HTML و CSS لازم در همان فایل هستند و وابستگی خارجی وجود ندارد. نمونه سه کارت با متن‌های متفاوت دارد. نوار ابزار می‌تواند Wrap شود، کارت‌ها بر اساس فضای موجود ردیف تازه می‌سازند و هر کارت درون خودش column است. Footer در محتوای کوتاه نزدیک انتهای viewport قرار می‌گیرد و در محتوای بلند پس از محتوا می‌آید؛ Fixed نیست و روی متن نمی‌افتد.

<!doctype html><html lang="fa" dir="rtl"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>نمونه Flexbox</title><style>
*{box-sizing:border-box}body{margin:0;min-height:100svh;display:flex;flex-direction:column;font:1rem/1.8 Tahoma,sans-serif;color:#111;background:#f6f6f6}header,main,footer{padding:1rem}header,footer{background:#fff}main{flex:1;width:100%;max-width:72rem;margin-inline:auto}.toolbar{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:1rem}.toolbar h1{margin:0;font-size:1.5rem}nav{display:flex;flex-wrap:wrap;gap:1rem}a{color:#111;text-decoration:underline}a:focus-visible{outline:3px solid #111;outline-offset:4px}.cards{display:flex;flex-wrap:wrap;gap:1rem;margin-block:2rem}.card{flex:1 1 18rem;min-inline-size:0;display:flex;flex-direction:column;padding:1.5rem;border:2px solid #111;border-radius:.8rem;background:#fff}.card h2{margin-block:0 1rem}.card p{overflow-wrap:anywhere}.actions{margin-block-start:auto;padding-block-start:1rem}.request{padding:1rem;border:2px solid #111;background:#fff}
</style></head><body><header class="toolbar"><h1>مسیرهای طراحی</h1><nav aria-label="ناوبری نمونه"><a href="#cards">کارت‌ها</a><a href="#request">درخواست</a></nav></header><main><section class="cards" id="cards" aria-label="سه کارت آموزشی"><article class="card"><h2>ساختار</h2><p>والد و فرزند مستقیم را مشخص کنید.</p><div class="actions"><a href="#request">انتخاب ساختار</a></div></article><article class="card"><h2>محتوای بلند</h2><p>این کارت توضیح بلندتری دارد تا رابطه محتوای داخلی و بخش اقدام دیده شود. چیدمان باید با تغییر طول متن هم قابل استفاده بماند.</p><div class="actions"><a href="#request">انتخاب محتوا</a></div></article><article class="card"><h2>محدودیت اندازه</h2><p>شناسه آموزشی بلند: example-long-content-without-normal-spaces-for-layout-review</p><div class="actions"><a href="#request">انتخاب اندازه</a></div></article></section><section class="request" id="request"><h2>بخش درخواست نمونه</h2><p>این صفحه داده‌ای دریافت یا ارسال نمی‌کند؛ لینک‌ها برای حرکت داخل فایل هستند.</p></section></main><footer>Footer پس از محتوا قرار می‌گیرد و Fixed نیست.</footer></body></html>

در toolbar، عنوان و nav فرزندان مستقیم هستند و gap فاصله میانشان را تعریف می‌کند. nav خودش Container جدا برای لینک‌ها است. کارت‌ها فرزندان مستقیم cards هستند و اندازه پایه آن‌ها با flex تعیین می‌شود. داخل هر کارت، actions با margin-block-start:auto فضای باقی‌مانده را مصرف می‌کند تا اقدام از متن فاصله بگیرد. این رفتار به column بودن کارت وابسته است؛ برداشتن display:flex از card بدون تغییر روش هم‌ترازی، قرارداد داخلی نمونه را عوض می‌کند.

body یک Container عمودی با حداقل ارتفاع viewport است و main فضای باقی‌مانده را می‌گیرد. این الگو برای Footer پس از محتوای کوتاه کاربرد دارد، اما به معنی چسباندن Footer به صفحه در همه Scrollها نیست. در عرض کم، کنترل‌ها جمع می‌شوند و هر کارت می‌تواند تمام فضای موجود را بگیرد. تعداد ردیف‌ها نتیجه عرض و محتوای همان نمونه است و با یک عدد ثابت معرفی نشده. لینک‌های کارت به بخش درخواست داخل همان فایل می‌روند؛ مقصد ساختگی بیرونی ندارند.

Wrap و ترتیب را با محتوا هماهنگ کنید

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

راهنمای ترتیب آیتم‌ها درباره تفاوت ترتیب بصری و منبع توضیح دارد. order و جهت reverse لزوماً ترتیب Tab یا خواندن را مطابق ظاهر تغییر نمی‌دهند. برای یک فرم یا جریان آموزشی، این اختلاف می‌تواند گیج‌کننده باشد. ترتیب معنی‌دار را در HTML نگه دارید و تغییر بصری را محدود به جایی کنید که کار و فهم کاربر آسیب نمی‌بیند. انتقال اقدام اصلی به ابتدا با CSS، جای اصلاح ساختار محتوا را نمی‌گیرد.

به جای breakpointهای زیاد، محدودیت را مشخص کنید

یک Layout منعطف باید بداند چه چیزی اجازه جمع شدن دارد و چه چیزی حداقل فضای قابل استفاده می‌خواهد. در نوار ابزار، دکمه خیلی باریک نباید متن را ناخوانا کند؛ Wrap می‌تواند راه مناسب‌تری باشد. در کارت، تصویر و متن ممکن است نیاز متفاوتی داشته باشند. breakpoint را برای تغییر معنی‌دار رابطه تعیین کنید، نه برای رفع هر برخورد اتفاقی. اگر چند قاعده فقط برای یک عنوان بلند اضافه شده‌اند، ابتدا محدودیت محتوا و min-size را بررسی کنید.

دسترسی‌پذیری از همین تصمیم‌ها اثر می‌گیرد. Zoom و تغییر اندازه فونت می‌توانند Wrap را زودتر ایجاد کنند و نباید کنترل مهم حذف شود. Focus باید پس از تغییر چیدمان همچنان دیده شود. مقاله Color Contrast برای کنترل‌های نوار ابزار مفید است. برای کارت کلیک‌پذیر هم از Link واقعی استفاده کنید؛ Flexbox فقط چیدمان را تعیین می‌کند و نام، نقش و رفتار تعاملی عنصر را به جای شما تعریف نمی‌کند.

کد را با قرارداد قابل تحویل نگه دارید

در بازبینی، رابطه والد و فرزند، محور، اندازه پایه و محدودیت محتوا را کنار هم بنویسید. اگر همکار بعدی wrapper تازه اضافه کند، ممکن است آیتم Flex تغییر کند؛ توضیح این رابطه از حفظ چند property مفیدتر است. CSS مشترک را برای نقش واقعی جزء تعریف کنید. مقاله Atomic Design درباره ارتباط جزء و صفحه کمک می‌کند، اما یک class عمومی مثل flex به تنهایی قرارداد Component کامل نیست.

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

واکنش به این مقاله

اشتراک‌گذاری این مقاله:
دیدگاه‌ها 0
۰ / ۲۰۰۰

هنوز دیدگاهی ثبت نشده

اولین نفری باشید که نظر می‌دهد!