TailwindCSS奇技淫巧:GroupHover诈尸?没关系
最近在写一个图片预览组件时遇到个烦人的问题 - 我需要在hover图片时显示一个遮罩和放大按钮,但这个hover效果总是被父元素触发,搞得整个交互体验很怪异。
你可能会说:"这不简单吗?用个group
和group-hover
不就搞定了?"
我一开始也是这么想的:
<div className="group">
<img className="group-hover:brightness-90" />
</div>
但问题就在这儿 - 如果父元素本身就是个可点击的卡片,那用户只要碰到卡片,图片就会变暗。这体验...emmm...说实话有点糟心。
灵光一闪
正当我一筹莫莫的时候,突然想到:要是能精确控制hover的范围就好了。等等,CSS变量是不是可以派上用场?
试了一下这个方案:
<div className="[--hover:0] hover:[--hover:1]">
<img className="brightness-[calc(100%-10%*var(--hover))]" />
</div>
卧槽,还真行!这就像是给每个元素都装了个独立的开关,hover的时候开关打开,离开就关闭,完全不受外界干扰。
这是怎么做到的?
简单来说就是:
- 默认状态下,
--hover
值是0 - 鼠标悬停时,值变成1
- 用这个0和1来计算具体的效果
你可以把它想象成一个亮度调节器:
- 没hover时调节器在0位置
- hover时调节器推到最大
- 中间的过渡由CSS动画负责
实战应用
来看看实际项目中的完整代码:
<div
className="
relative
[--hover:0]
hover:[--hover:1]
"
>
<img
src="/cute-cat.jpg"
className="
transition-all
duration-200
brightness-[calc(100%-10%*var(--hover))]
dark:brightness-[calc(100%-25%*var(--hover))]
"
/>
{/* 放大按钮 */}
<ZoomIcon className="
absolute
center
opacity-[var(--hover)]
"/>
</div>
注意看暗色模式下我们把亮度调整得更大一些(25%),因为暗色模式下需要更明显的对比度。
还能怎么玩?
这招不只能用在hover效果上。比如:
- 做个进度条:
<div className="[--progress:0] data-[loading=true]:[--progress:1]">
<div className="w-[calc(100%*var(--progress))]" />
</div>
- 搞个动画:
<div className="[--bounce:0] hover:[--bounce:1]">
<div className="translate-y-[calc(-10px*var(--bounce))]">
我能跳!
</div>
</div>
说点实在的,这招虽好,但也有几个坑要注意:
- IE:别想了,不支持(不过现在还有人用IE吗?)
- 计算太复杂容易卡,点到为止就行