fix: use safe-area-max-inset-top for iOS video extension
All checks were successful
build-website / build (push) Successful in 1m50s
All checks were successful
build-website / build (push) Successful in 1m50s
- Remove ClientOnly and Teleport wrappers that were causing SSR issues - Switch to safe-area-max-inset-top which properly returns notch height on iOS - Change position from fixed to absolute to prevent footer overlap - Add proper fallbacks for browsers without safe-area-max support - Simplify CSS by removing !important flags and duplicate styles This fixes the Safari bug where env(safe-area-inset-top) returns 0 in portrait mode by using safe-area-max-inset-top which always returns the correct notch height. 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -1,40 +1,35 @@
|
||||
<template>
|
||||
<section class="hero-voyage" id="heroSection">
|
||||
<!-- Hero video background teleported to body for proper safe area extension -->
|
||||
<!-- Using ClientOnly to avoid SSR/hydration issues with Teleport -->
|
||||
<ClientOnly>
|
||||
<Teleport to="body">
|
||||
<div ref="videoContainer" class="hero-video-container hero-video-teleported">
|
||||
<!-- White overlay that fades out when video is ready -->
|
||||
<div
|
||||
class="video-white-overlay"
|
||||
:class="{ 'fade-out': videoLoaded }"
|
||||
/>
|
||||
<!-- Hero video background using safe-area-max-inset-top for iOS Safari -->
|
||||
<div ref="videoContainer" class="hero-video-container">
|
||||
<!-- White overlay that fades out when video is ready -->
|
||||
<div
|
||||
class="video-white-overlay"
|
||||
:class="{ 'fade-out': videoLoaded }"
|
||||
/>
|
||||
|
||||
<video
|
||||
ref="videoElement"
|
||||
autoplay
|
||||
loop
|
||||
muted
|
||||
playsinline
|
||||
preload="auto"
|
||||
class="hero-video"
|
||||
:class="{ 'video-loaded': videoLoaded }"
|
||||
@loadeddata="handleVideoLoaded"
|
||||
@canplaythrough="handleVideoLoaded"
|
||||
@play="handleVideoLoaded"
|
||||
>
|
||||
<source
|
||||
src="https://videos.pexels.com/video-files/3571264/3571264-uhd_2560_1440_30fps.mp4"
|
||||
type="video/mp4"
|
||||
>
|
||||
</video>
|
||||
<video
|
||||
ref="videoElement"
|
||||
autoplay
|
||||
loop
|
||||
muted
|
||||
playsinline
|
||||
preload="auto"
|
||||
class="hero-video"
|
||||
:class="{ 'video-loaded': videoLoaded }"
|
||||
@loadeddata="handleVideoLoaded"
|
||||
@canplaythrough="handleVideoLoaded"
|
||||
@play="handleVideoLoaded"
|
||||
>
|
||||
<source
|
||||
src="https://videos.pexels.com/video-files/3571264/3571264-uhd_2560_1440_30fps.mp4"
|
||||
type="video/mp4"
|
||||
>
|
||||
</video>
|
||||
|
||||
<div class="hero-overlay gradient-warm" />
|
||||
<div class="hero-overlay gradient-depth" />
|
||||
</div>
|
||||
</Teleport>
|
||||
</ClientOnly>
|
||||
<div class="hero-overlay gradient-warm" />
|
||||
<div class="hero-overlay gradient-depth" />
|
||||
</div>
|
||||
|
||||
<div class="hero-content" :class="{ 'is-ready': videoLoaded }">
|
||||
<div class="hero-main">
|
||||
@@ -177,51 +172,43 @@ onMounted(() => {
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* Hero video container - Hardcoded safe area implementation for iOS */
|
||||
/* Hero video container using safe-area-max-inset-top for iOS Safari */
|
||||
.hero-video-container {
|
||||
position: fixed !important;
|
||||
left: 0 !important;
|
||||
right: 0 !important;
|
||||
width: 100vw !important;
|
||||
/* Hardcoded for iPhone 14/15 Pro Dynamic Island */
|
||||
/* Using negative value to extend into safe area */
|
||||
top: -59px !important;
|
||||
height: calc(100vh + 59px) !important;
|
||||
z-index: 0 !important;
|
||||
pointer-events: none !important;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: 100vw;
|
||||
/* Use safe-area-max-inset-top which always returns the notch height */
|
||||
/* Pull up by the max safe area to extend under notch */
|
||||
top: calc(-1 * env(safe-area-max-inset-top, 0px));
|
||||
/* Extend height to compensate */
|
||||
height: calc(100vh + env(safe-area-max-inset-top, 0px));
|
||||
z-index: 0;
|
||||
pointer-events: none;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
/* Teleported video container - ensure it stays at body level */
|
||||
.hero-video-teleported {
|
||||
position: fixed !important;
|
||||
z-index: 0 !important;
|
||||
/* Force the video to extend beyond safe area boundaries */
|
||||
top: -59px !important;
|
||||
height: calc(100vh + 59px) !important;
|
||||
}
|
||||
/* Fallback for browsers that don't support safe-area-max-inset-top */
|
||||
@supports not (padding: env(safe-area-max-inset-top)) {
|
||||
.hero-video-container {
|
||||
/* iPhone 14/15 Pro Dynamic Island fallback */
|
||||
top: -59px;
|
||||
height: calc(100vh + 59px);
|
||||
}
|
||||
|
||||
/* Fallback for older iPhones with smaller notch */
|
||||
@media screen and (max-height: 812px) {
|
||||
.hero-video-container,
|
||||
.hero-video-teleported {
|
||||
top: -44px !important;
|
||||
height: calc(100vh + 44px) !important;
|
||||
/* Older iPhones with smaller notch */
|
||||
@media screen and (max-height: 812px) {
|
||||
.hero-video-container {
|
||||
top: -44px;
|
||||
height: calc(100vh + 44px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Support for dynamic viewport height */
|
||||
@supports (height: 100dvh) {
|
||||
.hero-video-container {
|
||||
height: calc(100dvh + max(env(safe-area-inset-top), 59px));
|
||||
}
|
||||
}
|
||||
|
||||
/* When in standalone PWA mode, env() typically works better */
|
||||
@media screen and (display-mode: standalone) {
|
||||
.hero-video-container {
|
||||
top: calc(-1 * env(safe-area-inset-top));
|
||||
height: calc(100vh + env(safe-area-inset-top));
|
||||
height: calc(100dvh + env(safe-area-max-inset-top, 0px));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,12 +250,10 @@ onMounted(() => {
|
||||
|
||||
/* Container for hero section */
|
||||
.hero-voyage {
|
||||
/* Allow video to extend into safe area - no overflow clipping */
|
||||
max-width: 100vw !important;
|
||||
position: relative;
|
||||
min-height: 100vh;
|
||||
/* Explicitly allow overflow to ensure video can extend */
|
||||
overflow: visible !important;
|
||||
/* Allow video to extend into safe area */
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
.hero-main {
|
||||
|
||||
Reference in New Issue
Block a user