اهمیت آموزش flexbox در css نسخه ۳ بر کسی پوشیده نیست. FlexBox، ابزاری است که با تکبعدی دیدن المانها، کمک میکند تا آیتمهای یک صفحهی وب را به آسانی، با سرعت بالا و به صورت واکنشگرا طراحی کنیم. مرورگرهای مختلفی FlexBox را پشتیبانی کرده و این موجب شده تا توسعهدهندگان زیادی علاقهمند به استفاده از این ابزار مفید و کاربری باشند. همچنین در مورد مزایای استفاده از FlexBox صحبت کردیم و در آخر با دو مثال، کدنویسی آن را شروع کردیم. حال در این مقاله قصد داریم تخصصیتر به آموزش FlexBox بپردازیم.
Flex Container
همانطور که در طراحی صفحه با CSS Grid، المانها در یک Grid مادر با نام Container قرار میگیرند، در FlexBox نیز یک المان نگهدارنده با عنوان flex-container داریم:
.flex-container {
display: flex;
background-color: DodgerBlue;
}
.flex-container > div {
background-color: #f1f1f1;
margin: 50px;
padding: 50px;
font-size: 30px;
}
<div class="flex-container">
<div>1</div>
<div>2</div>
<div>3</div>
</div>
در این شکل نگهدارنده یا Container مشخص شده است:
خواص نگهدارنده (Flex Container)
در FlexBox، مجموعهای از ویژگیها بهگونهای تعریف شدهاند که تنها به نگهدارنده نسبت داده میشوند. این خواص عبارتند از:
- display
- flex Direction
- flex flow
- justify content
- align content
- align items
در ادامهی مقالهی آموزش FlexBox هر کدام از این ویژگیها را توضیح میدهیم.
Display
در این قسمت آموزش FlexBox به توضیح ویژگی Display در فلکس باکس میپردازیم.
همانطور که در شکل زیر میبینید، بهصورت پیش فرض همه divها display: block هستند و به همین دلیل هر div، کل عرض صفحه را گرفته و موجب میشود که divهای بعدی به پایین رفته و در کنار یکدیگر قرار نگیرند:
برای شروع کار با Flexbox، باید نگهدارندهی مورد نظر خود را بهصورت Flexbox درآوریم. برای تعریف یک نگهدارنده از نوع FlexBox باید مقدار display را معلوم کنیم که از نوع flex یا inline-flex باشد:
.flex-container {
display: flex | inline-flex;
}
در این حالت المانها دیگر تمامی عرض صفحه را اشغال نکرده و در کنار یکدیگر بهصورت inline قرار میگیرند. شاید این تغییر ساده بهنظر برسد اما در حقیقت ما در پشت صحنه چیزی قدرتمند را فعال کردهایم.
Flex Direction
در این قسمت آموزش FlexBox به توضیح ویژگی Flex Direction در فلکس باکس میپردازیم.
نگهدارنده یا Container در FlexBox دارای دو محور است:
- main axis : محور اصلی
- cross axis : محور متقاطع
این محورها بهصورت پیشفرض در اولین تصویر این مقاله و در بخش نگهدارنده مشخص شدهاند.
در شکل بخش قبل، دیدیم که هنگامی که display را برابر با flex قرار میدهیم، همه divها افقی و از سمت چپ به راست کنار همدیگر قرار گرفتند. این نحوهی قرارگیری به این علت است که بهصورت پیشفرض آیتمها در طول محور اصلی یا Main axis از سمت چپ به راست قرار میگیرند و تزاربندی میشوند.
با استفاده از ویژگی Flex-direction میتوان محور main axis و حالت پیشفرض را تغییر داد. در حالت پیشفرض، مقدار این ویژگی row هست اما با تغییر مقدار این ویژگی به column داریم:
همانطور که در شکل مشخص شده، هنگامی که این ویژگی را به column تغییر میدهیم، divها عمودی و از بالا به پایین قرار میگیرند. نکتهای که در اینجا باید به آن توجه داشت این است که با قرار دادن مقدار column برای این ویژگی، المانها در جهت cross axis قرار نمیگیرند؛ این مقدار، باعث شده تا جای محورهای main و cross عوض شده و به همین دلیل است که المانها عمودی میشوند. مقادیر دیگری نیز برای ویژگی flex-direction وجود دارد؛ از جمله:
- row-reverse : باعث شده تا المانها از راست به چپ قرار بگیرند.
- column-reverse : باعث شده تا المانها از پایین به بالا قرار بگیرند.
.flex-container {
display: flex;
flex-direction: row | column | column-reverse | row-reverse;
}
در تصویر زیر تفاوت بین column و column-reverse قابل مشاهده است:
Flex wrap
در این قسمت آموزش FlexBox به توضیح ویژگی Flex wrap در فلکس باکس میپردازیم.
همانطور که در بخشهای قبل دیدیم، بهصورت پیشفرض تمامی المانها در یک خط قرار میگیرند. با استفاده از خاصیت flex-wrap میتوان تعیین کرد که هرکدام از المانها در چند خط قرار بگیرند که به هر یک از این خطها flex line میگویند.
- nowrap: (پیشفرض) آیتمها در یک خط و در کنار هم قرار میگیرند.
- wrap: آیتمها در چند خط قرار میگیرند. در صفحات rtl از راست به چپ و در صفحات ltr از چپ به راست قرار میگیرند.
- wrap-reverse: این مقدار معکوس مقدار wrap است.
.flex-container{
display: flex;
flex-wrap: nowrap | wrap | wrap-reverse;
}
Flex flow
در این قسمت آموزش FlexBox به توضیح ویژگی Flex flow در فلکس باکس میپردازیم.
میتوان دو مقدار flex-direction و flex-wrap را با استفاده از این مقدار تنظیم کرد. مقدار پیشفرض آن row nowrap است.
.flex-container {
display: flex;
flex-flow: row wrap; /* flex-direction || flex-wrap */
}
Justify content
در این قسمت آموزش FlexBox به توضیح ویژگی Justify content در فلکس باکس میپردازیم.
با استفاده از این ویژگی میتوان نحوهی ترازبندی المانها بر روی محور اصلی یا Main axis را کنترل کرد. در اینجا تفاوتهای میان Main و Cross axis واضحتر است. این ویژگی ۵ مقدار اصلی را قبول میکند:
- Flex-start : مقدار پیشفرض هست و باعث شده تا المانها در ابتدای محور اصلی قرار بگیرند. اگر مقدار flex-direction برابر با row باشد، پس از قرار دادن مقدار flex-start برای ویژگی justify-content، تمامی divها در سمت چپ ترازبندی میشوند.
- Flex-end : تمامی المانها در سمت راست ترازبندی میشوند.
- Center : المانها در وسط قرار میگیرند.
- Space-between : میان تمامی المانها فضای یکسان قرار داده میشود. توجه داشته باشید که در ابتدا و انتها، فضایی قرار نمیگیرد.
- Space-around : تقاوت این مورد با مورد قبل در این هست که به ابتدا و انتها هم فضا اضافه خواهد شد.
.flex-container {
display: flex;
justify-content: flex-start | flex-end | center | space-between | space-around;
}
Align content
در این قسمت آموزش FlexBox به توضیح ویژگی Align content در فلکس باکس میپردازیم.
این خاصیت هنگامی که flex container دارای فضای بیشتر از flex line هاست، میتواند نحوهی چینش آنها را تعیین کند. مقادیر خاصیت align-content برابر مقادیر خاصیت justify-content میباشد و تنها یک مقدار بیشتر از justify-align دارد. این مقادیر عبارتند از:
- flex-start: با این مقدار flex lineها در ابتدای flex container جمع میشوند.
- flex-end: با این مقدار flex lineها در انتهای flex container جمع میشوند.
- center: با این مقدار flex lineها در وسط flex container جمع میشوند.
- space-between: فضای خالی به طور مساوی بین flex lineها توزیع میشود. خط اولی در ابتدا و خط آخری در انتهای flex container قرار میگیرد.
- space-around: فضای خالی به طور مساوی بین flex lineها تقسیم میشود.
- stretch: (پیشفرض) flex lineها کشیده میشوند و فضای خالی را پر میکنند.
.container {
display: flex;
align-content: flex-start | flex-end | center | space-between | space-around | stretch;
}
Align items
در این قسمت آموزش FlexBox به توضیح ویژگی Align items در فلکس باکس میپردازیم.
اگر ویژگی justify-content را به خوبی متوجه شده باشید، با این ویژگی هم مشکلی نخواهید داشت. این خاصیت بسیار شبیه به justify-content است. justify-content، المانها را بر اساس محور اصلی یا Main axis و ویژگی align-items، المانها را بر اساس Cross axis ترازبندی میکند. مقادیری که align-items عبارتند از:
- flex-start: آیتمها در نقطه شروع عرضی(cross start) قرار میگیرند.
- flex-end: آیتمها در نقطه اتمام عرضی (cross end) قرار میگیرند.
- center: آیتمها در وسط flex line قرار میگیرند.
- baseline: آیتمها با توجه به خطهایشان همتراز میشوند.
- stretch: (پیشفرض) در صورتی که ارتفاع(height) آیتمها مشخص نشده باشد، آیتمها کشیده میشوند و flex line را پر میکنند.
.flex-container {
display: flex;
align-items: flex-start | flex-end | center | baseline | stretch;
}
برای مثال، اگر بخواهیم المانی را در راستای عمودی وسط چین کنیم، داریم:
html, body {
height: 100%;
margin: 0;
}
body {
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
display: -webkit-flex;
display: flex;
}
در این کد با استفاده از ویژگیها و خصوصیات Flexbox کاری کردیم که محتویات درون body بهصورت وسط چین قرار داده شوند. برای اینکار در ابتدا display را برابر با flex و ترازبندیها را هم برابر با center یا مرکز قرار داده و Vendor Prefixها را برای پشتیبانی بیشتر گذاشتیم.
نکته مربوط به مقدار Stretch
اگر بخواهیم مقدار Stretch عمل کرده و المان مورد نظر تمامی فضای Cross axis را اشغال کند، دو راه داریم:
- از ویژگی height برای المانهای مورد نظر استفاده نکنیم.
- در صورت استفاده از height، مقدارش را برابر با auto قرار بدهیم. توجه داشته باشید که اگر ویژگی height را برای المان مورد نظر تعریف کنیم، مقدار stretch را بازنویسی (override) خواهد کرد و در این صورت المان تمامی فضا را اشغال نمیکند.
نکته مربوط به مقدار baseline
زمانی که مقدار ویژگی را برابر با baseline قرار میدهیم، المانها طوری تنظیم میشوند که پایین پاراگراف درون div ها، در یک خط قرار گرفته و تراز شود. اگر درون divها پاراگرافی وجود نداشته باشد، divها نسبت به موقعیت پایین خودشان تراز خواهند شد. مانند شکل زیر:
Flex Item
در این قسمت آموزش FlexBox به توضیح ویژگی Flex Item در فلکس باکس میپردازیم.
به المانهایی که درون نگهدارنده و بهعنوان فرزند قرار میگیرند Flex Item گفته میشود. برای Flex شدن فرزندان کافی است مانند کد زیر در تگ HTML آنها را درون یک div نگهدارنده قرار دهیم و نیازی به تعریف کلاس خاصی در استایل نیست:
<div class="flex-container">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
</div>
البته توجه داشته باشید که آیتمها هم مانند نگهدارنده، دارای ویژگیهای مخصوص به خود هستند که در بخشهای بعدی مقالهی آموزش FlexBox آنها را مرور خواهیم کرد.
خواص فرزندان (Flex Items)
همانطور که گفتیم در FlexBox، مجموعهای از ویژگیها بهگونهای تعریف شدهاند که تنها به فرزندان نسبت داده میشوند. این خواص عبارتند از:
- order
- flex grow
- و flex shrink
- flex basis
- flex
- align self
در ادامه هر کدام از این ویژگیها را توضیح میدهیم.
Order
در این قسمت آموزش FlexBox به توضیح ویژگی Order در فلکس باکس میپردازیم.
این مقدار میتواند مکان قرارگیری آیتم در کنار دیگر آیتمها را مشخص کند. مقدار پیشفرض ۰ است. اگر تنها مقدار order یکی از آیتمها تعیین شود، آن آیتم بعد از تمامی آیتمها قرار میگیرد؛ ولی اگر این خاصیت برای همهی آیتمها تعریف شود، میتوان جایگاه قرارگیری آیتمها را مشخص کرد. این خاصیت یکی از کاربردیترین خاصیتها هنگام طراحی واکنشگرا (responsive) هست. برای مقداردهی order میتوان برای هر آیتم در استایل کلاس جداگانه تعریف کرد یا به صورت مستقیم در HTML آن را همانند زیر مشخص نمود:
<div class="flex-container">
<div style="order: 3">1</div>
<div style="order: 2">2</div>
<div style="order: 4">3</div>
<div style="order: 1">4</div>
</div>
Flex grow
در این قسمت آموزش FlexBox به توضیح ویژگی Flex grow در فلکس باکس میپردازیم.
این خاصیت توانایی بزرگ شدن یک آیتم را تعیین میکند. flex-grow یک مقدار عددی بدون واحد میپذیرد. مقدار پیشفرض آن ۰ است؛ یعنی آیتمها توانایی بزرگ شدن را ندارند. در صورتی که flex container یا نگهدارنده فضای خالی داشته باشد و به یک آیتم flex-grow: 1 بدهید، آن آیتم تا جایی بزرگ میشود که فضای خالی درون نگهدارنده از بین برود.
دقت داشته باشید که هنگامی که خاصیت flex-direction نگهدارنده برابر با row باشد، flex-grow بر عرض (width) آیتم اعمال شده و اگر مقدار آن خاصیت برابر column باشد، flex-grow بر ارتفاع (height) اعمال میشود.
<div class="flex-container">
<div style="flex-grow: 1">1</div>
<div style="flex-grow: 1">2</div>
<div style="flex-grow: 8">3</div>
<div style="flex-grow: 1">4</div>
</div>
اگر به همه ی فلکس آیتمها flex-grow: 1; بدهید، همهی آنها به یک اندازه بزرگ میشوند. اگر در همین حالت مقدار flex-grow یکی از آیتم هارا ۲ قرار دهید، آن آیتم ۲ برابر دیگر آیتم خواهد شد.
Flex shrink
در این قسمت آموزش FlexBox به توضیح ویژگی Flex shrink در فلکس باکس میپردازیم.
این خاصیت توانایی کوچک شدن یک آیتم را در صورت لزوم تعیین میکند. مقدار پیشفرض آن ۱ است، یعنی آیتمها میتوانند کوچک شوند. اگر خاصیت flex-wrap نگهدارنده برابر nowrap باشد، آیتمها تا زمانی که عرضشان به ۰ برسد کوچک میشوند:
حال اگر در این صورت مقدار flex-shrink یکی از آیتمها را برابر ۲ قرار دهیم، آن آیتم ۲ برابر دیگر آیتمها کوچک میشود.
نمونهی کد:
<div class="flex-container">
<div>1</div>
<div>2</div>
<div style="flex-shrink: 0">3</div>
<div>4</div>
</div>
Flex basis
در این قسمت آموزش FlexBox به توضیح ویژگی Flex basis در فلکس باکس میپردازیم.
این خاصیت مقدار پایهی عرض یا ارتفاع آیتم را تعیین میکند. یعنی عرض یا ارتفاع (به ستونی یا ردیفی بودن آیتمها بستگی دارد) از این مقدار پایه نمیتواند کمتر شود. این خاصیت مانند min-height و min-width عمل میکند. مقدار پیشفرض این خاصیت auto میباشد، یعنی فلکس آیتمها میتوانند تا جایی کوچک شوند که عرض یا ارتفاع آنها به صفر برسد.
<div class="flex-container">
<div>1</div>
<div>2</div>
<div style="flex-basis: 200px">3</div>
<div>4</div>
</div>
Flex
در این قسمت آموزش FlexBox به توضیح ویژگی Flex در فلکس باکس میپردازیم.
این خاصیت در واقع یک امکان برای مختصر نویسی برای خاصیتهای flex-grow ، flex-shrink و flex-basis میباشد. در کد زیر مقادیر flex به ترتیب در کامنت مشخص شده است. مقادیر دوم و سوم (flex-shrink و flex-basis) اختیاری هستند.
<div class="flex-container">
<div>1</div>
<div>2</div>
<div style="flex: 0 0 200px">3</div> /* flex: flex-grow flex-shrink flex-basis */
<div>4</div>
</div
Align self
در این قسمت آموزش FlexBox به توضیح ویژگی Align self در فلکس باکس میپردازیم.
بهعنوان آخرین خاصیت باقیمانده از مبحث FlexBox، ویژگی align-self را معرفی میکنیم. این ویژگی موقعیت و ترازبندی یک المان را بهصورت جداگانه مشخص کرده و ویژگی align-items را برای المان مورد نظر، بازنویسی میکند. مقادیر مورد استفاده برای این ویژگی مشابه با ویژگی align-items است. مقدار پیش فرض auto میباشد که در این حالت موقعیت از ویژگی align-items تبعیت میکند. برای نمونه با اعمال این کد، فقط مربع اول در وسط قرار گرفته و بقیهی موارد در ابتدا قرار میگیرند:
#container {
align-items: flex-start;
}
.square#one {
align-self: center;
}
حال فرض کنید که ۴ مربع دارید و برای ۲ مورد از ویژگی align-self استفاده کرده و برای سایر موارد ویژگیهای align-items: center و flex-direction: row را تنظیم میکنیم. با این کار دو المان سمت راست ثابت در مرکز قرار میگیرند و دو مورد سمت چپ با استفاده از ویژگی align-self تغییر موقعیت میدهند. در نتیجه خروجی بهصورت زیر خواهد شد:
صفحهی واکنشگرا با FlexBox
بعد از آموزش FlexBox ، در این بخش میخواهیم یک صفحه ی واکنشگرا ساده با فلکس باکس طراحی کنیم.
کد HTML:
<div class="container">
<div class="item item1 header">header</div>
<div class="item item2 aside aside1">aside1</div>
<div class="item item3 main">main</div>
<div class="item item4 aside aside2">aside2</div>
<div class="item item5 footer">footer</div>
</div>
کد CSS:
.container {
margin: 10px;
padding: 10px;
min-height: 150px;
background-color: #a13647;
/* Flexbox */
display: flex;
flex-flow: row wrap;
}
.container .item {
background-color: #d84a43;
color: #fff;
margin: 10px;
padding: 10px;
min-height: 50px;
}
.item {
flex: 1; /*flex-grow: 1;*/
}
.item.header {
flex: 100%; /*flex-basis: 100%;*/
}
.item.aside {
flex: 0 200px; /*flex-grow: 0; flex-basis: 200px;*/
height: 150px;
}
.item.main {
flex: 1 auto; /*flex-grow: 1; flex-basis: auto ;*/
}
.item.footer {
flex: 100%;
}
@media screen and (max-width: 950px) {
.item.header {
order: 1;
}
.item.aside {
flex: 1 auto;
}
.item.aside.aside1 {
order: 3;
}
.item.aside.aside2 {
order: 4;
}
.item.main {
order: 2;
flex: 1 100%;
}
.item.footer {
order: 5;
}
}
@media screen and (max-width: 600px) {
.item.aside {
flex: 100%; /* flex-basis: 100%; as min-width: 100%;*/
}
}
حذف Margin با FlexBox
اگر با CSS کار کرده باشید، حتما جاهای زیادی به این مشکل برخوردید که بخواهید تا تعدادی المان را در کنار هم قرار داده و با استفاده از margin فاصلهی بین آنها را تنظیم کنید. این مورد اغلب در کنار هم قراردادن اعضای یک منو رخ میدهد. مشکل به این صورت است که برای اضافه کردن فاصلهی بین آیتمها، یک ویژگی همانند margin-right را تنظیم کرده ولی یک فاصلهی اضافه در سمت راست آخرین المان منو ایجاد شده و مورد مشکل ساز همین فاصلهی اضافه است. برای مثال کد زیر را در نظر بگیرید:
<!DOCTYPE html>
<html>
<head>
<title>List</title>
<style type="text/css">
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.clear:before,
.clear:after {
content: " ";
display: table;
}
.clear:after {
clear: both;
}
.list {
width: 800px;
list-style: none;
margin: 100px auto 0;
background-color: yellow;
}
.person {
width: 23%;
margin-right: 2.66%;
float: left;
background-color: red;
padding: 10px;
}
</style>
</head>
<body>
<ul class="list clear">
<li class="person">Item 1</li>
<li class="person">Item 2</li>
<li class="person">Item 3</li>
<li class="person">Item 4</li>
</ul>
</body>
</html>
میبینید که یک منو با ۴ li قرار دادیم و درون style هم عرض هر کدام را ۲۳ درصد تنظیم کرده و با استفاده از margin-right فاصلهی بین آنها را مشخص کردیم. خروجی کنونی شکل بالایی بهصورت زیر خواهد بود:
همانطور که در شکل مشخص است، بهدلیل مشکل فاصلهی اضافهی بیان شده در بالا، آیتم آخر پایین آمده است. روش متداول برای حل این مشکل این است که فاصلهی اضافه برای المان آخر را حذف کنیم تا به شکل پایین در تصویر دست یابیم:
<!DOCTYPE html>
<html>
<head>
<title>List</title>
<style type="text/css">
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.clear:before,
.clear:after {
content: " ";
display: table;
}
.clear:after {
clear: both;
}
.list {
width: 800px;
list-style: none;
margin: 100px auto 0;
background-color: yellow;
}
.person {
width: 23%;
margin-right: 2.66%;
float: left;
background-color: red;
padding: 10px;
}
.person:last-child {
margin-right: 0;
}
</style>
</head>
<body>
<ul class="list clear">
<li class="person">Item 1</li>
<li class="person">Item 2</li>
<li class="person">Item 3</li>
<li class="person">Item 4</li>
</ul>
</body>
</html
میبینید که یک کلاس کاذب last-child گذاشته و مقدار margin-right را برای آن ۰ قرار دادیم. در نتیجه فاصلهی اضافه از بین رفته و همهی آیتمها درون منو قرار گرفتند. همچنین یک راه سادهتر برای حذف کلاسهای کاذب مثل nth- و first- و last-child وجود دارد و آن استفاده از FlexBox هست. میتوان با قرار دادن مقدار space-between برای ویژگی justify-content، به راحتی بین المانها فاصله قرار داده و بهصورت زیر عمل کرد:
<!DOCTYPE html>
<html>
<head>
<title>List</title>
<style type="text/css">
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.list {
display: flex;
justify-content: space-between;
width: 800px;
list-style: none;
margin: 100px auto 0;
background-color: yellow;
}
.person {
flex-basis: 23%;
background-color: red;
padding: 10px;
}
</style>
</head>
<body>
<ul class="list clear">
<li class="person">Item 1</li>
<li class="person">Item 2</li>
<li class="person">Item 3</li>
<li class="person">Item 4</li>
</ul>
</body>
</html>
در این کد برای کلاس list استایل display برابر با flex قرار دادیم و برای کلاس person هم ویژگی flex-basis را برابر با ۲۳% گذاشتیم.
معرفی چند منبع خوب تکمیلی:
موارد آموزش داده شده را میتوان در این صفحه به صورت تعاملی مشاهده و تمرین کرد. کدهای سازندهی این بخش تعاملی بهدلیل حجم زیاد بارگذاری شدهاند و میتوانید از اینجا آنها را دانلود کنید.
در پایان چند منبع آنلاین برای تکمیل آموزش فلکس باکس معرفی میکنیم:
- ابزار: یک ابزار آنلاین با استفاده از آن میتوان قالب و چارچوب مورد نظر خود را بر اساس flexbox به وجود آورد و کدهای CSS را در خروجی تحویل گرفت.
- فریم ورک بولما: یک فریم ورک قوی و بروز برای CSS بر پایهی FlexBox برای ساخت طرحهای واکنشگرا و گریدبندی پیشرفته.
- سایت: یک سایت برای طراحی و ساخت طرحهای واکنشگرا و ساختارهای پیچیده.
- سایت اول و سایت دوم: دو سایت انگلیسی با آموزش کامل و تصویری مطالب بیان شده.
- سایت بازیگونه: یک سایت بسیار جذاب برای آموزش موارد گفته شده همراه با بازی.
جمع بندی:
در این مقاله به آموزش FlexBox پرداختیم و سپس یک صفحهی واکنشگرا طراحی کردیم. مشکلات معمول در CSS را با کمک FlexBox رفع کرده و در نهایت چند منبع آنلاین تکمیلی را معرفی کردیم.