אם בניתם אי פעם אזור hero במסך מלא בנייד וראיתם את החלק התחתון שלו נעלם מחוץ למסך, אתם כבר מכירים את הבעיה. נתקלתי בזה בעשרות פרויקטים, וזה אחד הבאגים שגורמים לכם לחשוב שיחידות vh פשוט לא נועדו לטלפונים. (אם יחידות CSS כמו vh, vw ו-rem עדיין חדשות לכם, המדריך ל-CSS למתחילים מסביר את כולן.)
היום יש לזה פתרון אמיתי ב-CSS. שלוש יחידות viewport חדשות (svh, lvh ו-dvh) נותנות לכם שליטה מלאה באופן שבו ה-chrome של הדפדפן בנייד משפיע על ה-layout.
Browser chrome הוא הכינוי לשורת הכתובת, לסרגל הכלים, ללשוניות ולשאר רכיבי הממשק שמסביב לתוכן הדף. אין לזה קשר לדפדפן Google Chrome.
הבעיה עם 100vh בנייד
הגדרת אלמנט עם height: 100vh עובדת מצוין בדסקטופ. האלמנט ממלא את חלון הדפדפן ושום דבר לא חורג ממנו.
בנייד זה נשבר.
לדפדפנים בנייד יש סרגלי כלים דינמיים (שורת הכתובת, ובחלק מהדפדפנים גם סרגל כלים תחתון) שמופיעים כשהדף נטען ומתכווצים כשגוללים.

