طراحی وب با HTML و CSS فهرست مطالب
فصل ۷

فلکس‌باکس: چیدمان مدرن

تا اینجا هر جعبه زیر جعبه قبلی می‌رفت و کاری از دستمان برنمی‌آمد. فلکس‌باکس این را تغییر می‌دهد و کنترل کامل چیدمان را به ما می‌دهد.

در این فصل با این مباحث آشنا می‌شوید
  1. مشکلی که فلکس‌باکس حل می‌کند
  2. جهت محور
  3. justify-content
  4. align-items
  5. flex-wrap
  6. نمونه نهایی فصل

۱. مشکلی که فلکس‌باکس حل می‌کند

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

فلکس‌باکس روش امروزی و درست این کار است. با یک خط شروع می‌شود:

<div class="container">
    <div class="item">یک</div>
    <div class="item">دو</div>
    <div class="item">سه</div>
</div>
.container {
    display: flex;
}

.item {
    background-color: #2f4f4f;
    color: white;
    padding: 20px;
}

اولین فلکس: نمونه 01-display-flex-intro

شرح مثال

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

مهم‌ترین جمله این فصل

هر ویژگی فلکس یا مال ظرف است یا مال آیتم. اگر ویژگی را اشتباهی جای دیگری بنویسید، هیچ اتفاقی نمی‌افتد. تمام ویژگی‌های این فصل مال ظرف هستند.

۲. جهت محور

در فلکس‌باکس دو محور داریم و همه چیز حول این دو می‌چرخد:

.row {
    display: flex;
    flex-direction: row;              /* پیش‌فرض: کنار هم */
}

.column {
    display: flex;
    flex-direction: column;           /* زیر هم */
}

.row-reverse {
    display: flex;
    flex-direction: row-reverse;      /* کنار هم، برعکس */
}

جهت محور: نمونه 02-flex-direction

شرح مثال

مقدارمحور اصلینتیجه
rowافقیپیش‌فرض. آیتم‌ها کنار هم.
columnعمودیآیتم‌ها زیر هم.
row-reverseافقی، معکوسترتیب آیتم‌ها برعکس می‌شود.
column-reverseعمودی، معکوسآخرین آیتم بالا می‌آید.
نکته مهم در صفحه‌های راست‌چین

در صفحه‌ای که dir="rtl" دارد، محور اصلی از راست شروع می‌شود. یعنی با row اولین آیتم سمت راست قرار می‌گیرد، نه سمت چپ. این دقیقاً همان چیزی است که برای فارسی می‌خواهیم و یکی از دلایلی است که نوشتن dir="rtl" در تگ html اینقدر مهم است.

نکته کلیدی برای فهم بقیه فصل: وقتی flex-direction را عوض می‌کنید، معنی دو ویژگی بعدی هم عوض می‌شود. چون آنها به «محور اصلی» و «محور عرضی» کار دارند، نه به «افقی» و «عمودی».

۳. justify-content

این ویژگی آیتم‌ها را در امتداد محور اصلی جابه‌جا می‌کند. در حالت پیش‌فرض که row است، یعنی به صورت افقی.

.start {
    display: flex;
    justify-content: flex-start;      /* پیش‌فرض */
}

.center {
    display: flex;
    justify-content: center;
}

.end {
    display: flex;
    justify-content: flex-end;
}

.between {
    display: flex;
    justify-content: space-between;
}

.around {
    display: flex;
    justify-content: space-around;
}

justify-content: نمونه 03-justify-content

شرح مثال

مقدارنتیجه
flex-start همه آیتم‌ها در ابتدای محور. در صفحه راست‌چین یعنی سمت راست.
center همه آیتم‌ها وسط ظرف، چسبیده به هم.
flex-end همه آیتم‌ها انتهای محور. در صفحه راست‌چین یعنی سمت چپ.
space-between اولی کاملاً ابتدا، آخری کاملاً انتها، بقیه فضا بینشان تقسیم می‌شود.
space-around دور هر آیتم فضای مساوی. فاصله بین دو آیتم دو برابر فاصله لبه‌هاست.
پرکاربردترین حالت واقعی

space-between پرکاربردترین مقدار در طراحی سایت است. هر سربرگی که لوگو در یک طرف و منو در طرف دیگر دارد، با همین یک خط ساخته می‌شود. در فصل چهاردهم دقیقاً همین کار را می‌کنیم.

۴. align-items

این ویژگی آیتم‌ها را در امتداد محور عرضی جابه‌جا می‌کند. وقتی جهت row است، یعنی به صورت عمودی.

.box {
    display: flex;
    height: 300px;
}

.stretch {
    align-items: stretch;             /* پیش‌فرض */
}

.top {
    align-items: flex-start;
}

.middle {
    align-items: center;
}

.bottom {
    align-items: flex-end;
}

align-items: نمونه 04-align-items

شرح مثال

مقدارنتیجه در حالت row
stretch پیش‌فرض. همه آیتم‌ها کشیده می‌شوند تا هم‌ارتفاع ظرف شوند.
flex-startهمه به بالا می‌چسبند.
centerهمه در وسط ارتفاع قرار می‌گیرند.
flex-endهمه به پایین می‌چسبند.

مقدار پیش‌فرض stretch بسیار مفید است: اگر سه کارت با متن‌های به‌طول متفاوت داشته باشید، هر سه خودکار هم‌ارتفاع می‌شوند و طرح مرتب می‌ماند. پیش از فلکس‌باکس، انجام این کار واقعاً سخت بود.

