מדריך Flexbox – יישור אלמנטים ב Flex Container

המדריך (הכמעט) מלא לשימוש ב Flexbox.

השימוש בגריד כזה או אחר היה מאז ומתמיד חלק בלתי נפרד מעיצוב ופיתוח אתרים. סביר להניח כי נתקלתם לא פעם באתרים הבנויים על CSS Framework כלשהו כגון Bootstrap, Foundation וכדומה שמאפשרים שימוש בקלאסים מוכנים ליצירת גריד הבנוי מעמודות ושורות.

אך כרוב המפתחים אני מעדיף לא להסתמך ולהיות תלוי בעניינים חיצוניים ומעדיף לוותר על על הוספה של נכסים חיצוניים כשאני מפתח אתר. מה גם שאם לא משתמשים נכון בנכסים אלו, מנצא עצמינו מוסיפים לא מעט CSS ו Javascript מיותרים העלולים לפגוע בזמן טעינת האתר.

למעשה, גם כאשר אני משתמש באותם Frameworks, ברוב המקרים הדבר היחיד בו אני נעזר הוא השימוש ב Grid Layouts לטובת עימוד בלבד ולא בשאר אפשרויות העיצוב.

אז כיצד ניתן ליצור את אותם עימודים בצורה קלה ומהירה? כיצד ליישר אלמנטים בצורה נוחה? Flexbox זו התשובה כמעט תמיד, במיוחד כשמדובר על עימודים חד מימדיים, ושלא כמו CSS Grid המיועד בד״כ עבור עימוד דו מימדי.

במדריך זה נראה בהרחבה כיצד להשתמש בתכונות ה justification וה alignment של Flexbox. אם אתם לא מעוניינים לקרוא ופשוט מחפשים דוגמאות קוד לעימודים נפוצים בפלקסבוקס, גשו היישר לחלק המציג דוגמאות קוד לעימודים נפוצים ב Flexbox.

Flexbox – מבט כללי

ב Flexbox קיימים שני סוגים של ״קופסאות״ (Boxes). האחד הוא Flex Container והשני הוא Flex Item.  תפקידו של ה Flex Container הוא לקבץ מספר Flex Items יחד ולקבוע כיצד אלו ממוקמים.

Flex Items vs Flex Container | קרדיט: internetingishard.com

Flex Items vs Flex Container | קרדיט: internetingishard.com

כל אלמנט שהוא ילד ישיר של Flex Container הוא בעצם Flex Item. ניתן לבצע מניפולציות על Flex Items אינדיבידואלית, אך במרבית המקרים יהיה זה תפקידו של הקונטיינר לקבוע מתווה (Layout).

תפקידם העיקרי של Flex Items הוא לציין לקונטיינר כמה אלמנטים עליו למקם בקונטיינר.

יישור אלמנטים  Flex Container

אחת הסיבות ש Flexbox (פלקסבוקס) יצרה עניין רב אצל מפתחי Web היא שזו הביאה עימה לראשונה אפשרויות נוחות ליישור אלמנטים. מעבר לכך השימוש ב Flexbox מאפשר עימוד אנכי בצורה פשוטה כך שניתן למרכז אלמנט בקונטיינר כלשהו במהירות.

בכדי ליישר אלמנט אנכית למרכז ציר ה-Y נשתמש בתכונה align-items. לעומת זאת בכדי ליישר אלמנט אופקית בציר ה-X נשתמש בתכונה justify-content כבדוגמה הבאה:

.flex-wrapper{
  display: flex;
  align-items: center;
  justify-content: center;
}

.flex-wrapper > div {
    height: auto;
    min-width: 60px;
    min-height: 60px;
}
<div class="flex-wrapper">
     <div>1</div>
</div>

הנה התוצאה:

1

אך לפני שנמשיך ובכדי להבין כיצד התכונה Flexbox עובדת בצורה המיטבית – חשוב כי תבינו את ההתייחסות של Flexbox לציר ה-X האופקי (Main-Axis) ולציר ה-Y האנכי (Cross-Axis).

