صفحه آرایی با فلکسباکس

صفحه آرایی با فلکس باکس ( Flexbox )

مقدمه

در دنیای HTML  و CSS  که نمایش محتوی را به عهده دارند همیشه یک موضوع, سختی و پیچیدگی خاص خود را داشته و آن هم صفحه آرایی است.

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

اگر با صفحه آرایی امروزی آشنا باشید قطعا با مشکل Float که به وسیله تکنیک Clearfix حل می شود دست و پنجه نرم کرده اید و حتی از مشکل whitespace  که در صفحه آرایی با inline-block به وجود می آید آگاهی دارید.

خبر خوب اینکه CSS3  ماژولی برای صفحه آرایی دارد که نه تنها مشکلات قبلی را کنار می زند بلکه ویژگی های بسیار چشم گیر و کاربردی را فراهم می کند. این ماژول Flexible Box یا Flexbox نام دارد.

برخی از امکانات فلکس باکس

  • چیدن عنصرها در یک ردیف کنار هم بدون نیاز به تعیین عرض مشخص و دقیق برای آنها
  • اگر برای عنصرهایی که در یک خط قرار گرفتن جای کافی نباشد به راحتی عنصر آخر به صورت خودکار در ردیف بعد قرار می گیرد.
  • به سرعت می توان چیدمان عنصرهای کنار هم را از افقی به عمودی و بالعکس عوض کرد.( فقط با تغییر یه کلمه )
  • همتراز سازی چپ, راست و مرکز نسبت به عنصر نگهدارنده
  • امکان تغییر ترتیب عنصرها بدون دست کاری در HTML ( این یکی واقعا خیلی عالیه )
  • تعیین کردن اندازه ی عنصر نسبت به اندازه ی عنصر نگهدارنده بدون نگران بودن در مورد واحد اندازه ی عنصر نگهدارنده و تغییرات viewport ( پنجره مرورگر)

شروع کار با فلکس باکس

اول عنصر نگهدارنده ( container ) و همینطور عنصرهای داخلی ( flex-item ) را بشناسیم.

 

عنصر نگهدارنده

 

عنصرهای داخلی  فلکس

 

توجه داشته باشید بیشترین ویژگی ها در این روش به عنصر نگهدارنده داده می شود.

برای تعیین یک نگهدارنده از نوع  flexbox باید display را از نوع flex تعریف کنیم.


.flex-container
{
  display : flex;
}

لازم به ذکر است که display مقدار دیگری هم می گیرد و آن inline-flex می باشد. کار این نوع شبیه flex است با این تفاوت که باعث می شود عنصر نگهدارنده خاصیت inline بگیرد.

در مرحله بعد برای اینکه عنصرهای داخلی یا فرزندها در یک ردیف در کنار هم قرار بگیرند باید ویژگی flex-direction را از نوع row تعریف کنید.


.flex-container
{
  flex-direction: row;
}

جهت چیدمان عنصرها

حال اگر بخواهیم عنصرها به جای چیدمان افقی, چیدمانی عمودی داشته باشند کافی است flex-direction را از نوع column تعریف کنیم.

دو مقدار دیگری که flex-direction می گیرد row-reverse و column-reverse می باشند که باعث می شوند ترتیب قرار گرفتن عنصرها به صورت عمودی بالعکس یا افقی بالعکس نمایش داده شود. مقدار پیشفرض برای این ویژگی row است.

توجه به این موضوع حائز اهمیت است که direction صفحه یا عنصرهای سطوح بالاتر تاثیر بر روی flex-direction از نوع row دارند که جهت قرار گرفتن عنصرها در موارد مختلف به قرار زیر است:

  • row: در ltr از چپ به راست, و در rtl از راست به چپ
  • row-reverse: در ltr از راست به چپ, و در rtl از چپ به راست

