SVG图标在浅色模式下不显示的原因及修复方案
问题:SVG锚点图标在浅色模式下不可见,深色模式正常显示
问题场景
使用以下HTML和CSS实现标题锚点图标,hover时显示图标:
HTML代码
<h2 class="mt-10 scroll-m-20 border-b pb-1 text-3xl font-semibold tracking-tight first:mt-0" id="know-your-life"> <a aria-hidden="true" tabindex="-1" href="#know-your-life"> <span class="icon icon-link"></span> </a> Know your life </h2>
CSS代码
:where(h1, h2, h3, h4, h5, h6) { position: relative; } :where(h1, h2, h3, h4, h5, h6) span.icon.icon-link { display: none; } :where(h1, h2, h3, h4, h5, h6):hover span.icon.icon-link { display: inline; background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill="%23000000" fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg>'); background-repeat: no-repeat; background-position: center center; background-size: 0.8em; height: 0.8em; width: 0.8em; padding-left: 1em; padding-right: 0.5em; cursor: pointer; } /* Dark mode icon */ @media (prefers-color-scheme: dark) { :where(h1, h2, h3, h4, h5, h6):hover span.icon.icon-link { filter: invert(1); } }
原因分析
- SVG图标固定设置了黑色填充(
fill="%23000000"),若浅色模式下页面背景为白色,且标题文本也为黑色,图标会与文本颜色融合,对比度极低导致视觉上完全不可见; - 深色模式下通过
filter: invert(1)将黑色图标转为白色,适配深色背景所以正常显示,但这种写法依赖背景色,灵活性差。
修复方法
推荐使用currentColor让图标自动继承标题文本颜色,无需单独适配深色模式:
修改后的CSS代码
:where(h1, h2, h3, h4, h5, h6) { position: relative; } :where(h1, h2, h3, h4, h5, h6) span.icon.icon-link { display: none; } :where(h1, h2, h3, h4, h5, h6):hover span.icon.icon-link { display: inline; /* 关键修改:将fill改为currentColor,继承父元素文本颜色 */ background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill="currentColor" fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg>'); background-repeat: no-repeat; background-position: center center; background-size: 0.8em; height: 0.8em; width: 0.8em; padding-left: 1em; padding-right: 0.5em; cursor: pointer; } /* 可删除深色模式的filter代码,currentColor会自动适配文本颜色 */
原理说明
currentColor是CSS内置变量,会自动继承当前元素或父元素的color属性值。修改后:
- 浅色模式下,标题文本为黑色,图标也会显示为黑色,与白色背景形成足够对比度;
- 深色模式下,若标题文本切换为白色,图标也会同步变为白色,完美适配深色背景;
- 无需依赖
filter,代码更简洁且兼容性更好。
内容的提问来源于stack exchange,提问作者Rasik
相关产品推荐
相关产品推荐