תנונ מבט בתמונות הבאות המתארות את ההתייחסות לצירים:

Flexbox Axis LTR - פלקסבוקס

עם האתר שלכם בעברית (RTL), ציר ה X ישנה כיוון כמובן, כלומר יתחיל בימין ויגמר בשמאל:

Flexbox Axis RTL - פלקסבוקס

הדוגמאות בפוסט זה יהיו בהתאם מכיוון ובלוג זה בעברית.

תכונות flexbox השולטות ביישור אלמנטים

התכונות אותן נתאר במהלך מדריך זה הם התכונות הבאות:

  • justify-content — שולטת ביישור האלמנטים כמכלול בציר ה-X.
  • align-items —שולטת ביישור האלמנטים כמכלול בציר ה-Y.
  • align-self —שולטת ביישור אלמנט Flex יחיד בציר ה-Y.
  • align-content —שולטת בריווח בין שורות Flex בציר ה-Y.

בואו נדבר על ציר ה-Y האנכי בתור התחלה…


Flexbox – ציר ה Y האנכי (Cross Axis)

אם נוסיף את התכונה display : flex לקונטיינר, הילדים הישירים של קונטיינר זה יהיו אלמנטים של Flex המסודרים בשורה כברירת מחדל. זה נראה כך (הקו המפריד קיים רק להבחנה בין האלמנטים):

אחת
שתיים
אלמנט שלוש מכיל יותר טקסט

במידה ואחד מהאלמנטים היה גבוה יותר, כל שאר האלמנטים יימתחו לגובה של אלמנט זה. כלומר הגבוה ביותר הוא שיקבע את גובה האלמנטים לאורך ציר ה-Y.

נדגים זאת על ידי שבירת שורות הטקסט של אלמנט מספר שלוש:

אחת
שתיים
אלמנט שלוש
מכיל יותר
טקסט

עליכם להבין כי אם לקונטיינר קיים גובה מוגדר (נאמר 300px), האלמנטים ימתחו לגובה זה ללא אבחנה בתוכן הקיים באותם אלמנטים.

הסיבה שאלמנטים נמתחים לאותו גובה היא שברירת המחדל של התכונה align-items הקובעת את יישור האלמנטים לאורך ציר ה-Y היא stretch וזו מותחת את האלמנטים כמה שניתן בתוך הקונטיינר.

כמובן שניתן להשתמש בערכים אחרים בכדי לקבוע כיצד האלמנטים יהיו מיושרים:

  • align-items: flex-start
  • align-items: flex-end
  • align-items: center
  • align-items: stretch
  • align-items: baseline

דוגמאות לשימוש בתכונה align-items

בואו נראה מספר דוגמאות לאפקט של התכונה align-items בציר ה-Y:

.flex-wrapper {
    display: flex;
    align-items: stretch;

}

.flex-wrapper > div {
    min-width: 60px;
    min-height: 60px;
    height: auto;
}

הקוד מעלה יספק את התוצאה הבאה (תכלס אין זה חובה להוסיף את align-items : stretch מכיוון והיא תכונת ברירת המחדל):

align-items : stretch

1
2
3
4

שינוי אך ורק של התכונה align-items יוביל לתוצאות הבאות:

align-items : flex-start

1
2
3
4

align-items : flex-end

1
2
3
4

align-items : center

1
2
3
4

לא נסביר את בפוסט זה את ההבדל בין flex-start ל baseline. מוזמנים לתת מבט בתשובה הבאה ב StackOverflow.

יישור אלמנט יחיד באמצעות התכונה align-self

חשוב להבין כי align-items בעצם קובעת את התכונה align-self על כל האלמנטים בקונטיינר כמכלול. זה אומר כי ניתן מפורשות להכריז על התכונה align-self עבור אלמנט יחיד בקבוצה.

התכונה align-self יכולה לקבל את כל הערכים שהתכונה align-items יכולה לקבל, אך ניתן להגדירה גם כ auto, שלבטח הנחתם – תגרום לאלמנט להתייחס לערך שנקבע עבור הקונטיינר עצמו.

שימו לב לדוגמה הבאה בה הקונטיינר הוא בעל התכונה align-items : startכך שכל האלמנטים יתיישרו לתחילת ציר ה-Y.

.flex-wrapper {
    align-items: flex-start;
    display: flex;
    height: 240px;
}

.flex-wrapper > div {
    height: auto;
    min-width: 60px;
    min-height: 60px;
}

.flex-wrapper > div:nth-child(1) {
    align-self: stretch;
}

.flex-wrapper > div:nth-child(3) {
    align-self: center;
}

קבענו כי האלמנט הראשון יהיה בעל התכונה align-self : stretch אך האלמנט השלישי יהיה בעל התכונה align-self : centerוזו תהיה התוצאה (דוגמה א׳):

1
2
3
4

יישור סט אלמנטים בציר ה Y האנכי

עד כה, יישרנו אלמנטים (או אלמנט אינדיבידואלי) באיזור שהוגדר על ידי הקונטיינר שלנו. אם תעטפו לצורך העניין מספר סטים של אלמנטים בקונטיינר Flexbox, כנראה ותרצו להשתמש גם בתכונה align-content האחראית לריווח בין אותם סטים.

התכונה align-content מקבלת את הערכים הבאים:

  • align-content: flex-start
  • align-content: flex-end
  • align-content: center
  • align-content: space-between
  • align-content: space-around
  • align-content: stretch
  • align-content: space-evenly (אינה מוגדרת בספסיפיקציה של Flexbox)

בדוגמה מטה הקונטיינר בגובה 300px אשר גבוה יותר מהנדרש עבור האלמנטים שלנו. הערך של align-content בדוגמה זו הוא space-between הקובע כי האיזור הריק שקיים יחולק שווה בשווה בין השורות וזאת כאשר האלמנט הראשון והאחרון יצמדו לגבולות הקונטיינר.

אני מזכיר כי ״אלמנט״ במקרה מתייחס לסט של אלמנטים המופיעים כל אחד בשורה משל עצמו.

.flex-wrapper {
    display: flex;
    height: 360px;
    flex-wrap: wrap;
    align-content: space-between;
}

.flex-wrapper > div {
    width: calc(100% / 3);
}
    
.flex-wrapper > :nth-child(7), 
.flex-wrapper > :nth-child(8) {
    width: 50%;
}

1align-content : space-between

1
2
3
4
5
6
7
8

שימו לב, כי בכדי שלתכונה align-content תהיה השפעה כלשהי, על הקונטיינר להיות גבוה יותר מהשורות עצמן יחדיו. במצב זה, התכונה תעבוד על השורות כסט ותקבע מה יקרה עם אותו שטח פנוי שקיים בכדי תאפשר לכם לשחק עם יישור אותן השורות בקונטיינר.

לא נעבור על כל האפשרויות, אך בואו נראה מספר דוגמאות נוספות בהן שיחקנו אך ורק עם התכונה align-content בהתייחסות לדוגמה האחרונה שהצגנו:

align-content : center

1
2
3
4
5
6
7
8

align-content : stretch

1
2
3
4
5
6
7
8

align-content : space-around

1
2
3
4
5
6
7
8

הפיכת הצירים – קביעת ה Main Axis

לפני שניגש לדבר על ציר ה-X האופקי, נאמר כי קיימת עבורינו אפשרות להפוך את הצירים. התכונות align-items ו align-self אותן תיארנו שולטות ביישור האלמנטים לאורך ציר ה-Y, בכיוון אנכי, אך זאת כאשר קיימת התכונה flex-direction: row:

flex-start
center
flex-end

לעומת זאת, כאשר קיימת התכונה flex-direction: columnתכונות אלו יישלטו באלמנטים לאורך ציר ה-X ובכיוון אופקי:

flex-start
center
flex-end

בכדי להבין טוב יותר כיצד שינוי זה משפיע על התכונות align-items ו align-self, תנו מבט בדוגמה הבאה הזהה לדוגמה שהצגנו מעלה (דוגמה א׳) אך בעלת flex-direction : column:

1
1
1
1

Flexbox – ציר ה X האופקי (Main Axis)

כעת, ולאחר שראינו כיצד יישור אלמנטים עובד בציר ה Y, ניתן מבט על ציר ה X. בציר ה X קיימת עבורינו תכונה אחת והיא justify-content וזאת מכיוון ובציר ה X אנו מתייחסים לאלמנטים כקבוצה.

בעזרת התכונה justify-content אנו שולטים על מה שיקרה עם השטח הריק בהנחה וקיים שטח רב יותר מהשטח אותו תופסים האלמנטים עצמם.

בדוגמה הבאה אנו מוסיפים את התכונה display : flex לקונטיינר כך שהאלמנטים יסתדרו בשורה בתחילת ציר ה X.

האלמנטים מסתדרים בצורה זו מכיוון והערך הדיפולטיבי של התכונה justify-content הינו flex-start.

השטח הריק הוא זה שקיים לאחר האלמנטים:

.flex-wrapper {
    display: flex;
    justify-content: flex-start;
}
1
2
3

במקרה זה הערך justify-content שווה ל space-between, השטח הריק מתחלק בין האלמנטים כאשר האלמנט הראשון והאחרון נצמדים לתחילתו ולסופו של הקונטיינר בהתאם:

justify-content : space-between

.flex-wrapper {
    display: flex;
    justify-content: space-between;
}
1
2
3

לתכונה justify-content אותם ערכים שקיימים לתכונה align-content:

  • justify-content: flex-start
  • justify-content: flex-end
  • justify-content: center
  • justify-content: space-between
  • justify-content: space-around
  • justify-content: space-evenly (אינה מוגדרת בספסיפיקציה של Flexbox)

אז שינוי אך ורק של התכונה justify-content בדוגמה מעלה יוביל לתוצאות הבאות:

justify-content : flex-end

1
2
3

justify-content: center

1
2
3

justify-content : space-around

1
2
3

יש לציין כי אם קיימת התכונה flex-direction : column אז התכונה justify-content תחלק את השטח הריק לאורך ציר ה Y וזאת כל עוד הקונטיינר גבוה יותר מהאלמנטים עצמם יחדיו:

.flex-wrapper {
    flex-direction: column;
    height: 300px;
    justify-content: space-between;
}

זו תהיה התוצאה:

1
2
3

התכונה flex-direction

ראינו כי התכונה flex-direction קובעת כיצד יונחו האלמנטים בקונטיינר ואף מגדירה לאיזה ציר נתייחס כציר הראשי.  החלפת  flex-direction : row ב flex-direction : column תהפוך בין ציר ה X לציר ה Y.

אך flex-direction יכולה גם לקבוע את הכיווניות של אלמנטים (רגילה או הפוכה). האפשרויות של התכונה הינן האפשרויות הבאות:

flex-direction: row

1
2
3

flex-direction: row-reverse

1
2
3

flex-direction: column

1
2
3

flex-direction: column-reverse

1
2
3

נזכיר ונאמר כי התכונה flex-direction מושפעת מכיווניות האתר (RTL or LTR).

שימוש ב auto margins ליישור אלמנטים ב Main Axis

לא קיימת עבורינו התכונה justify-items או justify-self עבור ציר ה-X ועלינו להתייחס לאלמנטים כקבוצה בציר זה. עם זאת, ניתן לבצע יישור אינדיבידואלי על מנת להפריד אלמנט או קבוצת אלמנטים מאחרים באמצעות שימוש ב auto margins.

סיטואציה שכיחה בה נרצה לעשות זאת היא תפריטי ניווט באתר בהם מספר אלמנטים מיושרים לשמאל כאשר קבוצת אלמנטים אחרת מיושרת לימין. תנו מבט בדוגמה הבאה:

