TailwindCSS奇技淫巧:GroupHover诈尸?没关系

TailwindCSS奇技淫巧:GroupHover诈尸?没关系

最近在写一个图片预览组件时遇到个烦人的问题 - 我需要在hover图片时显示一个遮罩和放大按钮,但这个hover效果总是被父元素触发,搞得整个交互体验很怪异。

你可能会说:"这不简单吗?用个groupgroup-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的时候开关打开,离开就关闭,完全不受外界干扰。

这是怎么做到的?

简单来说就是:

  1. 默认状态下,--hover值是0
  2. 鼠标悬停时,值变成1
  3. 用这个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效果上。比如:

  1. 做个进度条:
<div className="[--progress:0] data-[loading=true]:[--progress:1]">
  <div className="w-[calc(100%*var(--progress))]" />
</div>
  1. 搞个动画:
<div className="[--bounce:0] hover:[--bounce:1]">
  <div className="translate-y-[calc(-10px*var(--bounce))]">
    我能跳!
  </div>
</div>

说点实在的,这招虽好,但也有几个坑要注意:

  1. IE:别想了,不支持(不过现在还有人用IE吗?)
  2. 计算太复杂容易卡,点到为止就行