H5页面在折叠屏上的适配需要兼顾屏幕形态变化、交互体验和内容展示逻辑,以下是一套系统的适配方案,结合技术实现与最佳实践:
一、核心适配原则
- 状态感知优先:通过API精准识别折叠/展开状态,实现布局的精准切换
- 空间弹性利用:折叠时聚焦核心内容,展开时充分利用双屏空间
- 避免折痕遮挡:关键元素远离物理折痕区域
- 体验一致性:切换状态时保持操作连贯性(如滚动位置、表单状态)
二、技术实现方案
1. 折叠状态检测与监听
利用浏览器提供的折叠屏API,精准判断设备状态:
// 初始化检测折叠状态
function checkFoldState() {
// 支持视口分段API的浏览器
if (window.getWindowSegments) {
const segments = window.getWindowSegments();
const isUnfolded = segments.length > 1;
document.documentElement.classList.toggle('folded', !isUnfolded);
document.documentElement.classList.toggle('unfolded', isUnfolded);
// 记录折痕位置(如果有)
if (isUnfolded) {
const foldPosition = segments[0].width; // 假设左屏宽度即为折痕位置
document.documentElement.style.setProperty('--fold-position', `${
foldPosition}px`);
}
}
}
// 初始化检测
checkFoldState();
// 监听屏幕变化
window.addEventListener('resize', checkFoldState);
window.addEventListener('orientationchange', checkFoldState);
2. 布局适配方案
使用CSS变量和媒体查询结合,实现不同状态的布局切换:
/* 基础样式 */
.container {
width: 100%;
min-height: 100vh;
padding: 16px;
box-sizing: border-box;
}
/* 折叠状态(单屏) */
.folded .content-layout {
display: flex;
flex-direction: column;
gap: 20px;
}
.folded .sidebar {
display: none; /* 折叠时隐藏次要内容 */
}
.folded .main-content {
width: 100%;
}
/* 展开状态(双屏) */
.unfolded .content-layout {
display: grid;
grid-template-columns: 35% 65%; /* 左右分栏 */
gap: 24px;
}
.unfolded .sidebar {
display: block; /* 展开时显示侧边栏 */
position: sticky;
top: 16px;
align-self: start;
}
/* 避开折痕区域 */
.critical-element {
/* 关键元素远离折痕位置 */
margin-right: max(24px, calc(100vw - var(--fold-position) + 16px));
}
/* 安全区域适配 */
.safe-area {
padding: env(safe-area-inset-top) env(safe-area-inset-right)
env(safe-area-inset-bottom) env(safe-area-inset-left);
}
3. 交互体验优化
// 状态切换时保存滚动位置
let scrollPositions = {
folded: 0, unfolded: 0 };
function handleStateChange() {
// 保存当前状态的滚动位置
const currentState = document.documentElement.classList.contains('unfolded') ? 'unfolded' : 'folded';
scrollPositions[currentState] = window.scrollY;
// 恢复目标状态的滚动位置
const targetState = currentState === 'folded' ? 'unfolded' : 'folded';
window.scrollTo(0, scrollPositions[targetState] || 0);
// 触发重绘动画
document.body.classList.add('transitioning');
setTimeout(() => document.body.classList.remove('transitioning'), 300);
}
// 监听状态变化
const observer = new MutationObserver(handleStateChange);
observer.observe(document.documentElement, {
attributes: true, attributeFilter: ['class'] });
4. 媒体资源适配
<!-- 响应式图片 -->
<picture>
<source media="(min-width: 1000px)" srcset="large-image.jpg"> <!-- 展开状态 -->
<source media="(max-width: 999px)" srcset="small-image.jpg"> <!-- 折叠状态 -->
<img src="fallback.jpg" alt="响应式图片" class="responsive-img">
</picture>
<style>
.responsive-img {
width: 100%;
height: auto;
object-fit: cover;
}
.unfolded .responsive-img {
/* 展开状态下更高分辨率 */
image-rendering: -webkit-optimize-contrast;
}
</style>
三、测试与调试策略
- 设备模拟:使用Chrome DevTools的"Device Toolbar",选择"Foldable"设备预设
- 真实设备测试:重点测试三星Galaxy Z Fold系列、华为Mate X系列等主流机型
自动化检测:
// 简单的适配检测脚本 function testFoldAdaptation() { const testCases = [ { name: '折叠状态布局', check: () => document.querySelector('.folded .main-content')?.offsetWidth === window.innerWidth }, { name: '展开状态分栏', check: () => document.querySelector('.unfolded .content-layout')?.gridTemplateColumns === '35% 65%' }, { name: '折痕区域避开', check: () => { const criticalEl = document.querySelector('.critical-element'); return criticalEl ? criticalEl.getBoundingClientRect().right < parseInt(getComputedStyle(document.documentElement).getPropertyValue('--fold-position')) - 16 : false; }} ]; testCases.forEach(test => { console.log(`${ test.name}: ${ test.check() ? '✓' : '✗'}`); }); }
四、适配注意事项
- 避免使用固定像素宽度,优先采用相对单位(
%、vw、fr) - 关键交互元素(按钮、输入框)尺寸在折叠状态下不小于44×44px,保证可点击性
- 视频/Canvas元素需监听尺寸变化,及时调整渲染比例
- 针对外折机型,考虑折痕处的视觉过渡处理(如添加渐变阴影)
通过以上方案,可实现H5页面在折叠屏设备上从"基本兼容"到"体验优化"的跨越,确保用户在不同折叠状态下都能获得一致且高效的使用体验。