currentColor的使用场景

136 阅读2分钟

web开发框架带来的新思考

随着 astroqwiknextjs13 等框架的出现,人们逐渐开始思考究竟有多少代码需要被发送到客户端中,简单的 html + js + css 能够使TTI(time to interactive 可交互时间)的效率大幅提升。 solidjssvelet 等框架抛弃了虚拟DOM,他们选择了一种能够直接查找到变化的元素,并进行局部渲染的策略,这种策略也在 react 的虚拟DOM的性能优化框架 million 中被使用。

于是我们现在要讨论这样一种情况:当离开了 react、vue 带给我们的响应式渲染功能,在简单的 html + js + css 中,怎样给页面带来一些简单的交互效果——比如切换暗黑模式。

5.gif

可以看到,随着切换模式,图片的样式也随之点亮,如果我们使用的是 svg 图片,我们可以很容易在 react 简单封装一个组件:

function Svg({color}){
	return (
		<svg ...>
			<path d="..." fill={color}></path>
		</svg>
	)
}

当我们在切换模式时,给这个组件传入对应的 color ,就可以实现图中的点亮效果。但如果没有了 react 的帮助,可能我们就需要通过 document.querySelector(svg path) 选中里层的元素,并对其修改 fill 属性的颜色。 但我们举的是一个极简例子,如果元素层级更深,并且要维护多个 svg 元素,则这种 js 代码很快会变得繁琐起来。

使用currentColor

这时有一个 css 属性可以帮上我们忙: currentColor 。它表示取该元素上的 color 属性作为颜色。这是一个使用示例:

<div color="red">
	<svg>
		<path fill="currentColor" />
	</svg>
</div>

因为 color 是一个 可继承属性 ,因此 svgpath 会一层一层继承最外层 div 的红色 color 。而我们又为 pathfill 设置了 currentColor 值,于是最终我们得到了 <path fill="red" /> .

因此我们用 js 修改最外层的属性名,来实现暗黑模式的切换效果,以下是简单的示例代码:

<html class="dark">
	<body>
		<!--... -->
		<svg id="light_icon"><path d="..." fill="currentColor" /></svg>
		<svg color="#FF7D33" id="dark_icon"><path d="..." fill="currentColor" /></svg>
		<!--... -->
	</body>

	<script>
	  const darkBtn = document.querySelector("#dark_icon");
	  const lightBtn = document.querySelector("#light_icon");
	  const html = document.querySelector("html");
	
	  darkBtn?.addEventListener("click", () => {
	    html?.classList.add("dark");
	    darkBtn.setAttribute('color' , '#FF7D33')
	    lightBtn?.setAttribute('color' , '#2c2c2c')
	  });
	
	  lightBtn?.addEventListener("click", () => {
	    html?.classList.remove("dark");
	    darkBtn?.setAttribute('color' , '#2c2c2c')
	    lightBtn.setAttribute('color' , '#FF7D33')
	  });
	</script>
</html>

6.gif

总结

currentColor 给原生 html + js + css 开发带来了一定便利。混合渲染模式的场景下,还有多少组件应该放在客户端渲染依然是一个值得讨论的问题。