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

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

سوالت رو توی پنل بحث و گفتگو مطرح کن.

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

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

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

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

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

    .second
    {
    order: 1;
    }

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

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

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

      https://jsbin.com/vowava/ed

      1. بسیار سپاس گذار، قصد استفاده از این موضوع رو روی خروجی pdf دارمُ اگه موفقیت آمیز بود اعلام میکنم :D
        منتظر جواب بلندتون هم هستیم! :)

  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 این اندازه هارو به من نمیده

  5. سلام

    نظر شما راجع به سیستم گریدبندی چیه ؟

    به نظر شما فلکس باکس بهتره یا گرید ؟

    من فکر می کنم گرید بهتر باشه.

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

    1. نه من منبعی نمیشناسم. و خیر فعلا پشتیبانی مرورگرها از Grid جالب نیست و امکان استفاده ازش در پروژه های واقعی نیست.

  6. یزره سخت درکش برا من نیاز به مسال های گوناگون دارم اگه امکانش هست مثال های پیچیده تر و کاربردی تری بزارید ممنون

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

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

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

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

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

  11. سلام مجدد
    آقا من توی قسمت flex-shrink مشکل دارم ممنون میشم کمک کنین بهتر متوجه بشم
    با این مقادیری که شما به flex-shrink هر آیتم دادین طبق محاسبات شما اندازه نهایی عنصر اول 350px (البته شما حواستون نبوده و نوشتین 250px)، عنصر دوم 450px و عنصر سوم 300px خواهد بود اما وقتی inspect element میگیرم مقادیر دیگری رو برای عرض هناصر نشون میده. عنصر اول 360px، عنصر دوم 420px و سومی 320px.
    ظاهراً اونجوری که شما محاسبات رو انجام دادین مرورگر محاسبه نکرده و جوری دیگه ای این کارو کرده
    اگر متوجه نحوه محاسبه شدین ممنون میشم برای من هم توضیح بدین که بفهمم این flex-shrink دقیقاً چطوری کار میکنه

    1. من کلی گشتم تا جواب رو پیدا کردم
      معمولاً خیلی جاها که flex-shrink رو توضیح میدن خیلی سرسری ازش رد میشن و وقتی یک نفر یکم ریزتر بررسیش کنه و بخواد از محاسباتش سر در بیاره فقط گیج میشه و متوجه نمیشه.
      در اکثر جاها برای flex-shrink میگن که مثل flex-grow کار میکنه فقط در جهت معکوس، یعنی flex-grow فضای خالی رو به نسبت بین عناصر تقسیم میکنه و اونا رو بسط میده و flex-shrink هم به نسبتی که برای flex-shrink در نظر گرفتیم از عرض (یا ارتفاع) عنصر کم میکنه تا همه عناصر در containerشون جا بشن اما اینطوری نیست و محاسبات flex-shrink با flex-grow فرق داره.
      من از منابع آنلاین چیزی گیرم نیومد اما یک ebookی هست به اسم CSS Mastery: Advanced Web Standards Solutions که توسط Andy Budd و Emil Bjorklund نوشته شده که flex-box رو خوب توضیح داده. من از روی اون تونستم بفهمم محاسبات flex-shrink چطوری انجام میشه
      توی این کتاب نوشته در flex-shrink که قراره عناصر کوچک بشن برای اینکه عرض (یا ارتفاع) یک عنصر صفر نشه و یکی از عناصر کلاً ناپدید نشه نمیان مثل flex-grow فضاها رو به نسبت تقسیم کنن بلکه برای هر عنصر مقدار shrink به این صورت محاسبه میشه که میان مقدار flex-basis عنصر ضربدر flex-shrinkش رو تقسیم میکنن بر مجموع (flex-basis ضربدر flex-shrink) تک تک عناصر و نتیجه رو ضربدر فضایی که اضافه اومده میکنن.
      به عنوان مثال برای عنصر اولی که در مثال همین صفحه اومده
      flex-basis: 400px
      flex-shrink: 1
      و 300px هم مقدار فضایی بود که اضافه اومده بود
      پس مقداری که باید از عنصر اول کم بشه میشه:
      (400 * 1)
      / (تقسیم عبارت بالا بر عبارت پایین)
      (400 * 1) + (600 * 3) + (400 * 2)
      و حاصل این تقسیم ضربدر 300px (همون فضای اضافه)
      که میشه 40px برای عنصر باید ازش کم بشه.
      و طبق همین محاسبات باید از دومی 180px و از سومی 80px کم بشه.

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

      1. ممنون از توضیحاتی که نوشتید و بله کاملا درست هستش

        ولی نکته ای که شما و بقیه دوستان باید بدونید اینه که هیچ کدوم از سایت هایی که شما دیدید سر سری مطلب رو توضیح ندادن، روند پیاده سازی css توی مرورگرها همیشه در حال تغییر هستش. چون استانداردها باز نویسی میشه هر چند سال توی W3C.

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

        همونطور که چند بار دیگه نوشتم توی این کامنت ها، این مقاله نیاز به بروزرسانی داره که باید وقت بشه و انجام بدیم.

  12. با سلام و تشکر بابت آموزش خوبتون.
    وقتی display را روی flex قرار می گیرد، اگر container بدون wrap باشد با کوچک کردن صفحه، مطالب scroll می خورد. اما وقتی flex-direction از روی حالت پیش فرض روی row-reverse قرار می گیرد – یعنی از راست به چپ (بدون wrap) با کوچک کردن صفحه، مطالب scroll نمیخورد و مطالب کلا از دسترس خارج می شود. این قضیه حتی با کم کردن عرض container هم رخ می دهد.
    میشه بگید مشکل از کجاست و چگونه رفع می شود. ممنون

    1. سلام.

      نکته اینجاست که اسکرول فقط در جهت صفحه (ویژگی direction در CSS یا dir توی HTML) اتفاق میافته و برخلاف اون جهت اسکرول وجود نداره. در اینجا چون با row-reverse باعث میشید که عناصر در خلاف جهت صفحه (یا همون عنصر نگهدارندشون) چیده بشن، عناصر از جهتی خارج میشن که موافق با جهت عنصر نگهدارنده نیست و این انتفاق میافته.

      باید موردی که دارید روش کار می کنید رو ببینم تا بتونم کمکتون کنم ولی در کل یک سری کارها شبیه مثال زیر میشه کرد که از این اتفاق جلوگیری بشه.

      https://jsbin.com/jayiki/1/edit?html,css,output

  13. سلام

    طاعات و عبادات قبول

    چیزی که برای من سواله اینکه وقتی float ها دارن به خوبی و بدون مشکل رو همه پلتفرم ها و dvice ها کار میکنن، چرا باید از flex استفاده کنیم ؟
    الان من واقعا جز یکی دوتا مورد توانایی بیشتر ازش ندیدم .. حداقل اینکه واسه رسپانسیو یه قالب همون float هم کار راه انداز تره، هم راحت تر و هم پشتیبانیش تو مرورگرای پایین اوکی هست …
    درست نمیگم ؟

    1. سلام،

      اول اینکه float هیچ خوبی برای صفحه آرایی نداره، و فقط یک کار میشه باهاش کرد در صفحه آرایی و اون هم کنار هم قرار دادن ستون ها هستش که موجب مشکلات میشه که باید با هک هایی که هست برطرفشون کرد. (منطقی هم هست چون float کاربردش صفحه آرایی نیست)

      در مقابل اون فلکس باکس چنین کاری رو بصورت اصولی انجام میده چون کارش همین هستش. و بیشتر که با فلکس باکس کار کنید متوجه میشید که موارد استفاده و از اون بیشتره، و مهمتر اینکه، راحتی کار با اون رو اصلا نمیشه با float مقایسه کرد. (زمان میبره این موضوع کمی)

      و اما در مورد رسپانسیو و صفحه آرایی کلی صفحه، نکته اینجاست که فلکس باکس بیشتر برای چیدمان اجزا داخلی و موارد داخل کامپوننت ست و اون ماژولی که مخصوص به صفحه آرایی است CSS Grid هستش. (موردی که در مورد رسپانسیو مطرح کردید)
      هرچند که میشه همین کار رو با فلکس باکس هم انجام داد و باز هم خیلی بهتر از float میشه انجام داد، اگر تسلط کافی باشه.

      و اما از نظر پشتیبانی، خوب این موضوع دیگه مخصوص به پروژه مورد نظر هست و اینکه چه رویه ای رو برای پشتیبانی دنبال میکنید. که نکات زیادی هست که جاش توی کامنت نیست.

      در کل یه روزی میاد، که همونطور که افراد الان میگن چطور قدیما با table صفحه آرایی میکردند، بگن چطور با float…؟

  14. سلام خسته نباشید.من یک div دارم که dislpay اون فلکس هست.overflow اش هم زدم روی اسکرول.حالا وقتی توش تعداد زیادی عکس میزارم اسکرول افقی میخوره.منم همینو میخام.ولی مشکلم اینجاست که اگه به عنوان آیتم به جای img از div استفاده کنم به جای اینکه اسکرول بخوره ، اندازه div ها رو کم میکنه تا توش جا بشن.ولی من میخام هر div اندازه خودش رو داشته باشه و اسکرول بخوره.ممنون میشم راهنمائیم کنید.

  15. خیلی خوب توضیح دادید من ۵۰ تا سایت رو خوندم اما متوجه نشدم فلکس باکس چیه اما شما خیلی جامع و دسته بندی شده ویژگی هاش رو گفتید.ممنوووونم.عالی بود

  16. سلام آقای سیدی من دانشجوی رشته کامپیوتر هستم خیلی دوست دارم تو زمینه UI مثل شما بشم امسال مسابقات جهانی ملی مهارت دارم امید وارم بازم از این مطالب خوب بزارید : )

  17. ببخشید اگه بخوام قالب یک سایت رو از صفر تا 100 با فلکس باکس بزنم چه کار باد بکنم آیا قالب هست که با فلکس اصولی زده شده باشه و ما بتونیم از اون الگو برداری کنیم که در کجا هاش از Flex box استفاده کنیم : /؟

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