All checks were successful
build-website / build (push) Successful in 1m50s
- Add hardcoded fallbacks using max() function per Apple's recommendation - Support both constant() and env() for legacy compatibility - Use 59px fallback for Dynamic Island devices - Add iOS-specific detection with @supports(-webkit-touch-callout) - Create improved test page with device detection - Update hero-content padding with same fallback approach This works around the known Safari bug where env(safe-area-inset-top) returns 0px in portrait mode. The video will now extend 59px above the viewport on Dynamic Island iPhones, ensuring it covers the notch area.
267 lines
8.0 KiB
HTML
267 lines
8.0 KiB
HTML
<!doctype html>
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
|
<title>Safe Area Fix Test - Harbor Smith</title>
|
|
<style>
|
|
* {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
html {
|
|
height: 100%;
|
|
}
|
|
|
|
body {
|
|
margin: 0;
|
|
background: #000;
|
|
height: 100%;
|
|
}
|
|
|
|
/* Use @supports as recommended by Apple */
|
|
@supports(padding: max(0px)) {
|
|
.bg {
|
|
position: fixed;
|
|
left: 0;
|
|
right: 0;
|
|
width: 100%;
|
|
/* Use max() function to ensure fallback */
|
|
top: calc(-1 * max(env(safe-area-inset-top), 20px));
|
|
/* Safari-specific: use constant as fallback */
|
|
top: calc(-1 * max(constant(safe-area-inset-top), env(safe-area-inset-top), 20px));
|
|
height: calc(100vh + max(env(safe-area-inset-top), 20px));
|
|
height: calc(100vh + max(constant(safe-area-inset-top), env(safe-area-inset-top), 20px));
|
|
z-index: -1;
|
|
}
|
|
}
|
|
|
|
/* Fallback for browsers without @supports */
|
|
.bg {
|
|
position: fixed;
|
|
left: 0;
|
|
right: 0;
|
|
top: -44px; /* Standard notch height fallback */
|
|
width: 100%;
|
|
height: calc(100vh + 44px);
|
|
z-index: -1;
|
|
}
|
|
|
|
/* iOS-specific using -webkit-touch-callout */
|
|
@supports (-webkit-touch-callout: none) {
|
|
.bg {
|
|
/* For iPhone 14/15 Pro with Dynamic Island (59px) */
|
|
top: -59px;
|
|
height: calc(100vh + 59px);
|
|
}
|
|
}
|
|
|
|
/* Gradient background */
|
|
.bg::before {
|
|
content: "";
|
|
position: absolute;
|
|
inset: 0;
|
|
background: linear-gradient(180deg,
|
|
#ff0000 0%, /* Red at very top */
|
|
#ff6600 10%, /* Orange */
|
|
#ffcc00 20%, /* Yellow */
|
|
#33cc33 30%, /* Green */
|
|
#0099ff 50%, /* Blue */
|
|
#6633cc 70%, /* Purple */
|
|
#cc33cc 90%, /* Magenta */
|
|
#000000 100% /* Black at bottom */
|
|
);
|
|
}
|
|
|
|
/* Content with proper safe area padding using max() */
|
|
@supports(padding: max(0px)) {
|
|
.content {
|
|
position: relative;
|
|
min-height: 100vh;
|
|
padding-top: max(env(safe-area-inset-top), 44px);
|
|
padding-top: max(constant(safe-area-inset-top), env(safe-area-inset-top), 44px);
|
|
padding-left: max(env(safe-area-inset-left), 0px);
|
|
padding-right: max(env(safe-area-inset-right), 0px);
|
|
padding-bottom: max(env(safe-area-inset-bottom), 0px);
|
|
color: #fff;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
}
|
|
|
|
/* Fallback content padding */
|
|
.content {
|
|
position: relative;
|
|
min-height: 100vh;
|
|
padding-top: 44px;
|
|
padding-left: 0;
|
|
padding-right: 0;
|
|
padding-bottom: 0;
|
|
color: #fff;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
@supports (-webkit-touch-callout: none) {
|
|
.content {
|
|
padding-top: 59px; /* Dynamic Island */
|
|
}
|
|
}
|
|
|
|
h1 {
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
font-size: 2rem;
|
|
text-align: center;
|
|
text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.info {
|
|
background: rgba(255, 255, 255, 0.1);
|
|
backdrop-filter: blur(10px);
|
|
-webkit-backdrop-filter: blur(10px);
|
|
padding: 20px;
|
|
border-radius: 10px;
|
|
margin: 20px;
|
|
max-width: 90%;
|
|
}
|
|
|
|
.info p {
|
|
margin: 10px 0;
|
|
font-family: monospace;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.success {
|
|
color: #4CAF50;
|
|
}
|
|
|
|
.warning {
|
|
color: #FFC107;
|
|
}
|
|
|
|
.error {
|
|
color: #F44336;
|
|
}
|
|
|
|
/* Force fullscreen for better safe area support */
|
|
@media screen and (display-mode: standalone) {
|
|
.bg {
|
|
top: calc(-1 * env(safe-area-inset-top));
|
|
height: calc(100vh + env(safe-area-inset-top));
|
|
}
|
|
|
|
.content {
|
|
padding-top: env(safe-area-inset-top);
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="bg"></div>
|
|
<div class="content">
|
|
<h1>Safe Area Fix Test v2</h1>
|
|
<div class="info">
|
|
<p class="success">✅ Using hardcoded fallback: -59px for Dynamic Island</p>
|
|
<p class="success">✅ Using max() function for reliable fallbacks</p>
|
|
<p class="success">✅ Supporting both env() and constant()</p>
|
|
<p class="warning">⚠️ Safari bug: env() returns 0 in portrait mode</p>
|
|
|
|
<p style="margin-top: 20px; font-weight: bold;">Visual Test:</p>
|
|
<p>🔴 Red should be visible in the notch area</p>
|
|
<p>📝 This text should be below the notch</p>
|
|
|
|
<p style="margin-top: 20px; font-weight: bold;">Debug Values:</p>
|
|
<p>Safe Area Top: <span id="safeTop">checking...</span></p>
|
|
<p>Computed Top Padding: <span id="computedPadding">checking...</span></p>
|
|
<p>Viewport Height: <span id="viewHeight">checking...</span></p>
|
|
<p>User Agent: <span id="userAgent">checking...</span></p>
|
|
|
|
<p style="margin-top: 20px; font-weight: bold;">Workaround Status:</p>
|
|
<p id="workaround" class="warning">Using hardcoded fallback values</p>
|
|
</div>
|
|
|
|
<div class="info" style="margin-top: 20px;">
|
|
<p style="font-weight: bold;">Try These Tests:</p>
|
|
<p>1. Rotate to landscape and back to portrait</p>
|
|
<p>2. Add to Home Screen for PWA mode</p>
|
|
<p>3. Check if red gradient extends to top</p>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
function detectDevice() {
|
|
const ua = navigator.userAgent;
|
|
const isIPhone = /iPhone/.test(ua);
|
|
const isIPad = /iPad/.test(ua);
|
|
const isIOS = isIPhone || isIPad;
|
|
|
|
// Detect specific iPhone models with notch/Dynamic Island
|
|
const hasNotch = isIPhone && screen.height >= 812; // iPhone X and later
|
|
const hasDynamicIsland = isIPhone && screen.height >= 852; // iPhone 14 Pro and later
|
|
|
|
return {
|
|
isIOS,
|
|
isIPhone,
|
|
hasNotch,
|
|
hasDynamicIsland,
|
|
screenHeight: screen.height,
|
|
screenWidth: screen.width
|
|
};
|
|
}
|
|
|
|
function updateDebugInfo() {
|
|
const device = detectDevice();
|
|
const styles = getComputedStyle(document.documentElement);
|
|
|
|
// Try to get safe area values
|
|
let safeTop = styles.getPropertyValue('padding-top') || '0px';
|
|
|
|
// Get computed padding on content
|
|
const content = document.querySelector('.content');
|
|
const computedPadding = window.getComputedStyle(content).paddingTop;
|
|
|
|
document.getElementById('safeTop').textContent = safeTop || '0px (Safari bug)';
|
|
document.getElementById('computedPadding').textContent = computedPadding;
|
|
document.getElementById('viewHeight').textContent = window.innerHeight + 'px';
|
|
document.getElementById('userAgent').textContent = device.isIPhone ?
|
|
(device.hasDynamicIsland ? 'iPhone 14/15 Pro' :
|
|
device.hasNotch ? 'iPhone with Notch' : 'iPhone') :
|
|
'Not iPhone';
|
|
|
|
// Update workaround status
|
|
const workaroundEl = document.getElementById('workaround');
|
|
if (parseInt(safeTop) > 0) {
|
|
workaroundEl.textContent = '✅ Safe area is working!';
|
|
workaroundEl.className = 'success';
|
|
} else if (device.hasDynamicIsland) {
|
|
workaroundEl.textContent = '⚠️ Using 59px fallback for Dynamic Island';
|
|
workaroundEl.className = 'warning';
|
|
} else if (device.hasNotch) {
|
|
workaroundEl.textContent = '⚠️ Using 44px fallback for notch';
|
|
workaroundEl.className = 'warning';
|
|
}
|
|
}
|
|
|
|
// Update on load and orientation change
|
|
window.addEventListener('load', updateDebugInfo);
|
|
window.addEventListener('orientationchange', () => {
|
|
setTimeout(updateDebugInfo, 100);
|
|
});
|
|
window.addEventListener('resize', updateDebugInfo);
|
|
|
|
// Check for standalone mode
|
|
if (window.navigator.standalone) {
|
|
document.body.classList.add('standalone');
|
|
}
|
|
</script>
|
|
</body>
|
|
</html> |