ویژگی بعدی که برای عنصر نگهدارنده تعیین می شود flex-wrap می باشد. فرض کنید مجموع اندازه عنصرهای داخلی بیشتر از اندازه عنصر نگهدارنده شود, به وسیله این ویژگی می توان کنترل کرد که عنصرها به خط بعد بروند یا در همان خط بمانند.

wrap

که مقادیراین ویژگی به شرح زیر است:

  • wrap: باعث می شوند عنصرها به خط بعد بروند
  • nowrap: مقدار پیشفرض که باعث می شود تحت همه شرایط تمام عنصرها در یک خط باقی بمانند.
  • wrap-reverse: این ویژگی باعث می شود عنصرهایی که در عنصر نگهدارنده جای نمی گیرند در همان خط بمانند و به جای آنها عنصرهای دیگر که از لحاظ ترتیب قبل آنها قرار دارند به خط بعد بروند.

 


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

می توان این دو ویژگی را به صورت کوتاه شده در یک ویژگی به نام flex-flow بیان کرد:


.flex-container
{
  flex-flow: row wrap;
}

 مواردی که تا الان بررسی شد می توانید در اینجا در حال اجرا ببینید. مقادیری که کامنت شدند را خودتان بررسی کنید تا به درک مفهموم کمک کند.

See the Pen zxXObg by Mojtaba Seyedi (@seyedi) on CodePen.

آشنایی با محور ها و کلمات کلیدی

عکس های زیر حاوی مفاهیم و کلمات مهمی هستند که باید بشناسیم. محورهای اصلی و عمود در فلکس باکس   کلمات کلیدی فلکس باکس

 

هم ترازسازی عنصرهای داخلی نسبت به محور اصلی (Main axis) به کمک justify-content

  به کمک ویژگی justify-content که به عنصر نگهدارنده اطلاق می شود می توان عنصرهای داخلی را نسبت به محور اصلی هم تراز کرد که شکل زیر مقادیر ممکن برای این ویژگی و چگونه هم تراز سازی را برای هر مقدار نشان می دهد.     گزینه های مرتب سازی عنصرهای داخلی نکته اینکه این ویژگی همچنین بر روی عنصرهایی که به خط بعد سرریز می کنند هم تاثیر می گذارد. در مثال مورد نظر ما داریم:  


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

 

 هم ترازسازی عنصرهای داخلی نسبت به محور عمود (Cross axis) به کمک align-items

  شکل زیر مقادیر قابل تعریف برای align-items را روشن بیان می کند.     تراز عنصرها نسبت به عنصر نگهدرانده لطفا به دو گزینه baseline  و stretch بیشتر توجه کنید چون هر دوی این ها واقعا جزو آروزی های css کارها بوده اند. همیشه ما به دنبال این بودیم که جدا از محتوای ستون هایمان آنها بتوانند ارتقاعی پویا و همینطور برابر داشته باشند. داریم:  


.flex-container
{
  align-items: stretch;
}

 

align-content

آخرین ویژگی در رابطه با عنصر نگهدارنده align-content می باشد. این ویژگی اجازه می دهد زمانی که عنصرهای داخلی بیشتر از یک ردیف هستند بتوان آن چند ردیف را نسبت به محور عمود هم ترازسازی کرد. تصویر زیر گویای ماجراست.     گزینه های تراز تمام عنصرها روشن است که این ویژگی زمانی که فقط یک ردیف از عنصرهای داخلی وجود دارند کاربردی ندارد.  


.flex-container
{
  align-content: space-around;
}

 

See the Pen Flexbox 2 by Mojtaba Seyedi (@seyedi) on CodePen.

تغییر ترتیب عنصرهای داخلی

توجه داشته باشید که ویژگی هایی که از این به بعد بررسی می کنیم مربوط به عنصرهای داخلی خواهند بود. اولین ویژگی order می باشد که به وسیله آن می توان ترتیب نمایش عنصرهای داخلی را بدون تغییر در ساختار HTML عوض کرد. مقداری که به این ویژگی انتصاب داده می شود یک عدد صحیح است. تصویر زیر گویای مطلب است. بزرگترین عدد حاکی آخرین عنصر از نظر ترتیب است. مقدار پیشفرض برای تمام عنصرها عدد 0 است. (مثال زیر صفحه آرایی چپ به راست دارد)

 

