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

صفحه آرایی با فلکس باکس ( 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 بهره ببرید.

49 دیدگاه برای “صفحه آرایی با فلکس باکس ( Flexbox )

  1. سلام این مقاله عالیه ، خسته نباشین. من در حین مطالعه نکته ای به ذهنم رسید که گفتم بعنوان پیشنهاد اینجا ارایه بدم تا اگر معقول رسید خواننده های محترم هم در نگارش مقالاتشون توجه کنن. بنظر بنده درک واژهای “آیتم” , “آیتمها” خیلی اسونتر و سریعتر از درک «عنصر» و عناصر» هستش. در مطالعه سریع با حرکات سریع چشم، تفاوت ظاهری «آیتمها» با شکل مفرد اون یعنی «ایتم» بوضوح سریعتر از تفاوت بین “عناصر” و «عنصر» برای مغز قابل درکه. چون در هنگام مطالعه سریع با چشم مغز انسان بیشتر به حروف اول و پایانی واژگان متمرکز می شه که در «عناصر» و «عنصر» حروف اول و اخر کاملا یکی هستند. موق باشین . با احترام :)

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

  2. مجتبی جان، اون قسمتی که نوشتی :

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

    .second
    {
    order: 1;
    }

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

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

      به این لینک برو و مقادیر order رو تغییر بده تا کاملا موضوع روشن بشه.

      https://jsbin.com/vowava/ed

  3. سلام و عرض ادب
    ممنون بابت مطلب خوبتون
    امکانش هست تفاوت align-content و align -items رو به صورت واضح تر توضیح بدین و تفاوت هاشو بیان کنین؟
    آیا align-items روی چند ردیف تاثیر ندارد؟؟؟

    1. سلام.

      align-items تمرکزش رو عناصری است که توی یک ردیف جا میشن. یعنی وقتی باهاش کار می کنید فقط طوری تنظیمش کنید که میخواید عناصری که توی “یک ردیف” هستند “نسبت به هم” تراز بشن.

      اما align-content همه ردیف ها رو نسبت به عنصر نگهدارنده تراز می کنه.

      این دمو رو نگاه کنید:

      http://codepen.io/seyedi/pe

      به هر دوی این ویژگی ها flex-end دادم. این مقدار برای align-items باعث شده تا عنصرهایی که در یک ردیف هستند پایینشون باهم تراز شه.

      اما همین مقدار برای ویژگی align-content باعث شده تا کل ردیف ها همه با هم به کف عنصر نگهدارنده بچسبند.

      نمیدونم تونستم کمکتون کنم یا نه. ولی تمرین کنید و آیتم ها رو کم و زیاد کنید و از طرفی مقادیر هر دو ویژگی رو مدام تغییر بدید تا بهتر موضوع درک بشه.

      اگر هم تونستید روش بهتری برای توضیح این دو ویژگی پیدا کنید لطفا به من هم بگید تا پست رو آپدیت کنم.

      ممنون از شما. باز هم نکته ای بود بگید لطفا

  4. سلام مجتبی جان …
    تو بحث flex-shrink که گفتی “” اول 1/6 از 300px یعنی 50px کاهش خواهیم داشت و 3.6 از 300 ,,,,بر چه اساسی گفتین 1.6 از 300 و 3.6 از 300 و …..!!
    لطفا راهنمایی کن.مرسی داداش

    1. سلام. ممنون از پیامتون. راست میگید گنگ نوشتم اونجا رو.

      جمع shrink عناصر 6 هستش. 1 + 3 + 2 = 6. خب برای اولی 1 ششم از اندازه خود عنصر باید آب بشه. برای دومی 3 ششم و الی آخر…

      موفق باشید.

      1. البته برای اولی که یک ششم میشه برابر 50px و اندازه نهایی 350px میشه که اشتباهاً 250px خورده.
        من با همین متود میرم جلو اما inspecter این اندازه هارو به من نمیده

    1. سلام. این دو رو نمی تونیم در مقابل هم قرار بدیم. میشه توی صفحه آرایی یک صفحه از هردوی این دو استفاده کرد و از نقاط قوت هر کدومشون بهره برد.

  5. سلام مرسی که آموزش دادید من یه مشکلی دارم: میخواهم آیتم ها به صورت سطری کنار هم ببینم ولی ارتفاع آن ها متفاوت است مشکلی که به وجود میآید اینه که یه سری فضا خالی در بین سطرهام بوجود میاد نکتش اینه که نمیخوام آیتم را بکشم تا با ایتم کناریش هم ارتفاع بشه و اینکه صورت مسئله را تغییر بدم سطونی هم نمیخواهم ایتم هام را کنار هم بچینم چون صفحه بینهایت است و … یه چیزی تو مایه های سایت ویسگون میخوام که پستها کنار هم است با ارتفاع متفاوت راه css وجود داره؟ اگه کسی میتونه یا میدونه ممنون میشوم کمک کنه

  6. سلام چجوری میشه اینو با بوت استرپ ادغام کرد ؟

    یعنی برای ریسپانسیو کردن این باید مدیا کوئری بزنیم ؟‌یا اینکه میشه با یه فریم ورک ریسپانسوش کرد ؟‌

  7. سلام ، خسته نباشید
    لطفا اگر ممکنه من رو راهنمایی کنید
    من میخوام یک سری عکس کنار هم قرار بگیرن که عرض متفاوت دارند و ارتفاعشون برابره
    مثلا انگار در بوت استرپ به یک عکس کلاس col-lg-8 بدیم و به دیگری col-lg-4
    حالا مسئله اینه میخوام مثل grid خود جای خالی رو با عنصری که عرضش مناسب هست پر کنه
    این امکان در فلکس باکس هست؟

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

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *