System/device combinations where the issue does not occur:
Physical device: iOS 26.0 (23A5318c) + iPhone 16 Pro Max
System/device combinations where the issue does occur:
System versions:
Physical device: iOS 26.0 (23A5330a), iOS 26.0 (23A340) Simulator: iOS 26.0 (23A339)
Device models:
Physical device: iPhone 12
Reproducible in Safari, WKWebView, and UIWebView:
Yes
Actual behavior
In WebView (and identically in Safari):
-
Before the keyboard is shown, header/footer elements with
position: fixed
are correctly aligned with the screen viewport. Scrolling up/down works as expected. -
After the keyboard appears, the
visualViewport
position changes. -
Bug: When the keyboard is dismissed,
visualViewport.offsetTop
does not reset to0
. As a result, fixed header/footer elements remain misaligned:- When scrolling down, the position looks correct.
- When scrolling up, the header/footer are visibly offset.
Steps to reproduce
- Focus an input field → the keyboard appears
- Dismiss the keyboard
- Observe that
visualViewport.offsetTop
remains >0 (does not reset to zero) position: fixed
header/footer elements are misplaced relative to the screen
Expected behavior
- After the keyboard is dismissed,
visualViewport.height
should return to match the layout viewport, andvisualViewport.offsetTop
should reset to0
. - When scrolling upward, fixed elements should remain correctly positioned within the layout viewport.
Minimal reproducible demo
A simple HTML file containing:
- A header and footer with
position: fixed
- An input element to trigger the keyboard
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
<title>H5 吸顶吸底页面 Demo</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, sans-serif;
height: 2000px; /* 设置内容高度 */
background-color: #f0f8ff; /* body 背景浅蓝色 */
padding-top: 120px; /* 预留 header 高度 */
padding-bottom: 60px; /* 预留 footer 高度 */
overflow-x: hidden;
}
/* 吸顶 Header */
header {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 120px;
background-color: #ff6b6b; /* 红色 */
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 24px;
font-weight: bold;
z-index: 1000;
}
/* 吸底 Footer */
footer {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 60px;
background-color: #4ecdc4; /* 青绿色 */
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 18px;
font-weight: bold;
z-index: 1000;
}
/* 输入框样式 */
.input-container {
margin: 100px auto;
width: 80%;
max-width: 600px;
text-align: center;
}
input[type='text'] {
padding: 12px;
font-size: 16px;
border: 2px solid #ddd;
border-radius: 8px;
width: 100%;
box-sizing: border-box;
}
input[type='text']:focus {
outline: none;
border-color: #4ecdc4;
}
</style>
</head>
<body>
<!-- 吸顶 Header -->
<header>吸顶 Header (120px)</header>
<!-- 主体内容 -->
<div class="input-container">
<input type="text" placeholder="请输入内容..." />
</div>
<!-- 吸底 Footer -->
<footer>吸底 Footer (60px)</footer>
</body>
</html>