• בלוג
  • היום למדתי: CSS Sticky ו overflow לא הולכים טוב יחד

היום למדתי: CSS Sticky ו overflow לא הולכים טוב יחד

מאפיין CSS Sticky הוא הדרך הכי קלה היום להגדיר שפס עליון מהעמוד ימשיך ללוות אותנו כשאנחנו גוללים למטה, ובעצם "יידבק" לראש העמוד. הוא נוח במיוחד כשיש לכם טבלה ואתם רוצים ששורת הכותרת תמשיך ללוות את הגולש גם אם הוא גולל למטה את השורות עצמן. מה שמיוחד ב sticky בניגוד להגדרת overflow: scroll על הטבלה זה שאנחנו לא מייצרים שני פסי גלילה (אחד חיצוני לעמוד והשני פנימי לטבלה) אלא משתמש גולל בפס הגלילה הרגיל החיצוני של העמוד וכששורת הכותרת של הטבלה מגיעה לחלק העליון של העמוד היא פשוט נדבקת לשם.

בקיצור הוספתי את ההגדרות המתאימות ל position: sticky בדיוק כמו בתיעוד וצפיתי באימה כששום דבר לא עבד. הנה הקוד, תחילה ה HTML ואחריו ה CSS (דמיינו את זה עם מאות שורות):

<div class="root">
<table>
  <thead>
    <tr>
    <th>name</th>
    <th>hair color</th>
    <th>city</th>
    <th>gender</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>bob</td>
      <td>blue</td>
      <td>foo</td>
      <td>agender</td>
    </tr>
    <tr>
      <td>bob</td>
      <td>blue</td>
      <td>foo</td>
      <td>agender</td>
    </tr>
</tbody>
<table>
</div>
.root {
  overflow: hidden;
}
thead th {
  position: sticky;
  top: 0;
  background: #d2d2d2;  
  padding: 2px 5px 2px 0;

}

table {
  border-collapse: collapse;
}

ובקודפן:

וקל לראות שגלילה של המסך לא באמת משאירה את שורת הכותרת "דבוקה" לראש העמוד. מה קורה פה?

התשובה מסתתרת במשפט הבא מתוך MDN:

Note that a sticky element "sticks" to its nearest ancestor that has a "scrolling mechanism" (created when overflow is hidden, scroll, auto, or overlay)

או בעברית - בגלל שמעל הטבלה יש לי div עם מאפיין overflow: hidden, למרות של div הזה אין הגבלת גובה והוא לא מייצר גלילה פנימית, ה sticky של הטבלה יהיה דביק ביחס אליו ולא ביחס ל body. במילים אחרות שורת הכותרת של הטבלה אכן נדבקת לחלק העליון, פשוט לחלק העליון של ה div שעוטף אותה, והוא זז למעלה מחוץ לחלק שאנחנו רואים.

הפיתרון? כמו תמיד פשוט כשיודעים. כל פעם שרוצים להשתמש ב position: sticky יש לוודא שאין מעליכם אלמנט עם overflow. הנה הקודפן המתוקן: