float vs inline-block – מתי להשתמש בכל אחת מההגדרות

לעיתים לא נדירות בכל בעת בנית אתר נצטרך למקם יותר מאלמנט אחד בשורה. אם ניקח לצורך העניין שיש לנו div – ההגדרה הדיפולטיבית שלו היא שהוא בלוק – מה שאומר שהוא כברירת מחדל יתפוס לנו שורה שלמה (אלא אם הגדרנו לו רוחב), ובנוסף, הוא ישבור שורה אחרי האלמנטים שלפניו ולפני אלו שאחריו. (קראו עוד על display: block). ישנן שתי דרכים פשוטות לסדר שאלמנטים יעמדו אחד ליד השני, שהן הפשוטות ביותר, עם השלכות מעטות ביותר על האלמנטים הסובבים. הדרכים הן – float או inline-block. בפוסט הזה נסביר את הרציונל של כל אחת מהדרכים ומתי עדיף להשתמש בהן.

נצייר לנו דוגמא שתלווה אותנו לאורך הפוסט.
נניח שיש לנו שלושה divים, ולכל אחד הגדרת רוחב 30% – אמנם כל אחד יתפוס 30% מרוחב האלמנט שמכיל אותם, אבל הם יעמוד אחד מתחת לשני, ולא אחד ליד השני:
מצב סטנדרטי של שלושה דיבים עם הגדרת בלוק
ישנן שתי דרכים עיקריות להעמיד אותם בשורה אחת. נסקור כל אחת בנפרד, ונסכם מתי יש עדיפות להגדרה אחת על פני אחרת.

float

ההגדרה float גורמת למעין "ריחוף" של האלמנט, בדרך כלל אלמנט עם display: block, מה שאומר שאם ניתן לאותם 3 div'ים מהדוגמא שלעיל את ההגדרה float: right; – הם יעמדו האחד ליד השני לצד ימין. כלומר – הראשון יעמוד הכי ימני, אחריו השני, ואחרון השלישי.
הדגמת מצב אלמנטים עם float right

זה נראה מובן מאליו, לא?! ככה זה אמור להיות בעברית? אז זהו שלא. כי אם נגדיר float: left – הראשון "עף" שמאלה, אחריו השני מקבל את ההגדרה ו"עף" שמאלה – למאחורי הראשון, והאלמנט השלישי יגיע לנו מימין לשני.
הדגמת אלמנטים עם float left

כלומר אין קשר לשפה או לdirection שמוגדר לbody, אלא הצד שאליו הגדרנו את הריחוף – זה יהיה הצד שאליו יהיה מיושר האלמנט.

אם נאתגר עוד קצת, נניח שלשלושת הdiv'ים האמורים ניתן כך:
float: right;
float: left;
float: right;
הראשון יהיה צמוד לימין, השני צמוד לשמאל והשלישי צמוד לימין – מיד בסוף האלמנט הראשון. כלומר יהיה לנו את הראשון, השלישי והשני.
משחק עם float שונים לשלושה אלמנטים

נראה שסיימנו לדבר על float? בקושי התחלנו…
להגדרה float יש השלכות מסוימות על האלמנט עם ההגדרה ועל האלמנטים שאחריו, וכן על האלמנט שמכיל אותו (הparent שלו), והאלמנטים שאחרי אותו parent.

נתחיל מהאלמנטים האחים (siblings) של האלמנט עם הריחוף. במידה והם עם ריחוף – הם יעמדו לידו ככל שיש מקום, ולאחר מכן ירדו שורה, אלא שאם יש אלמנטים בגבהים שונים זה עשוי לייצר בעיות שונות.
מצב שבו לכל האלמנטים יש אותו גובה:
הדגמת float כשיש גלישת שורה בגובה אלמנטים זהה

והנה מה שקורה כשלאחד מהאלמנטים יש גובה גבוה יותר. האלמנט ששובר לשורה הבאה לא עף ימינה עד מתחת לאלמנט הראשון (האדום), אלא הוא מנסה לעוף ימינה כביכול מצד שמאל, לכן אם האלמנט השלישי מסתיים גבוה יותר מהשני – הוא "נתקע בקיר" של האלמנט השני, וזה ייראה כך:
הדגמת float עם מעבר שורה, אלמנטים בגבהים שונים

