mix-blend-mode异常表现:父元素设为100vh时混合效果变化
mix-blend-mode 异常表现分析及解决方案
问题复现代码
body { background: blue; } main { width: 2rem; height: 10rem; background: blue; } div { position: absolute; width: 5rem; height: 5rem; mix-blend-mode: screen; } div:nth-child(1) { background: red; } div:nth-child(2) { top: 2rem; background: green; }
<main> <div></div> <div></div> </main>
现象描述
- 初始状态下,div仅与彼此及
main元素的背景混合,视觉上未与body的蓝色背景产生混合效果 - 将
main的height设为100vh后,div超出main宽度的区域开始与body背景混合,颜色出现明显变化 - 即便移除
main的背景,其高度变化仍会影响div的混合范围
原因解析
这不是Chrome的Bug,而是mix-blend-mode遵循的混合上下文规则导致的:
- 当元素设置
mix-blend-mode后,会和所在混合上下文内的背景、其他元素进行混合 - 初始状态下,两个div的整体都处于
main的垂直范围内,且main与body背景同为蓝色,视觉上无法区分div和谁混合;当main高度改为100vh后,div超出main宽度的部分直接暴露在body背景上,这部分就会触发与body的混合 - 混合范围由元素的可见覆盖区域决定,和容器是否有背景无直接关联
需求实现方案(容器内div仅彼此混合)
要让容器内的div仅互相混合,不与容器背景或外部元素混合,可通过isolation: isolate为容器创建隔离的混合上下文,同时调整容器背景的实现方式:
方案代码
body { background: blue; } main { width: 2rem; height: 10rem; /* 创建隔离混合上下文,限制内部混合范围 */ isolation: isolate; position: relative; } /* 用伪元素承载容器背景,避免与div混合 */ main::before { content: ''; position: absolute; inset: 0; background: blue; /* 伪元素置于div下方,不参与混合计算 */ z-index: -1; } div { position: absolute; width: 5rem; height: 5rem; mix-blend-mode: screen; } div:nth-child(1) { background: red; } div:nth-child(2) { top: 2rem; background: green; }
原理说明
isolation: isolate让main成为独立的混合上下文,内部div仅会与上下文内的其他div混合- 将容器背景移至伪元素并设置
z-index: -1,使背景处于div层级下方,不会参与div的混合计算 - 该方案兼容Chrome、Firefox、Safari等主流现代浏览器
内容的提问来源于stack exchange,提问作者fweth
相关产品推荐
相关产品推荐