ב-Safari ב-iOS שורת הכתובת נמצאת בתחתית, וב-Chrome באנדרואיד למעלה. בשני המקרים היא מתכווצת כשגוללים.
כשאתם כותבים 100vh, הדפדפן מחשב את הערך הזה לפי ה-viewport הגדול ביותר (כשכל סרגלי הכלים מוסתרים). אבל בטעינה הראשונה סרגלי הכלים מוצגים, כך שהשטח שהמשתמש רואה בפועל קטן יותר.
התוצאה: האלמנט ה"מסך מלא" שלכם גבוה יותר מהשטח שהמשתמש רואה. החלק התחתון של האלמנט לא נראה: ב-Safari ב-iOS הוא מוסתר מתחת לסרגל הכלים, וב-Chrome באנדרואיד הוא יורד מתחת לגבול המסך. כפתור CTA בתחתית ה-hero נדחף אל מחוץ למסך.
.hero {
height: 100vh; /* Overflows on mobile! */
display: flex;
align-items: center;
justify-content: center;
}
עד עכשיו הפתרון היה האק ב-JavaScript שמשתמש ב-window.innerHeight:
document.documentElement.style.setProperty(
'--vh', window.innerHeight * 0.01 + 'px'
);
// Then in CSS: height: calc(var(--vh, 1vh) * 100);
זה עבד, אבל זה היה שביר, דרש resize listener ופשוט הרגיש לא נכון. זה משהו ש-CSS אמור לפתור בעצמו.
שלושת הסוגים החדשים של יחידות Viewport
ה-CSS Working Group הגדיר שלוש דרכים חדשות למדוד את ה-viewport, במקום ההתנהגות היחידה של vh. כל אחת מהן מגדירה אחרת מה נחשב "100% מגובה ה-viewport".
| יחידה | מודדת | מתאימה ל- |
|---|---|---|
svh |
ה-viewport הקטן ביותר (סרגלי הכלים מוצגים) | אזורי hero, מסכי פתיחה, תוכן above the fold |
lvh |
ה-viewport הגדול ביותר (סרגלי הכלים מוסתרים) | Layouts אימרסיביים, גלריות במסך מלא, app shells |
dvh |
ה-viewport הנוכחי (מתעדכן בזמן אמת) | Layouts שמתאימים את עצמם, sticky footers, ווידג'טים של צ'אט |
לכל יחידה יש גם גרסאות לרוחב, ל-inline ול-block. גרסאות ה-inline וה-block עובדות לפי אותו היגיון צירים של CSS logical properties:
| מימד | Small | Large | Dynamic |
|---|---|---|---|
| Height | svh |
lvh |
dvh |
| Width | svw |
lvw |
dvw |
| Inline | svi |
lvi |
dvi |
| Block | svb |
lvb |
dvb |
| Min | svmin |
lvmin |
dvmin |
| Max | svmax |
lvmax |
dvmax |
The small viewport-percentage units (sv*) are defined with respect to the small viewport size: the viewport sized assuming any UA interfaces that are dynamically expanded and retracted to be expanded.
The large viewport-percentage units (lv*) are defined with respect to the large viewport size: the viewport sized assuming any UA interfaces that are dynamically expanded and retracted to be retracted.
איך dvh (גובה Viewport דינמי) עובד
dvh שונה משתי היחידות האחרות. בניגוד ל-svh ו-lvh שהם ערכים קבועים, dvh מתעדכן בזמן אמת כששורת הכתובת וסרגל הכלים מופיעים או נעלמים.
כששורת הכתובת מוצגת, 100dvh שווה לשטח הנראה הקטן יותר. כשהמשתמש גולל ושורת הכתובת מתכווצת, 100dvh גדל וממלא את השטח שהתפנה.
.adaptive-panel {
height: 100dvh;
/* Shrinks when address bar appears */
/* Grows when address bar hides */
}
זה נשמע מושלם, אבל יש כאן trade-off. dvh מפעיל חישוב layout מחדש בכל פעם שסרגל הכלים זז, ולכן הוא עלול לגרום ל-reflow שרואים בעין באלמנטים שתלויים בו.
היזהרו עם dvh באלמנטים שיש בתוכם הרבה אלמנטים פנימיים. שינויי הגודל הרצופים בזמן גלילה עלולים לגרום ל-layout shifts ולאנימציות מקוטעות. ברוב הסקשנים במסך מלא, svh הוא בחירה בטוחה יותר.
מתי להשתמש ב-dvh
- Sticky footers או אלמנטים שצמודים לתחתית וצריכים להישאר בתחתית השטח הנראה בפועל
- ממשקי צ'אט או סרגלי כלים שצריכים תמיד למלא בדיוק את השטח הנראה
- Overlays של מודאלים שצריכים לשנות גודל יחד עם ה-chrome של הדפדפן
מתי להימנע מ-dvh
- אזורי hero ומסכי פתיחה. כאן עדיף
svh, שנותן תוצאה יציבה בלי חריגה מהמסך - אלמנטים עם תוכן כבד או אנימציות, שעלולים לגמגם בזמן reflow
- כל layout שבו גובה קבוע בטעינה הראשונה חשוב יותר מהתאמה בזמן אמת
דוגמה אינטראקטיבית: vh מול svh מול lvh מול dvh
ארבע היחידות מוצגות זו לצד זו. הסתירו והציגו את שורת הכתובת ושימו לב אילו טלפונים משנים גובה ואילו נשארים במקום. רק אחד מהם מתאים את עצמו בזמן אמת.
מקרי שימוש מעשיים
בואו נראה איך כל יחידה עובדת ב-layouts אמיתיים.
אזורי hero עם svh
באזורי hero במסך מלא, svh הוא הבחירה הנכונה. הוא מבטיח שהאלמנט ייכנס לשטח הנראה גם כששורת הכתובת מוצגת. זה חשוב במיוחד ב-layouts עם scroll snapping, שבהם כל סקשן אמור למלא בדיוק מסך אחד.
.hero {
min-height: 100svh;
display: flex;
align-items: center;
justify-content: center;
}
Sticky footer עם dvh
אם אתם צריכים layout שבו ה-footer צמוד לתחתית ה-viewport הנראה, dvh ישאיר אותו במקום גם כשה-chrome של הדפדפן משתנה.
.page-wrapper {
min-height: 100dvh;
display: flex;
flex-direction: column;
}
.main-content {
flex: 1;
}
.footer {
/* Always at the bottom of the visible area */
}
Overlay במסך מלא עם lvh
ל-overlays של מודאלים שצריכים לכסות כל פיקסל במסך, גם אחרי שהמשתמש גלל וסרגל הכלים נעלם, השתמשו ב-lvh.
.overlay {
position: fixed;
inset: 0;
height: 100lvh;
background: rgba(0, 0, 0, 0.8);
}
איך להוסיף Fallback
היחידות האלה נתמכות בכל הדפדפנים המודרניים (Chrome 108+, Safari 15.4+, Firefox 101+), אבל דפדפנים ישנים פשוט מתעלמים מהן. לכן תמיד הוסיפו fallback עם vh.
.hero {
height: 100vh; /* Fallback for older browsers */
height: 100svh; /* Modern browsers use this */
}
ה-cascade של CSS עושה כאן את העבודה. דפדפנים שמכירים את svh דורסים את ההצהרה הראשונה, ואלה שלא נשארים עם ערך ה-vh.
אפשר גם להשתמש ב-@supports ללוגיקת fallback מורכבת יותר:
.hero {
height: 100vh;
}
@supports (height: 100svh) {
.hero {
height: 100svh;
}
}
טעויות נפוצות
אלה הטעויות שאני רואה שוב ושוב כשמפתחים מתחילים לעבוד עם יחידות ה-viewport החדשות.
שימוש ב-dvh באזורי hero
dvh משנה גודל בזמן הגלילה, ולכן אזור ה-hero "קופץ" כששורת הכתובת מתכווצת. ב-hero השתמשו ב-svh, שנשאר יציב.
להניח ש-dvh מתחשב במקלדת הווירטואלית
אף אחת מיחידות ה-viewport החדשות לא מתחשבת במקלדת שעל המסך. כשמשתמש נוגע בשדה קלט, המקלדת דוחפת תוכן למעלה ו-100dvh לא מתכווץ בהתאם.
ב-layouts עם הרבה שדות קלט תצטרכו קוד JavaScript נוסף, או את הערך interactive-widget בתגית ה-viewport meta (נתמך ב-Chrome וב-Firefox באנדרואיד, Safari ב-iOS מתעלם ממנו):
<meta name="viewport"
content="width=device-width, initial-scale=1,
interactive-widget=resizes-content">
לדלג על ה-fallback
התמיכה רחבה, אבל חלק קטן מהתעבורה עדיין מגיע מדפדפנים ישנים שלא תומכים ב-svh/dvh. תמיד הצהירו על height: 100vh לפני היחידה החדשה.
שימוש ב-dvh באנימציות או transitions
מכיוון ש-dvh משנה ערך במהלך הגלילה, אנימציה של גובה אלמנט מ-0 ל-100dvh עלולה לגרום לריצוד לא צפוי. השתמשו ביחידות קבועות או ב-svh/lvh באנימציות.
תמיכת דפדפנים
כל שלושת סוגי היחידות הגיעו לסטטוס Baseline Widely Available ביוני 2025, כלומר הם נתמכים בכל מנועי הדפדפנים הגדולים.
לפי caniuse, כ-94% מהמשתמשים בעולם גולשים בדפדפנים שתומכים ביחידות האלה. רוב השאר משתמשים בגרסאות ישנות של Chrome ו-UC Browser.
שאלות נפוצות
שאלות נפוצות על גובה viewport דינמי ב-CSS:
vh שקול ל-lvh בדפדפנים מודרניים. הוא משתמש בגודל ה-viewport הגדול ביותר (כשסרגלי הכלים מוסתרים). dvh משתנה בזמן אמת כשה-chrome של הדפדפן מופיע או נעלם, ותואם בכל רגע לשטח שנראה בפועל.
svh. הוא מייצג את ה-viewport הקטן ביותר (עם שורת הכתובת גלויה), כך שה-hero ייכנס במלואו למסך כבר בטעינה הראשונה. עם dvh ה-hero ישנה גודל כשהמשתמש גולל, וזה עלול להרגיש קופצני.
dvh, svh ו-lvh מקבלות את אותו ערך כמו vh. ההבדל רלוונטי רק בנייד, בדפדפנים עם סרגלי כלים שמתכווצים.
interactive-widget=resizes-content בתגית ה-viewport meta (Chrome ו-Firefox באנדרואיד, Safari ב-iOS מתעלם ממנו), או טפלו בזה ב-JavaScript.
calc(). לדוגמה, height: calc(100svh - 60px) נותן לכם את גובה ה-viewport הקטן פחות header של 60px.
vh בשביל האחוז הקטן של המשתמשים בדפדפנים ישנים.
dvh מפעיל חישובי layout מחדש בכל פעם שסרגל הכלים של הדפדפן משנה גודל. באלמנטים פשוטים ההשפעה זניחה, אבל ב-layouts מורכבים עם הרבה אלמנטים פנימיים זה עלול לגרום לגמגום שרואים בעין. svh ו-lvh הם ערכים סטטיים, בלי שום עלות בביצועים.
סיכום
לבאג ה-100vh בנייד יש סוף סוף פתרון. השתמשו ב-svh לסקשנים יציבים במסך מלא שנכנסים למסך כבר בטעינה הראשונה, ב-lvh ל-layouts אימרסיביים שממלאים את כל השטח האפשרי, וב-dvh כשצריך להגיב בזמן אמת לשינויים בסרגל הכלים. ואל תשכחו fallback עם vh לדפדפנים ישנים.
מאז ש-Chrome 108 יצא אני משתמש ב-svh כברירת מחדל באזורי hero, ובעיית החריגה מהמסך פשוט נעלמה. ברוב ה-layouts, svh היא היחידה שאתם באמת צריכים. dvh שימושי, אבל רק במקרים מסוימים כמו sticky footers ו-page wrappers מבוססי flexbox.