.flex-wrapper {
    display: flex;
}

.flex-wrapper > div:nth-child(4) {
    margin-right: auto;
}
1
2
3
4
5

הדבר היחיד שביצענו הוא הוספת margin-right : auto לאלמנט מספר 4 הדוחף אלמנט זה ואת אלו שאחריו לקצה השמאלי של ה Main Axis.

עימודים נפוצים ב Flexbox עם דוגמאות קוד

תיאורטית, השימוש ב Flexbox הוא פשוט ונוח לבניית עימודים, בין אם מורכבים ובין אם כאלו פחות מורכבים.

עם זאת אני מוצא את עצמי לא פעם מוסיף את התכונה display : flex לאלמנט מסויים ואחר כך מבזבז לא מעט זמן בכדי להבין כיצד לגרום לאותו Flexbox Container להתנהג כפי שאני רוצה.

אם אתם בסיטואציה דומה אז הנה מספר דוגמאות CSS של עימודים ב Flexbox אותן אתם יכולים להעתיק ולהדביק לפרוייקט שלכם, לפחות כנקודת התחלה.

כל אחת מהדוגמאות בפוסט זה מניחה כי ה HTML מכיל אלמנט עם הקלאס container ובתוכו מספר ילדים בעלי הקלאס item (מספר הילדים משתנה כמובן בין דוגמה לדוגמה). אם לא מובן משהו הרגישו חופשי לשאול בתגובות.

<div class="container">
  <div class="item"></div>
  <div class="item"></div>
  <div class="item"></div>
  ...
</div>

1. Stretch all, fixed spacing

.container {
  display: flex;
}

.item {
  flex-grow: 1;
  height: 100px;
}

.item + .item {
  margin-right: 2%;
}

2. Stretch middle, fixed spacing

.container {
  display: flex;
}

.item {
  height: 100px;
  width: 100px; /* A fixed width as the default */
}

.item-center { 
  flex-grow: 1; /* Set the middle element to grow and stretch */
}

.item + .item { 
  margin-right: 2%; 
}

3. Alternating גריד

