fix: use safe-area-max-inset-top for iOS video extension
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:
2025-09-21 19:06:08 +02:00
parent f94e3584ce
commit 84d6d58dd7

View File

@@ -1,10 +1,7 @@
<template> <template>
<section class="hero-voyage" id="heroSection"> <section class="hero-voyage" id="heroSection">
<!-- Hero video background teleported to body for proper safe area extension --> <!-- Hero video background using safe-area-max-inset-top for iOS Safari -->
<!-- Using ClientOnly to avoid SSR/hydration issues with Teleport --> <div ref="videoContainer" class="hero-video-container">
<ClientOnly>
<Teleport to="body">
<div ref="videoContainer" class="hero-video-container hero-video-teleported">
<!-- White overlay that fades out when video is ready --> <!-- White overlay that fades out when video is ready -->
<div <div
class="video-white-overlay" class="video-white-overlay"
@@ -33,8 +30,6 @@
<div class="hero-overlay gradient-warm" /> <div class="hero-overlay gradient-warm" />
<div class="hero-overlay gradient-depth" /> <div class="hero-overlay gradient-depth" />
</div> </div>
</Teleport>
</ClientOnly>
<div class="hero-content" :class="{ 'is-ready': videoLoaded }"> <div class="hero-content" :class="{ 'is-ready': videoLoaded }">
<div class="hero-main"> <div class="hero-main">
@@ -177,51 +172,43 @@ onMounted(() => {
</script> </script>
<style scoped> <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 { .hero-video-container {
position: fixed !important; position: absolute;
left: 0 !important; left: 0;
right: 0 !important; right: 0;
width: 100vw !important; width: 100vw;
/* Hardcoded for iPhone 14/15 Pro Dynamic Island */ /* Use safe-area-max-inset-top which always returns the notch height */
/* Using negative value to extend into safe area */ /* Pull up by the max safe area to extend under notch */
top: -59px !important; top: calc(-1 * env(safe-area-max-inset-top, 0px));
height: calc(100vh + 59px) !important; /* Extend height to compensate */
z-index: 0 !important; height: calc(100vh + env(safe-area-max-inset-top, 0px));
pointer-events: none !important; z-index: 0;
pointer-events: none;
background: #ffffff; background: #ffffff;
} }
/* Teleported video container - ensure it stays at body level */ /* Fallback for browsers that don't support safe-area-max-inset-top */
.hero-video-teleported { @supports not (padding: env(safe-area-max-inset-top)) {
position: fixed !important; .hero-video-container {
z-index: 0 !important; /* iPhone 14/15 Pro Dynamic Island fallback */
/* Force the video to extend beyond safe area boundaries */ top: -59px;
top: -59px !important; height: calc(100vh + 59px);
height: calc(100vh + 59px) !important; }
}
/* Fallback for older iPhones with smaller notch */ /* Older iPhones with smaller notch */
@media screen and (max-height: 812px) { @media screen and (max-height: 812px) {
.hero-video-container, .hero-video-container {
.hero-video-teleported { top: -44px;
top: -44px !important; height: calc(100vh + 44px);
height: calc(100vh + 44px) !important; }
} }
} }
/* Support for dynamic viewport height */ /* Support for dynamic viewport height */
@supports (height: 100dvh) { @supports (height: 100dvh) {
.hero-video-container { .hero-video-container {
height: calc(100dvh + max(env(safe-area-inset-top), 59px)); height: calc(100dvh + env(safe-area-max-inset-top, 0px));
}
}
/* 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));
} }
} }
@@ -263,12 +250,10 @@ onMounted(() => {
/* Container for hero section */ /* Container for hero section */
.hero-voyage { .hero-voyage {
/* Allow video to extend into safe area - no overflow clipping */
max-width: 100vw !important;
position: relative; position: relative;
min-height: 100vh; min-height: 100vh;
/* Explicitly allow overflow to ensure video can extend */ /* Allow video to extend into safe area */
overflow: visible !important; overflow: visible;
} }
.hero-main { .hero-main {