改变svg图标颜色

背景

前段时间做的一个需求,菜单的图标是通过接口返回,且在不同主题下使用不同的颜色。 接到这个需求,大脑立刻想到的做法是接口配置了N套不同主题的图标。这种做法,可能会带来的一个问题是,当存在多套主题时,同一个系统就要配置多套图标。但有时候,主题与主题之间的不同点仅仅是配色。如何通过只配置一套图标,就能在不同的主题下渲染为相应的颜色,这是这篇文章的背景了。

filter

在网络上,搜索css改变svg图标颜色,最多的推荐方式是使用css的filter,于是,我立马动起手来。

html 复制代码
<span class="menu-item-wrapper">
    <span id="menuSpan" class="menu-item-icon" />
</span>
css 复制代码
.menu-item-wrapper{
    display: inline-block;
    width: 128px;
    height: 128px;
    overflow: hidden;
}
.menu-item-icon{
    display: inline-block;
    width: 128px;
    height: 128px;
    filter: drop-shadow(#474F5E -128px 0);
    background-image: url(./home.svg);
    transform: translateX(128px);
}
.menu-item-wrapper:hover .menu-item-icon{
    filter: drop-shadow(red -128px 0);
}

在Chrome的效果如下:

初始状态:

鼠标hover后改变颜色:

但是在safari浏览器下,却会因为父元素overflow:hidden导致图标无法显示。在移动端浏览器的效果,也存在兼容问题。虽然可以通过各种修修补补的方式实现目的,但让人难受,总要担心没有测试到的浏览器,显示会异常。

-webkit-mask-box-image

虽然是不标准的语法,但是,它在safari的效果,却让人满意。

html 复制代码
<!DOCTYPE html>
<html>
    <head>
        <style>
            .menu-item-wrapper{
                display: inline-block;
                width: 30px;
                height: 30px;
                overflow: hidden;
            }
            .menu-item-wrapper:hover .menu-item-icon{
                background-color: red;
            }
            .menu-item-icon{
                display: inline-block;
                width: 30px;
                height: 30px;
                background-color: #474F5E;
                -webkit-mask-box-image: url('./home.svg') 0 0;
            }
        </style>
    </head>
    <body>
        <div>
            <span id="menuSpanWrapper" class="menu-item-wrapper">
                <span id="menuSpan" class="menu-item-icon" />
            </span>
        </div>
    </body>
</html>

初始状态:

鼠标hover后改变颜色:

当然,它也不是没有坑的,它在firefox下是不支持的。

最终方案

综合了这两个样式的特点,于是,我想到了个折中的方式: Chrome、safari,使用-webkit-mask-box-image firefox,使用filter

html 复制代码
<!DOCTYPE html>
<html>
    <head>
        <style>
            .menu-item-wrapper{
                display: inline-block;
                width: 128px;
                height: 128px;
                overflow: hidden;
            }
            .menu-item-wrapper:hover .menu-item-icon{
                background-color: red;
            }
            .menu-item-icon{
                display: inline-block;
                width: 128px;
                height: 128px;
                background-color: #474F5E;
            }
            .menu-item-icon.firefox{
                background-color: unset;
                filter: drop-shadow(#474F5E -128px 0);
                transform: translateX(128px);
            }
            .menu-item-wrapper:hover .menu-item-icon.firefox{
                background-color: unset;
                filter: drop-shadow(red -128px 0);
            }
        </style>
    </head>
    <body>
        <div>
            <span id="menuSpanWrapper" class="menu-item-wrapper">
                <span id="menuSpan" class="menu-item-icon" />
            </span>
        </div>
    </body>

    <script>
        const isFirefox = /firefox/i.test(navigator.userAgent)

        const menuSpanEl = document.getElementById('menuSpan')
        if(isFirefox) {
            menuSpanEl.classList.add('firefox')
            menuSpanEl.style.backgroundImage = 'url("./home.svg")'
        }else{
            menuSpanEl.style.webkitMaskBoxImage = 'url("./home.svg") 0 0'
        }
    </script>
</html>
相关推荐
陈随易36 分钟前
bm2,Node.js 与 Bun 项目部署新选择
前端·后端·程序员
福兮说2 小时前
canvas 旋转图片的六个坑:四角被裁、Math.ceil 多出 1px 黑边、JPG 角发黑、翻转方向反了
前端·javascript·图像处理·canvas
传人once3 小时前
多图片上传预览功能如何写
前端·css·html·jquery·html5
Eric.464 小时前
Wan‑Animate+MiniMax-H3 本地部署 AI 漫剧流水线:8G 显存动作迁移与动态分镜工程实战
前端·人工智能·comfyui·ai漫剧
传人once5 小时前
悬停旋转放大和位移效果如何写
javascript·css·动画
库拉镜像AI牛牛5 小时前
短剧内容自动化生产:知漫剧工作室落地教程
大数据·服务器·前端·人工智能·语音识别
律宏阔5 小时前
Flutter 列表图片内存优化:CachedNetworkImage 与 ClipRRect 的取舍
前端·flutter
行者全栈架构师5 小时前
【鸿蒙心迹】相册文搜图工程化落地:HarmonyOS 7.0 端侧 AI 检索全链路实战与 5 个踩坑解法
前端
律宏阔5 小时前
Dart 3 Record:解决 Future.wait 异构返回值的类型问题
前端·flutter
Seraphina366 小时前
DVWA(XSS Reflected/Stored High,CSRF Low)
前端·xss·csrf