עד כאן לגבי אחים עם ריחוף

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

חשוב להדגיש שלעולם לא ייווצר מצב שההתוכן של האלמנט ללא הריחוף יוסתר מתחת או יעלה מעל האלמנט עם הריחוף (אלא אם נגדיר את זה בכל מיני הגדרות כמו position: absolute. מדובר על התנהגות רגילה), מצד שני, האלמנט עצמו לא ממש מתחשב בגודל של האלמנטים עם הריחוף.

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

גם האלמנט האב של אלמנט עם ריחוף – במידה ואין לו עצמו ריחוף (לאבא) – לא קולט את הגובה של האלמנטים עם הריחוף, ומבחינתו הם לא קיימים מבחינת גובה. לכן אם יש לו צבע רקע, והאלמנטים עם הריחוף הם אחרונים, או שכולם עם ריחוף – בעצם לא נראה את הרקע של האבא, כביכול אין לו תוכן וממילא אין לו גובה.

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

display: inline-block

על הגדרה זו הרחבתי בפוסט שעסק בdisplay. תוכלו לקרוא עליו בהרחבה, איך הוא עובד וכו'.

מתי נעדיף להשתמש בdisplay: inline-block?

התאמה לכיוון

כשיש לנו רכיבים שעשויים לבוא בעברית ובאנגלית – מימין לשמאל ומשמאל לימין. אם נשתמש בfloat: right עבור אלמנטים שלצורך העניין אמורים להיות מיושרים לימין – נצטרך להגדיר באופן מיוחד עבור כל אלמנט כזה באנגלית שיקבל float: left וכן להיפך.
ראיתי מקומות שפתרו את זה באמצעות הוספת קלאס של float-right או float-left לאלמנטים שצריכים לקבל float, ואז בשפה ההפוכה, רק הגדירו float לכיוון ההפוך עבור הקלאסים הללו. השיטה הזו לא מוצלחת בעיני, כי באופן כללי אני לא בעד הכנסת הגדרה כל כך משמעותית ברמה הרספונסיבית לתוך קלאס. אבל זו אכן אפשרות.

