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

فلکس‌باکس پیشرفته و حرکت نرم

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

در این فصل با این مباحث آشنا می‌شوید
  1. gap: فاصله بین آیتم‌ها
  2. رشد و کوچک شدن آیتم‌ها
  3. ترتیب نمایش
  4. align-self
  5. حرکت نرم با transition
  6. نمونه نهایی فصل

۱. gap: فاصله بین آیتم‌ها

در فصل قبل برای فاصله دادن به کارت‌ها از margin استفاده کردیم. این کار جواب می‌دهد اما یک عیب دارد: به لبه‌های بیرونی ظرف هم فاصله اضافه می‌کند و برای درست کردنش باید ترفندهایی بزنید. gap این مشکل را کاملاً حل می‌کند.

.container {
    display: flex;
    gap: 20px;                 /* فاصله یکسان بین همه آیتم‌ها */
}

.container2 {
    display: flex;
    flex-wrap: wrap;
    gap: 15px 30px;            /* فاصله بین سطرها، سپس بین ستون‌ها */
}

gap: نمونه 01-gap

شرح مثال

gap یا margin

از این پس برای فاصله دادن به آیتم‌های داخل یک ظرف فلکس، همیشه gap را انتخاب کنید. کد کوتاه‌تر می‌شود، نیازی به حذف margin آخرین آیتم ندارید و نتیجه دقیقاً همانی است که انتظار دارید. gap در گرید هم کار می‌کند و در فصل یازدهم بار دیگر می‌بینیمش.

۲. رشد و کوچک شدن آیتم‌ها

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

.container {
    display: flex;
    gap: 10px;
}

.sidebar {
    flex-basis: 250px;        /* اندازه شروع */
    flex-grow: 0;             /* رشد نکن */
    flex-shrink: 0;           /* کوچک هم نشو */
}

.content {
    flex-grow: 1;             /* تمام فضای باقی‌مانده را بگیر */
}

.item-a { flex-grow: 1; }
.item-b { flex-grow: 2; }     /* دو برابر item-a رشد می‌کند */

رشد و کوچک شدن: نمونه 02-flex-grow-shrink-basis

شرح مثال

ویژگیمعنیپیش‌فرض
flex-basis اندازه اولیه آیتم پیش از تقسیم فضای اضافه auto
flex-grow اگر فضای اضافه بود، چقدر از آن را بگیرد 0 یعنی رشد نکن
flex-shrink اگر فضا کم بود، چقدر کوچک شود 1 یعنی کوچک شو

flex-grow یک نسبت است، نه یک اندازه. اگر آیتم اول عدد ۱ و آیتم دوم عدد ۲ داشته باشد، فضای اضافه به نسبت یک به دو بینشان تقسیم می‌شود. اگر همه عدد ۱ بگیرند، فضا مساوی تقسیم می‌شود و همه هم‌عرض می‌شوند.

پرکاربردترین الگو

چیدمان «نوار کناری به‌علاوه محتوای اصلی» را با همین دو خط می‌سازید: به نوار کناری flex-basis ثابت و flex-shrink: 0 بدهید تا هرگز فشرده نشود، و به محتوای اصلی تنها flex-grow: 1 بدهید تا هر چه باقی ماند را بگیرد. دیگر لازم نیست هیچ درصدی حساب کنید.

نوشتار کوتاه

هر سه ویژگی را می‌شود در یک خط نوشت: flex: 1 0 250px; که به ترتیب یعنی grow، سپس shrink، سپس basis. نوشتن flex: 1; هم میان‌بر بسیار رایجی است و یعنی «رشد کن و فضای اضافه را بگیر».

۳. ترتیب نمایش

.item {
    order: 0;                 /* پیش‌فرض همه آیتم‌ها */
}

.first {
    order: -1;                /* برو اول همه */
}

.last {
    order: 10;                /* برو آخر همه */
}

ترتیب نمایش: نمونه‌های 03-order و 03-order-flags

شرح مثال

