说句实在话,折叠屏开发过程中踩过的坑,往往都源于一个看似简单的问题:你精心设计的按钮,怎么屏幕一展开,就恰好落在物理铰链那块“不能触、不能见”的死角上了?

铰链区域遮挡导致控件不可见?这样解决最有效
问题的关键,千万别再一味纠结于“居中没对齐”了。致命点在于,你用 justify-content: center 算出的那个完美坐标,在物理世界却是一片“虚无之地”——那里既不会渲染像素,也压根不响应任何点击事件。更扎心的是,Android 12 之后引进的 env(safe-area-inset-left) 等安全区方案,对于中间这条横跨屏幕的铰链是完全无效的。别再浪费时间测试它了。
- 首先,立刻放弃所有基于
window.innerWidth或screen.width的静态像素偏移计算。这两个值在折叠屏展开后,仍然返回的是整个屏幕的理论总宽度,但实际上,中间被铰链硬生生“掐断”了,可绘制区域是分隔开的。 - 其次,也别想着用 JavaScript 在
resize时暴力重排控件。高频的 DOM 操作不仅会导致明显卡顿,而且 resize 信号本身并不可靠。 - 真正可靠的信号其实是 CSS 的
display-fold特性。但注意,matchMedia('(display-fold: horizontal)')这个 API,目前仅在 Chrome Beta v125+ 和三星 One UI 6.1+ 这类较新的环境中支持。所以,一个健壮的 fallback 方案是绝对必要的。
@container hinge-safe 如何精准留出 2px 铰链安全间隙
这里的核心思路,从“躲着走”升级为“让布局自己知道是否跨过了铰链”。关键在于两步走:声明容器,然后条件化定义网格。
- 第一步,为你的主要内容容器(比如
)设置container-type: inline-size和container-name: hinge-safe,把它变成一个可被查询的容器。 - 第二步,使用容器查询(
@container)来精准命中条件:@container hinge-safe (min-width: 720px) and (aspect-ratio >= 2/1)。这个条件保证了只在屏幕展开且宽高比足够时(避免在竖屏小屏上误触发)才会应用特殊布局。 - 布局精髓在这里:
grid-template-columns: 1fr 2px 1fr。我们明确定义了三列布局,中间那 2px 的列,就是为铰链预留的安全间隙。给它加上pointer-events: none确保点击穿透,background: transparent让它视觉上隐形。 - 最重要的规则来了:所有可交互的控件(按钮、输入框、链接),只能放在第一列(
grid-column: 1)或第三列(grid-column: 3)。绝对,绝对不要使用grid-column: 2或者让元素跨越多列从而覆盖中间那 2px 区域。
为什么不能用 media query 判断 display-fold?最佳替代方案来了
你可能会问,CSS 媒体查询不是更优雅吗?遗憾的是,@media (display-fold: horizontal) 这条规则目前还停留在实验性阶段,绝大多数生产环境的浏览器都会直接忽略它。写了也是白写。
- 去
caniuse.com查一下就知道,Chrome Stable 稳定版、Firefox、Safari 都尚未实现这个媒体查询,基本全是“No support”。 - 所以,务实的 fallback 方案必须上马。一个有效的组合拳是:
matchMedia('(display-mode: standalone)')(判断是否是 PWA 应用模式) +matchMedia('(min-aspect-ratio: 4/3)')(捕获展开后的宽屏状态) +window.innerHeight > 800(进一步排除某些窄高的小屏设备)。 - 别忘了防抖。监听媒体查询变化时,一定要加上防抖:
mediaQuery.addEventListener('change', debounce(updateHingeClass, 100)),否则折叠/展开的频繁触发会导致严重的布局抖动(layout thrashing)。
折叠态和展开态切换时状态丢失怎么防?这招最稳
铰链避让解决了“看得见、点得着”的问题,但别忘了,用户在折叠与展开之间,体验必须是连续的。Activity 重建导致页面刷新、滚动位置瞬间跳回顶部、辛苦输入的表单一键清空……这些问题和布局无关,却直接关系到用户会不会骂人。
- 对于 Android 端的 WebView 或混合应用,必须在
AndroidManifest.xml中为对应 Activity 声明configChanges="screenSize|smallestScreenSize|screenLayout|orientation"。这是告诉系统:“屏幕配置变化了,别急着销毁重建我的页面,让我自己处理。”否则,系统默认行为就是销毁并重启,所有状态归零。 - 对于纯 Web 端,要主动利用
sessionStorage或localStorage来缓存关键状态。例如,定时保存textarea里的内容、scrollTop的滚动位置,并在页面重新加载(DOMContentLoaded)后立即恢复。 - 这里有个陷阱:别依赖
onbeforeunload事件来保存状态,因为在设备折叠/展开的瞬间,这个事件很可能不会触发。更可靠的监听对象是visibilitychange事件(document.visibilityState),它更能捕捉到页面被挂起或恢复的时机。
说到底,铰链避让真正的复杂度,远不止 CSS 怎么写。它要求你同时处理好三件事:布局容器是否跨越了物理铰链、当前系统是否支持最新的特性 API、用户的操作状态在不同屏幕形态下能否无缝衔接。这三环,缺少任何一环,都会让用户在满怀期待展开屏幕的瞬间,遭遇“点不到按钮、输不了字、找不到刚才看到哪了”的糟糕体验。