.container {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

.item {
  width: 48%;
  height: 100px;
  margin-bottom: 2%;
}

.item:nth-child(3n) {
  width: 100%;
}

4. גריד 3×3

.container {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

.item {
  flex: 0 32%;
  height: 100px;
  margin-bottom: 2%; /* (100-32*3)/2 */
}

5. גריד 3*3:    constrained proportions | 1:1

.container {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

.item {
  width: 32%;
  padding-bottom: 32%; /* Same as width, sets height */
  margin-bottom: 2%; /* (100-32*3)/2 */
  position: relative;
}

6. גריד 3*3:    constrained proportions | 16:9

.container {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
}

.item {
  width: 32%;
  padding-bottom: 18%; /* 32:18, i.e. 16:9 */
  margin-bottom: 2%; /* (100-32*3)/2 */
}

7. גרף: Vertical Bars

.container {
  display: flex;
  height: 300px;
  justify-content: space-between;
  align-items: flex-end;
}

.item { width: 14%; }
.item-1 { height: 40%; }
.item-2 { height: 50%; }
.item-3 { height: 60%; }
.item-4 { height: 20%; }
.item-5 { height: 30%; }

8. גרף: Horizontal Bars

.container {
  display: flex;
  height: 300px;
  justify-content: space-between;
  flex-direction: column;
}

.item { height: 14%; }
.item-1 { width: 40%; }
.item-2 { width: 50%; }
.item-3 { width: 60%; }
.item-4 { width: 20%; }
.item-5 { width: 30%; }

נספח – התכונה place-items ו place-content

קיימות אגב תכונות מקוצרות לאלו. התכונה place-items מקבילה לשימוש יחד בו place-content:

.flex-wrapper {
  display: flex;
  place-content: center center;
}


.flex-wrapper {
  display: flex;
  place-items: center center;
}

התכונה place-content היא קומבינציה של התכונות align-content ו justify-content ומאפשרת לכתוב שתי אלו בהגדרה דקלרטיבית אחת. כנ״ל לגבי התכונה place-items שהיא קיצור לתכונות align-items ו justify-items.

רגע, אבל אמרנו שלא קיימת התכונה justify-items ב Flexbox….??

אני עדיין מאחורי הטענה. התכונה justify-items היא אינה חלק מהספסיפקציות של Flexbox והשימוש בה לא יוביל לכלום עם השימוש ב Flexbox Container.

התכונה אם אינכם יודעים מגדירה את התכונה justify-self על קבוצת אלמנטים בקונטיינר מסויים והאפקט של זו משתנה בהתאם למתווה (layout) בו אתם משתמשים (block elements, tables וכדומה…). ב Flexbox התכונה לא תבצע מאום…

לא נתעכב על כך והאמת שקצת לא ברור מדוע קיימת התכונה place-items וזאת כאשר justify-items אינה בספסיפיקציות של Flex ואינה רלוונטית… יש לכם רעיון מדוע? שתפו בתגובות…

לסיכום

צפו כי בעתיד נוכל להשתמש בעוד תכונות הקיימות ב Box Alignment Level 3 עבור Flex. אני מניח שנוכל להשתמש בתכונות column-gap ו row-gap הקיימות ב CSS Grid Layout

אם נסכם, במדריך זה התעסקנו בעיקר ביישור אלמנטים בקונטיינר לאורך הצירים, אך קיימות תכונות נוספות ל Flex עליהן כדאי לדעת – flex-flow, flex-grow, flex-basis וכדומה.אלוכ מעבר לסקופ של מדריך זה אך מבטיח לכתוב גם על אלו בהקדם. בין אם במדריך זה או במדריכים נפרדים.

הרשמו לרשימת התפוצה בכדי להשאר מעודכנים. מעבר לכך, אם ישנן שאלות, הערות או סתם פידבק חיובי אתם מוזמנים לספר לנו בתגובות כתמיד…. 🙂

רועי יוסף
רועי יוסף

מפתח וורדפרס, מאמין ביצירת הזדמנויות לעסקים קטנים, סטארטאפים נועזים ואנשים עצמאים לשנות את העולם. אוהב טיפוגרפיה, צבעים וכל מה שבינהם ומכוון לספק אתרי וורדפרס עם ביצועים גבוהים, תמיכה בכל הדפדפנים, בעלי קוד ולידי, סמנטי ונקי.

6תגובות...
  • בן 29 באפריל 2019, 18:05

    למרות שאני מודע לפלקס בוקס אהבתי לקרוא.

  • אלעד סרוסי 29 באפריל 2019, 18:20

    קודם כל אחלה פוסט תודה רבה! אשמח לדעת איך היית עושה כמו בדוגמא שנתת לגבי space-between רק לגבי שני items כאשר הראשון בהתחלה והשני באמצע. שוב תודה.

    • רועי יוסף 29 באפריל 2019, 18:37

      שמח שאהבת אלעד 🙂

      שאלתך מתייחסת לחלק האחרון של הפוסט. אתה צריך לעשות שימוש ב auto margins:

      <div class="flex-wrapper">
         <div>1</div>
         <div>2</div>
      </div>
      .flex-wrapper {
          display: flex;
      }
      
      .flex-wrapper > div:nth-child(2) {
          margin-right: auto;
          margin-left: auto;
      }

      אבל האלמנט במקרה זה יהיה ממורכז בשטח הריק ולא לרוחב הקונטיינר המלא. אז הפתרון יהיה באמצעות CSS Grid. תן מבט בדוגמה הבאה ב Codepen.

  • אליהו 17 ביוני 2019, 10:26

    יפה מאוד, אחלה פוסט תודה על ההשקעה 🙂

השאירו תגובה

פעימות
Up!