order ترتیب نمایش آیتم‌ها را عوض می‌کند، بدون اینکه ترتیبشان در فایل HTML تغییر کند. همه آیتم‌ها به طور پیش‌فرض عدد صفر دارند و مرورگر آنها را از کوچک به بزرگ مرتب می‌کند. آیتم‌هایی با عدد یکسان، به ترتیب نوشته شدنشان در HTML می‌مانند.

عدد منفی کاملاً مجاز است و ساده‌ترین راه فرستادن یک آیتم به ابتداست، بدون اینکه لازم باشد عدد بقیه را عوض کنید.

کاربرد واقعی این ویژگی

در فصل دوازدهم می‌بینید که روی موبایل گاهی می‌خواهیم ترتیب قسمت‌ها فرق کند. مثلاً روی دسکتاپ تصویر سمت راست باشد و روی موبایل تصویر بالای متن بیاید. با order این کار بدون دست زدن به HTML انجام می‌شود.

با احتیاط استفاده کنید

order تنها ترتیب دیداری را عوض می‌کند. صفحه‌خوان‌ها و کلید Tab همچنان ترتیب اصلی HTML را دنبال می‌کنند. اگر بسیار از آن استفاده کنید، تجربه کاربران نابینا و کسانی که با صفحه‌کلید کار می‌کنند به هم می‌ریزد.

۴. align-self

align-items که در فصل قبل دیدیم، روی ظرف نوشته می‌شود و همه آیتم‌ها را با هم جابه‌جا می‌کند. align-self همان کار را برای یک آیتم انجام می‌دهد.

.container {
    display: flex;
    align-items: center;        /* قانون کلی برای همه */
    height: 250px;
}

.special {
    align-self: flex-start;     /* استثنا: فقط این یکی بالا بماند */
}

.other {
    align-self: flex-end;       /* و این یکی پایین */
}

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

شرح مثال

مقدارهای align-self دقیقاً همان مقدارهای align-items هستند: flex-start، center، flex-end و stretch. تنها تفاوت این است که align-self روی آیتم نوشته می‌شود و قانون ظرف را برای همان آیتم نادیده می‌گیرد.

الگوی فکری این است: قانون کلی را روی ظرف بنویسید و استثناها را روی آیتم‌ها. این همان کاری است که همیشه در CSS بهترین نتیجه را می‌دهد؛ کد کوتاه می‌ماند و استثناها هم مشخص و خوانا هستند.

۵. حرکت نرم با transition

در فصل پنجم hover: را یاد گرفتیم، اما تغییر رنگ ناگهانی و پرشی اتفاق می‌افتاد. transition این تغییر را نرم و تدریجی می‌کند و ظاهر سایت را به شکل چشمگیری حرفه‌ای‌تر.

.btn {
    background-color: #2f4f4f;
    color: white;
    padding: 12px 28px;
    border-radius: 8px;
    transition: background-color 0.3s;
}

.btn:hover {
    background-color: #ff6347;
}

.card {
    border: 1px solid #dddddd;
    transition: all 0.3s ease;
}

.card:hover {
    border-color: #ff6347;
    box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
}

حرکت نرم: نمونه 05-hover-transition

شرح مثال

transition سه بخش دارد و معمولاً دو تای اول کافی است:

  1. چه چیزی. نام ویژگی‌ای که باید نرم تغییر کند، مانند background-color. اگر بنویسید all، هر چیزی که عوض شود نرم عوض می‌شود.
  2. چقدر طول بکشد. مانند 0.3s یعنی سه دهم ثانیه. واحد s ثانیه است و ms میلی‌ثانیه.
  3. با چه سرعتی. مانند ease که پیش‌فرض است: آرام شروع می‌شود، تند می‌شود و آرام تمام می‌شود. linear یعنی سرعت ثابت.
مهم‌ترین نکته transition

transition را روی حالت عادی بنویسید، نه روی hover:. اگر آن را داخل hover: بگذارید، رفتن نرم می‌شود اما برگشتن ناگهانی. نوشتنش در حالت عادی باعث می‌شود هر دو جهت نرم باشند.

زمان مناسب

