פריסה

הפודקאסט של CSS - 009: פריסה

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

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

פריסה: היסטוריה קצרה

בימים הראשונים של האינטרנט, עיצובים מורכבים יותר ממסמך פשוט, נוצרו עם רכיבי <table>. ההפרדה בין HTML לסגנונות חזותיים הייתה קלה יותר כאשר שימוש נרחב ב-CSS נעשה בסוף שנות ה-90 של המאה ה-20. שירות CSS פתח את הדלת למפתחים שיוכלו לשנות לחלוטין את המראה והתחושה של אתר בלי לגעת ב-HTML. היכולת החדשה הזו נתנה השראה לפרויקטים כמו The CSS Zen Garden, שנוצר כדי להדגים את העוצמה של CSS ולעודד יותר מפתחים ללמוד אותו.

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

ציר זמן שמראה את ההתפתחות של שירות ה-CSS לאורך השנים, משנת 1996 ועד שנת 2021.

פריסה: ההווה והעתיד

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

הסבר על הנכס display

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

.my-element {
  display: inline;
}

רכיבים בתוך השורה פועלים כמו מילים בתוך משפט. הם יושבים זה לצד זה בכיוון הרציף. רכיבים כמו <span> ו-<strong>, שלרוב משמשים לסגנון של קטעי טקסט ברכיבים שמכילים כמו <p> (פסקה), מופיעים בתוך השורה כברירת מחדל. הן גם שומרות על הרווח הלבן שמסביב.

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

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

.my-element {
    display: block;
}

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

.my-element {
    display: flex;
}

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

Flexbox ורשת

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

גמיש

.my-element {
    display: flex;
}

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

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

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

.my-element div {
    flex: 1 0 auto;
}

הנכס flex הוא קיצור של flex-grow, flex-shrink ו-flex-basis. ניתן להרחיב את הדוגמה שלמעלה באופן הבא:

.my-element div {
 flex-grow: 1;
 flex-shrink: 0;
 flex-basis: auto;
}

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

תצוגת רשת

.my-element {
    display: grid;
}

ה-Grid דומה בהרבה דרכים ל-flexbox, אבל הוא תוכנן לשלוט בפריסות עם צירים מרובים במקום בפריסות עם ציר אחד (אנכי או אופקי).

ה-Grid מאפשר לכתוב כללי פריסה על רכיב שיש לו display: grid, ומציגה כמה עקרונות חדשים לעיצוב פריסה, כמו הפונקציות repeat() ו-minmax(). יחידת רשת שימושית אחת היא היחידה fr, שמהווה חלק משטח האחסון שנותר – אפשר ליצור רשתות מסורתיות של 12 עמודות עם פער בין כל פריט, בעזרת 3 מאפייני CSS:

.my-element {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 1rem;
}

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

.my-element :first-child {
  grid-row: 1/3;
  grid-column: 1/4;
}

המאפיינים grid-row ו-grid-column מורים לרכיב הראשון ברשת להתפרס עד לתחילת העמודה הרביעית, מהעמודה הראשונה, ולאחר מכן span עד לשורה השלישית, מהשורה הראשונה.

פריסת זרימה

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

בלוק מוטבע

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

p span {
    display: inline-block;
}

השימוש ב-inline-block יוצר תיבה שיש בה חלק מהמאפיינים של רכיב ברמת הבלוק, אבל עדיין מועברת בתוך השורה.

p span {
    margin-top: 0.5rem;
}

צף

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

img {
    float: left;
    margin-right: 1em;
}

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

פריסה מרובת עמודות

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

<h1>All countries</h1>
<ul class="countries">
  <li>Argentina</li>
  <li>Aland Islands</li>
  <li>Albania</li>
  <li>Algeria</li>
  <li>American Samoa</li>
  <li>Andorra</li>
  …
</ul>
.countries {
    column-count: 2;
    column-gap: 1em;
}

הפעולה הזו תפצל באופן אוטומטי את הרשימה הארוכה לשתי עמודות ותוסיף פער בין שתי העמודות.

.countries {
    width: 100%;
    column-width: 260px;
    column-gap: 1em;
}

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

מיקום

לבסוף, נערכת סקירה כללית זו של מנגנוני הפריסה. המאפיין position משנה את ההתנהגות של רכיב מסוים בזרימה הרגילה של המסמך, ואת הקשר שלו לרכיבים אחרים. האפשרויות הזמינות הן relative, absolute, fixed ו-sticky, כאשר ערך ברירת המחדל הוא static.