تغییر ترتیب عنصرها

 

ما در مثالمان می خواهیم عنصری که از نظر ترتیب HTML دوم است را به عنوان آخرین عنصر نمایش دهیم پس داریم:


.second
{
  order: 1;
}

 
از آنجایی که order برای تمام عنصرها بصورت پیش فرض 0 است, در نتیجه کافی است برای این عنصر, یک order با عددی بزرگرتر از 0 انتخاب کنیم.

 

انعطافپذیر سازی عنصرهای داخلی

یکی از اصلی ترین و ارزشمندترین امکاناتی که فلکس باکس در اختیار ما قرار می دهد قابلیت انعطاف پذیر بودن اندازه عنصرهای داخلی نسبت به فضای عنصر نگهدارنده است. که اگر جهت عنصر نگهدارنده row باشد عرض انعطاف پذیر می شود و اگر جهتش column باشد ارتفاع انعطاف پذیر است. برای رسیدن به این هدف باید با سه ویژگی flex-grow وflex-shrink و flex-basis آشنا بشویم.

flex-grow

این عامل یک عدد صحیح می باشد که نشان می دهد یک عنصر داخلی چند برابر عنصرهای دیگر از فضای عنصر نگهدارنده سهم می برد. مثلا اگر همه عنصرها مقدار 1 را داشته باشند فضای عنصر نگهدارنده به صورت برابر بین عنصرهای داخلی تقسیم می شود اما اگر یکی از آنها مقدار 2 را بگیرد سهم آن دو برابر سهم دیگر عنصرهای داخلی می باشد. شکل زیر گویای مطلب است.

تقسیم بندی فضا با flex-grow

در مثال به این صورت می نویسیم:


.first
{
  flex-grow: 1;
}
.second
{
  flex-grow: 2;
}
.third
{
  flex-grow: 1;
}

 

flex-basis

 

می توان به هر عنصر یک مقدار flex-basis به صورت زیر اختصاص داد

 


.first
{
  flex-grow: 1;
  flex-basis: 200px;
}

.second
{
  flex-grow: 2;
  flex-basis: 300px;
}

.third
{ 
  flex-grow: 1; 
  flex-basis: 250px;
}

اول از همه این مقدار با توجه به جهت عنصر نگهدارنده به عرض یا ارتقاع به صورت خودکار تعلق میگیرد یعنی اگر جهت عنصر نگهدارنده row باشد این مقدار به عرض عنصرهای داخلی داده می شود و اگر column باشد به ارتقاع عنصرهای داخلی تعلق میگیرد. سپس هر مقدار که از فضای عنصر نگهدارنده باقی بماند بین عنصرهای داخلی با توجه به flex-growی آنها تقسیم می شود تا در نهایت عنصرهای داخلی به عرض یا ارتفاع واقعی خود دست پیدا کنند.

در مثال ما که جهت هم افقی است مقادیر برای عرض عنصرهای داخلی تعیین می شوند پس برای عنصر اول 200px برای عنصر دوم 300px و برای عنصر سوم 250px ثبت می شود که جمع این سه مقدار 750px می باشد حال با توجه به اینکه عرض عنصر نگهدارنده در مثال ما 950px است پس هنوز مقدار 200px از عنصر نگهدارنده باقی مانده است که باید بین عنصرهای داخلی تقسیم شود. با توجه به اینکه flex-grow برای عنصر اول و سوم 1 است به هر کدام 50px فضای بیشتر داده می شود و چون flex-grow برای عنصر دوم 2 است 100px فضای بیشتر به این عنصر تعلق می گیرد. در آخر عرض نهایی عنصر اول 250px عنصر دوم 400px و عنصر سوم 300px می شود که جمع نهایی آنها 950px است که برابر با اندازه عنصر نگهدارنده می شود.

