在获取 favicon 时,存在一种情况是,对于有些域名,favicon service 爬取 favicon 失败,比如下面这个例子:
html
<img
src="https://www.google.com/s2/favicons?domain=【】&sz=【】"
alt="favicon"
/>
这时 favicon service 通常会给你返回一个 fallback image,但我的需求是,当获取 favicon 失败时,显示大写的域名首字母。那么这个需求要如何实现呢?
一、
首先,我们需要监听 img
的 error
事件。error
事件会在一个 resource 加载失败或无法使用时出发,比如,图片无法找到或无效时。
html
<img
data-favicon
/>
js
document.querySelectorAll("img[data-favicon]").forEach((img) => {
img.addEventListener("error", () => {
// Fired when the image can't be found or is invalid.
});
});
这里我们先给 img
添加了一个 data-favicon
属性,方便我们在脚本里选中该元素。然后遍历所有找到的目标元素,给它们分别绑定 error
事件。
二、
然后,我们先给 img
元素添加 data-fallback
属性。为了演示作用,下面这里的值是硬编码的。实际项目中,如果是用 React 的话,你可能是这样来设定的 -- data-fallback={new URL(url).hostname.charAt(0)}
。
html
<div class="favicon-wrapper">
<img
data-fallback="F"
/>
</div>
然后,在 error
事件的处理程序里,我们通过 dataset.fallback
来读取 fallback value,并给父元素添加一个 data-fallback
属性,值设定为刚才读取到的 fallback value。
js
img.parentElement.dataset.fallback = img.dataset.fallback;
三、
最后一步就要靠 CSS 来实现了。当父元素带有 data-fallback
属性时,我们先将 img 元素给隐藏掉,然后我们就可以绘制自己想要的 fallback shape 了。这里是通过伪元素来实现的。
css
.favicon-wrapper[data-fallback] {
& img {
display: none;
}
&::before {
content: attr(data-fallback);
color: gray;
font-size: 64px;
font-weight: 800;
text-transform: uppercase;
transform: rotate(-10deg);
}
}