之前我们在hexo-iconify插件让你能够使用所有iconify图标中通过iconify官网所提供的api实现了一个给hexo博客轻松引入iconify图标的插件,这个插件通过icon这一helper,将图标以svg内联的方式写入网页中,虽然是按需引入,对于单个页面来说没有其他额外负担,但是在实际使用中,我们的网站是多页面的,很多图标被重复使用,但是由于是内联引用的,没法复用,造成了一定程度上资源的浪费。突然感觉又回到了iconfont了
于是我又去翻了官方文档,找到了svg in css这一章节,发现了iconify也提供了类似于iconfont这种通过css来引入的方法,与iconfont使用字体不同,iconify使用的是mask-image来将图标显示出来,之所以使用mask-image而不是background,主要还是因为mask-image能够使用currentColor来进行图标颜色的更改
于是我对原本的插件进行升级,在原有基础上,新增了icons这一helper,让你能够轻松的引入css图标
主要原理
其实也不难去想怎么实现这一功能,svg生产datauri相对比较容易,不需要base64编码,我们在helper部分返回类名,在渲染时将使用到的图标及类名注入css文件中即可
hexo.extend.helper.register(
'icons',
function (iconName: string, fileName?: string) {
return getIconClass(iconName, fileName)
},
)
hexo.extend.filter.register('after_render:css', function (str, data) {
let defaultFile = 'icons.css'
if (hexo.config.iconify?.file) {
defaultFile = hexo.config.iconify.file
}
saveIcons.forEach((value, key) => {
const fileName = value.file || defaultFile
if (data.path.includes(fileName)) {
hexo.log.info(`iconify: 写入图标 ${key} 到 ${fileName}`)
str += `.${key}{--svg:url("${value.data}");}`
}
})
return str
})
当然我们需要事先设置好基类 icons 的样式,我们在css文件中添加以下内容
.icons {
display: inline-block;
width: 1em;
height: 1em;
vertical-align: -.15em;
background-color: currentcolor;
mask: no-repeat center / 100%;
mask-image: var(--svg);
}
优缺点
好处是集中了显示效果与体积相对比iconfont好,资源复用比svg inline好,能够自定义插入到哪个css文件(我们可以把首屏显示的放到主要css中,将那些一开始用户不可见或者需要下滑可见的放到非核心css中,保证用户体验)
缺点,主要集中在mask的兼容性问题,对于我来说是足够的,因为他除了ie都兼容,更何况svg本身在ie上就存在兼容性问题