לעומת זאת כשאנחנו מדברים על display: inline-block – החיים הופכים לקלים במיוחד. מאחר והאלמנטים בעצם מתנהגים כמו מילים במשפט – אין שום בעיה עם הכיוון, בדיוק כמו שבrtl סימן השאלה יופיע משמאל למשפט כי הוא כתוב אחריו – כך גם האלמנטים עם display: inline-block יתיישרו אחד אחרי השני בהתאם לdirection של האבא שלהם. האתר האחרון שבניתי הינו multisite (נדבר על זה בהזדמנות בעז"ה), ששתי האתרים שלו הינם אחד בעברית והשני – אתר זהה, רק באנגלית. בגלל שאת רוב היישורים סידרנו באמצעות inline-block ולא באמצעות float – כמעט ולא נזקקנו להתאמות לאנגלית. הכל התהפך אוטומטית בשניה שהוספנו לbody את ההגדרה direction: ltr באנגלית.

כך שכשיש לכם אתר או רכיב שאמור להיות בשתי שפות – זו נקודה שכדאי לחשוב עליה.

יישור אנכי

כמו שדיברנו בפוסט על יישור אנכי, כשיש לנו רצף של 2 אלמנטים או יותר עם inline-block ניתן להוסיף להם יישור אנכי – vertical-align. לא ניתן להגדיר את זה לאלמנטים עם float. למעשה ברגע שניתן float כלשהו (חוץ מnone כמובן) לאלמנט, לא משנה אם הוא היה בלוק או inline-block – הוא מתנהג בצורה זהה, וללא יישור אנכי. זו עוד נקודה שבמקרים רבים חשובה מאד. רק לדמיין מצב של שתי אלמנטים שאמורים לעמוד אחד ליד השני מיושרים אנכית, ועשינו את זה עם float: right, float: left בהתאמה, אז אומנם הם עומדים אחד ליד השני, אבל שתיהם מיושרים כלפי מעלה באותה נקודה. צריך להוסיף margin לאלמנט הנמוך יותר. ומה עושים כשהגבהים שלהם דינאמיים?!

בקיצור, כשצריך שתי אלמנטים שמיושרים אנכית האחד לשני – עדיף לחלוטין להשתמש בdisplay: inline-block ולא בfloat.

רווח בין אלמנטים

הנקודה הזו נפוצה בעיקר כשיש תפריט שרוצים שיהיה מתוח ברוחב מסוים, ללא קשר לאורך התוכן ולמס' הקישורים שבו. את זה לא ניתן בשום פנים לעשות אם float, כי בfloat צריך להגדיר ריווח (margin) בין האלמנטים קבוע – או בפיקסלים או באחוזים. ובמידה והקישורים בתפריט דינאמיים ומשתנים מפעם לפעם – אנחנו בבעיה…

לעומת זאת אם נשתמש לתפריט הזה עם display: inline-block – ישנה דרך נפלאה לסדר את זה (מקווה לכתוב על זה פוסט נפרד). דרך שבה לא צריך לתת ריווח בין האלמנטים אלא הריווח נוצר באופן אוטומטי.

אז מתי בכל זאת כדאי להשתמש בfloat?!

שבירת שורה באמצע

כשצריך אלמנטים שנמצאים באותה שורה, ומידי פעם אמורה להשבר השורה – אם נרצה להשתמש בdisplay: inline-block – נצטרך להוסיף אלמנט מיוחד שישבור לנו את השורה. בדיוק כמו שכשרוצים לשבור שורה בין מילים צריך ללחוץ במיוחד על אנטר ולהוסיף br.

לעומת זאת כשמשתמשים בfloat – לאלמנט שצריך לשבור שורה פשוט מוסיפים clear וזה הכל.

יישור תמונה + גלישת טקסט

הרבה פעמים רוצים ליישר תמונה וטקסט, באופן כזה שהתמונה נמצאת נניח בימין למעלה, והטקסט מתחיל משמאלה וגולש כלפי מטה, בדיוק כמו שהעמוד כאן נראה. אם ננסה את זה עם inline-block – הטקסט ירד מתחת לתמונה לחלוטין, אבל כשמשתמשים בfloat:right רק על התמונה – זו אחת התכונות של float, שהתוכן של האלמנטים האחים שלא מרחפים – עולה לצד האלמנט המרחף. אני מדגישה שרק התוכן, כי אם למה שמכיל את הטקסט יש מסגרת או רקע – זה יעמוד גם מתחת לתמונה.

יישור אלמנט בכיוון הפוך מכיוון הכתיבה

כשרוצים ליישר רק אלמנט אחד לכיוון ההפוך מכיוון הכתיבה, למשל כשאנחנו בעברית – RTL – ואיזשהו פריט צריך להיות מיושר שמאלה – יותר פשוט להגדיר לו float: left מאשר להתחיל לשחק עם text-align כדי שה"טקסט" (הלא הוא האלמנט עם inline-block) יטרח להתיישר שמאלה.

ובנוסף…

בנוסף, כשמתעצלים לממש את הפתרונות של display: inline-block רק בואו לא נשכח להוסיף clear: both מיד לאחר האלמנט.

 

עד כאן בנוגע לfloat מול inline-block. כמו שציינתי בתחילת הפוסט, ישנן דרכים נוספות ליישר אלמנטים יחד באותה שורה, לדוגמה flex, אבל כשמשתמשים בהגדרות הללו ההשלכות יחסית מעטות על האלמנטים שמסביב (כן, גם בנוגע לfloat. ברגע שמוסיפים clear פותרים כל בעיה), לעומת לדוגמה flex, שצריך לטפל בתאימות הדפדפנים שלה בעיקר במכשירי סלולר, וכך באופנים האחרים. בשתי הדרכים הללו אני משתמשת הרבה, ומהניסיון שלי – הן עובדות נפלא!

בהצלחה! וכמו תמיד – אם יש לכם רעיונות נוספים, נקודות שפספסתי, או שסתם בא לכם להשאיר הערות – בשמחה!

כתוב/כתבי תגובה