بین ۰.۲ تا ۰.۴ ثانیه بهترین محدوده است. کمتر از آن دیده نمی‌شود و بیشتر از آن کاربر را منتظر می‌گذارد و حس کندی به سایت می‌دهد.

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

<body>

    <div class="layout">

        <aside class="sidebar">
            <h3>دسته‌بندی</h3>
            <p>وب</p>
            <p>شبکه</p>
            <p>گرافیک</p>
        </aside>

        <main class="content">
            <h2>دوره‌های ما</h2>

            <div class="cards">
                <div class="card">
                    <h3>طراحی وب</h3>
                    <p>پانزده جلسه</p>
                </div>
                <div class="card">
                    <h3>جاوااسکریپت</h3>
                    <p>بیست جلسه</p>
                </div>
                <div class="card featured">
                    <h3>دوره ویژه</h3>
                    <p>ثبت‌نام محدود</p>
                </div>
            </div>
        </main>

    </div>

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

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

/* چیدمان کلی: نوار کناری ثابت، محتوا کشسان */
.layout {
    display: flex;
    gap: 25px;
}

.sidebar {
    flex-basis: 220px;
    flex-shrink: 0;
    background-color: #2f4f4f;
    color: white;
    padding: 20px;
    border-radius: 10px;
}

.content {
    flex-grow: 1;
}

.content h2 {
    color: #2f4f4f;
    margin-bottom: 20px;
}

/* کارت‌ها */
.cards {
    display: flex;
    flex-wrap: wrap;
    gap: 20px;
    align-items: flex-start;
}

.card {
    flex-grow: 1;
    flex-basis: 200px;
    background-color: white;
    padding: 22px;
    border-radius: 10px;
    border: 1px solid #dddddd;
    transition: all 0.3s ease;
}

.card:hover {
    border-color: #ff6347;
    transform: translateY(-4px);
}

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

/* استثنا: کارت ویژه اول بیاید و کشیده شود */
.featured {
    order: -1;
    align-self: stretch;
    border-top: 4px solid #ff6347;
}

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

شرح مثال

این مثال یک چیدمان واقعی سایت است و هر پنج مفهوم فصل در آن نقش دارد:

در hover: کارت‌ها یک ویژگی تازه هم آمده است: transform: translateY(-4px) که کارت را چهار پیکسل به بالا می‌برد و حس «بلند شدن» می‌دهد. این ویژگی را در فصل سیزدهم کامل توضیح می‌دهیم.

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

پوشه 08-flexbox-advanced شامل نمونه‌های 01-gap تا 06-final-example.

خلاصه فصل

ویژگیروی چهکارش
gapظرففاصله بین آیتم‌ها، بدون فاصله لبه‌ها
flex-basisآیتماندازه اولیه
flex-growآیتمسهم از فضای اضافه، به صورت نسبت
flex-shrinkآیتماجازه کوچک شدن. صفر یعنی هرگز.
flex: 1آیتممیان‌بر رایج برای رشد کردن
orderآیتمترتیب نمایش. منفی هم مجاز است.
align-selfآیتماستثنا زدن به align-items ظرف
transitionهر عنصرنرم کردن تغییر. در حالت عادی بنویسید.

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

  1. چیدمان نوار کناری و محتوا را بسازید، طوری که با تغییر عرض پنجره تنها محتوا کم و بسیار شود.
  2. سه دکمه بسازید که رنگ و اندازه‌شان با transition نرم عوض شود.
  3. در یک فهرست پنج‌تایی، با order کاری کنید آخرین مورد اول نمایش داده شود.
  4. یک ظرف با align-items: center بسازید و یک آیتم را با align-self استثنا کنید.
  5. یک بار transition را داخل hover: بنویسید و ببینید چرا برگشت ناگهانی می‌شود.
  6. مقدار gap را از ۵ تا ۵۰ پیکسل عوض کنید و بهترین حالت را برای طرح خودتان پیدا کنید.
فصل قبل: فلکس‌باکس فصل بعد: موقعیت‌دهی و سرریز