وسط‌چین کردن کامل، بالاخره

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

.perfect-center {
    display: flex;
    justify-content: center;    /* وسط افقی */
    align-items: center;        /* وسط عمودی */
    height: 100vh;              /* ارتفاع کل پنجره */
}

وسط‌چین کامل با سه خط

واحد vh یعنی درصدی از ارتفاع پنجره مرورگر. 100vh یعنی «به اندازه کل ارتفاع صفحه نمایش». این واحد را در فصل دوازدهم کامل بررسی می‌کنیم.

۵. flex-wrap

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

.no-wrap {
    display: flex;
    flex-wrap: nowrap;                /* پیش‌فرض */
}

.wrap {
    display: flex;
    flex-wrap: wrap;
}

.card {
    width: 300px;
    padding: 20px;
    background-color: white;
}

flex-wrap: نمونه 05-flex-wrap

شرح مثال

یک عادت خوب

هر وقت فلکس‌باکس را برای چیدن چند کارت یا محصول به کار می‌برید، تقریباً همیشه flex-wrap: wrap را هم بنویسید. همین یک خط باعث می‌شود صفحه روی موبایل هم قابل استفاده بماند و کارت‌ها به جای فشرده شدن، زیر هم بروند. این ساده‌ترین قدم به سمت طراحی واکنش‌گراست، بدون اینکه هنوز حتی یک media query نوشته باشیم.

۶. نمونه نهایی فصل

<body>

    <header class="site-header">
        <div class="logo">کادوس</div>
        <nav class="menu">
            <a href="#">خانه</a>
            <a href="#">دوره‌ها</a>
            <a href="#">تماس</a>
        </nav>
    </header>

    <section class="hero">
        <h1>آموزش طراحی وب</h1>
    </section>

    <section class="cards">
        <div class="card">
            <h3>HTML</h3>
            <p>ساختار صفحه</p>
        </div>
        <div class="card">
            <h3>CSS</h3>
            <p>ظاهر صفحه و چیدمان آن</p>
        </div>
        <div class="card">
            <h3>JavaScript</h3>
            <p>رفتار صفحه</p>
        </div>
    </section>

</body>
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-family: Tahoma, sans-serif;
}

body {
    background-color: #f5f5f5;
    line-height: 1.9;
}

/* سربرگ: لوگو یک طرف، منو طرف دیگر */
.site-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    background-color: #2f4f4f;
    padding: 15px 30px;
}

.logo {
    color: white;
    font-size: 20px;
    font-weight: bold;
}

.menu {
    display: flex;
}

.menu a {
    color: white;
    text-decoration: none;
    margin-right: 20px;
}

.menu a:hover {
    color: #ff6347;
}

/* هدر بزرگ: متن دقیقاً وسط */
.hero {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 300px;
    background-color: #223a3a;
    color: white;
}

/* کارت‌ها: کنار هم و در موبایل زیر هم */
.cards {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    padding: 40px 20px;
}

.card {
    width: 280px;
    background-color: white;
    padding: 25px;
    margin: 10px;
    border-radius: 10px;
    border-top: 4px solid #ff6347;
}

.card h3 {
    color: #2f4f4f;
    margin-bottom: 10px;
}

نمونه نهایی فصل: نمونه 06-final-example

شرح مثال

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

  1. سربرگ. space-between لوگو را به یک انتها و منو را به انتهای دیگر می‌فرستد. align-items: center هم باعث می‌شود لوگو و منو در ارتفاع سربرگ هم‌تراز باشند، حتی با اینکه اندازه‌هایشان فرق دارد.
  2. منو. خودش هم یک ظرف فلکس جداگانه است تا سه لینک کنار هم بنشینند. پس یک عنصر می‌تواند هم‌زمان آیتم ظرف بالاتر و ظرف آیتم‌های پایین‌تر باشد.
  3. هدر بزرگ. همان الگوی وسط‌چین کامل با سه خط، که عنوان را دقیقاً در مرکز مستطیل قرار می‌دهد.
  4. بخش کارت‌ها. ترکیب wrap و center. روی صفحه بزرگ هر سه کارت کنار هم و وسط‌چین‌اند. پنجره را که باریک کنید، کارت سوم به خط بعد می‌رود و بار دیگر وسط می‌ماند.

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

فایل‌های تمرینی این فصل

پوشه 07-flexbox شامل نمونه‌های 01-display-flex-intro تا 06-final-example.

خلاصه فصل

ویژگیروی چهکارش
display: flexظرففعال کردن فلکس‌باکس
flex-directionظرفجهت محور اصلی: row یا column
justify-contentظرفچیدمان در محور اصلی
align-itemsظرفچیدمان در محور عرضی
flex-wrap: wrapظرفاجازه رفتن به خط بعد

تمرین‌های فصل هفت

  1. یک سربرگ بسازید که لوگو در یک سمت و سه لینک در سمت دیگر باشد.
  2. یک جعبه به ارتفاع کل صفحه بسازید و یک متن را دقیقاً در مرکز آن قرار دهید.
  3. شش کارت بسازید و با flex-wrap کاری کنید که با باریک شدن پنجره، خودشان مرتب زیر هم بروند.
  4. هر پنج مقدار justify-content را روی یک ظرف امتحان کنید و تفاوتشان را یادداشت کنید.
  5. سه کارت با متن‌های کوتاه و بلند بسازید و ببینید align-items: stretch چگونه هر سه را هم‌ارتفاع می‌کند.
فصل قبل: متن‌آرایی فصل بعد: فلکس‌باکس پیشرفته