See the Pen Felxbox 3 by Mojtaba Seyedi (@seyedi) on CodePen.

flex-shrink

  این عامل به ندرت مورد استقاده قرار می گیرد. کاربرد آن زمانی است که جمع اندازه های عنصرهای داخلی بیشتر از عنصر نگهدارنده شود و سرریز داشته باشیم. حال باید عنصرهای داخلی کمی آب شوند (shrink) تا از سرریز جلو گیری شود که این کم کردن اندازه عنصرهای داخلی با توجه به این عامل انجام می گیرد مثال زیر دا در نظر بگیرید:


.first
{
  flex-grow: 1;
  flex-basis: 400px;
  flex-shrink: 1;
}

.second
{
  flex-grow: 2;
  flex-basis: 600px;
  flex-shrink: 3;
}

.third
{
  flex-grow: 1;
  flex-basis: 400px;
  flex-shrink: 2;
}

   فرض کنید اندازه عنصر نگهدارنده ما 1100px باشد همان طور که می بینید جمع عنصرهای داخلی 1400px است پس ما 300px سرریز خواهیم داشت.   حال از اندازه هر عنصر با توجه به flex-shrink آن مقداری کم می شود.   در عنصر اول 1/6 از 300px یعنی 50px کاهش خواهیم داشت که اندازه نهایی عنصر 250px می شود.   در عنصر دوم 3/6 از 300px یعنی 150px کاهش خواهیم داشت که اندازه نهایی عنصر 450px می شود.   در عنصر سوم 2/6 از 300px یعنی 100px کاهش خواهیم داشت که اندازه نهایی عنصر 300px می شود.   با این سه عامل که تا الان فرا گرفتیم می توانیم عنصرهای داخلی به طور کامل انعطاف پذیر طراحی کنیم و این کار واقعا ارزشمند و کاربردی است.   توجه داشته باشید که می توان این سه ویژگی را در یک ویژگی به نام flex به صورت کوتاه شده بیان کرد. به صورت زیر:   flex: grow shrink basis   برای مثال آخر داریم:


.first
{
  flex: 1 1 400px;
}

.second
{
  flex: 2 3 600px;
}

.third
{ 
  flex: 1 2 400px;
}

توجه داشته باشید چون می خواهیم عنصرها در یک ردیف بمانند flex-wrap: nowrap می باشد.

 

See the Pen Flexbox 4 by Mojtaba Seyedi (@seyedi) on CodePen.

 

ترازسازی تک عنصر با align-self

در بالا ویژگی مورد بررسی قرار گرفت یه نام align-items که وظیفه ترازسازی تمام عنصرهای داخلی را به عهده داشت و این ویژگی به عنصر نگهدارنده تعلق داشت. حال اگر بخواهیم تنها روی یک عنصر ترازسازی را انجام دهیم چه؟

برای این کار از ویژگی align-self استفاده می کنیم که این ویژگی به عنصر داخلی تعلق می گیرد و مقادیر آن شبیه مقادیر align-items است. شکل و مثال زیر مطلب را واضح تر می کند:


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

.second
{
  align-self: flex-end;
}

تراز تنها یک عنصر با align-self

توجه: float, clear, vertical-align هیچ تاثیری روی عنصر فلکس ندارند.

 

زمین بازی فلکس باکس

در آدرس زیر شما به محیطی برای یادگیری بهتر فلکس باکس دسترسی خواهید داشت:

همچنین در آدرس زیر ابزارهای مفیدی برای این ماژول معرفی شده اند:

 

پشتیبانی مرورگرها

در مورد مرورگرهای قدیمی چکار کنیم؟

برای اینکه بتوانید از فلکس باکس در مرورگرهایی مثل اینترنت اکسپلورر 8 و 9 هم استفاده کنید می توانید از پلیفیل هایی مثل flexibility و یا flexiejs بهره ببرید.