.my-element {
  position: relative;
  top: 10px;
}

הרכיב הזה מופנה כלפי מטה ב-10 פיקסלים על סמך המיקום הנוכחי שלו במסמך, מכיוון שהוא ממוקם ביחס לעצמו. הוספה של position: relative לרכיב גם הופכת אותו לבלוק המכיל של כל רכיבי צאצא עם position: absolute. משמעות הדבר היא שעכשיו הצאצא שלה ימוקם מחדש ברכיב הספציפי הזה, במקום ההורה היחסי העליון, כאשר מוחל עליו מיקום מוחלט.

.my-element {
  position: relative;
  width: 100px;
  height: 100px;
}

.another-element {
    position: absolute;
    bottom: 0;
    right: 0;
    width: 50px;
    height: 50px;
}

כשמגדירים את position ל-absolute, הרכיב הזה ינותק מזרימת המסמך הנוכחית. המשמעות היא שני דברים:

  1. אפשר למקם את הרכיב הזה בכל מקום שרוצים באמצעות top, right, bottom ו-left בהורה היחסי הקרוב ביותר שלו.
  2. כל התוכן שמסביב לרכיב מוחלט הזורם מחדש כדי למלא את השטח הנותר שנותר על ידי אותו רכיב.

רכיב עם ערך position של fixed מתנהג באופן דומה ל-absolute, כשההורה שלו הוא רכיב השורש <html>. רכיבים במיקום קבוע נשארים עם עוגן בפינה הימנית העליונה על סמך הערכים של top, right, bottom ו-left שהגדרת.

בעזרת sticky אפשר להשיג את ההיבטים העוגנים והקבועים של fixed, וגם את ההיבטים הצפויים יותר שמכבדים את הזרימה של מסמכים ב-relative. עם הערך הזה, כשאזור התצוגה גולל מעבר לרכיב, הוא נשאר מעוגן לערכים top, right, bottom ו-left שהגדרתם.

סיכום

בפריסת CSS יש אפשרויות בחירה רבות וגמישות. כדי להתעמק עוד יותר בעוצמה של Flexbox ו-Grid של CSS, אפשר להמשיך למודולים הבאים.

בדיקת ההבנה

בחינת הידע שלכם בנושא פריסה

אילו שני דברים עושה הנכס display?

קובע את inline, את block או את none.
מנוע הפריסה צריך לדעת אם התיבה הזו היא ברוחב מלא או לא, והאם צריך להוסיף לה שורה חדשה.
המדיניות הזו קובעת את המסגרת של פריסת הרשת.
המאפיין display יכול להגדיר את התצוגה כרשת, אבל הוא לא קשור למסגרת פריסה.
הגדרת ההתנהגות של הילדים.
ל-Flexbox ולרשת יש דעות ופיצ'רים חדשים לילדים.
המדיניות הזו קובעת אם התיבה צריכה להיגלל.
זה הנכס overflow.

כדי להעביר מספר פסקאות לעמודות, איזה מאפיין CSS מתאים לביצוע המשימה הזו?

display: grid
בעוד שהרשת יכולה לכלול פסקאות מרובות בעמודות, העמודות האלה יהיו עמודות משלהן ולא יזרמו מאחת לשנייה.
column-count
הפסקאות יזרמו מקצה אחד של הטור לתחילת הטור הבא, בדומה לאופן הפעולה של כתב עת או עיתון.
display: flex
טקסט גמיש יכול לכלול מספר פסקאות בעמודות, אבל העמודות האלה יהיו עמודות משלהן, ולא צריך לזרום יחד מאחת לשנייה.
float
כדאי לנסות שוב.

מה זה אומר אם חסימה לא מתקדמת?

הוא תקוע על גדות הנהר.
ההקשר הוא CSS, ולא גיאוגרפיה.
הוא קיבל ערך מיקום של top או left.
שימוש במאפיינים האלה בלבד לא יפתור את הבעיה.
הוא כבר לא ממוקם לפי מיקומי האח שלו.
תיבה עם position: absolute לדוגמה, ממוקמת עכשיו עם קואורדינטות x ו-y על סמך הבלוק המכיל, ולא הסדר שלו עם רכיבים אחרים אחים.

Flexbox ו-Grid שלהם עוטפים את הילדים כברירת מחדל?

נכון
יש לצרף אותה באמצעות flex-wrap: wrap או repeat(auto-fit, 30ch).
לא נכון
ל-Flexbox ול-Grid יש תכונות אריזה מיוחדות שצריך להוסיף להן סגנונות נוספים.