如何基于背景色使用mix-blend-mode设置焦点轮廓样式
问题原因
- 无效伪元素定义:
.button::after没有设置content: ''及布局属性,不会实际渲染,属于冗余无效代码 - 混合范围错误:直接给元素本身设置
mix-blend-mode: difference会导致元素内的文字、背景等所有内容都参与混合,而非仅焦点轮廓参与混合 - outline混合兼容性问题:部分浏览器下元素外轮廓
outline的混合上下文计算存在异常,无法正确和下层背景做差值计算
修复方案
用独立的绝对定位伪元素绘制焦点轮廓,仅对伪元素开启差值混合,既可以保证只有轮廓参与和背景的颜色计算,不会影响元素本身的内容显示,兼容性也更好。
完整修复代码
HTML
<div class="container"> <a class="button">a button</a> <h4><a href="#">Inline text element</a></h4> </div>
CSS
body { font-family: "Roboto", sans-serif; font-size: 16px; display: flex; align-items: center; justify-content: center; height: 100vh; /* 可切换为white测试效果 */ background: blue; } h4 { font-size: 24px; } a { text-decoration: none; color: white; position: relative; } .button { background: grey; color: white; padding: 1rem 1.5rem; border-radius: 4px; text-transform: uppercase; } /* 给所有需要焦点轮廓的元素设置相对定位,用于锚定伪元素 */ button, input[type=checkbox], input[type=radio], input[type=submit] { position: relative; } button:focus-visible, a:focus-visible, input[type=checkbox]:focus-visible, input[type=radio]:focus-visible, input[type=submit]:focus-visible { /* 清除默认轮廓,改用伪元素绘制 */ outline: none; } /* 统一用伪元素绘制焦点轮廓,仅对伪元素做混合 */ button:focus-visible::after, a:focus-visible::after, input[type=checkbox]:focus-visible::after, input[type=radio]:focus-visible::after, input[type=submit]:focus-visible::after { content: ''; position: absolute; /* 匹配原outline-offset: 4px的位置 */ top: -4px; left: -4px; right: -4px; bottom: -4px; border: 2px solid #fff; border-radius: inherit; pointer-events: none; mix-blend-mode: difference; }
JS
document.querySelectorAll("a:not(a[href])").forEach((element) => { element.setAttribute("href", "#"); });
修复后切换body的background为white时,焦点轮廓会自动计算为和背景差值最大的高对比度颜色,可正常显示。
内容的提问来源于stack exchange,提问作者Millhorn
相关产品推荐
相关产品推荐

