颠覆你认知,令你疯狂的CSS技巧:has(),+和*🚀🚀—你正在摆脱JavaScript的控制!!😱

3,097 阅读8分钟

前言

我敢说,这是整个掘金社区绝无仅有的讲解,学好他能极大减少JavaScript的书写和依赖,提高网站的渲染速度。

如果本文对你有帮助,请在评论区扣个666之类的,如果你不认同,也请大佬们提出您的意见🚀

你们评论我才能知道我写的东西对你们有没有用,都不说话我都不知道该更新什么了😭

加油不要忘了点赞和收藏以及关注,这是对我更新文章最大的动力。

我会持续更新劲爆的内容,颠覆整个掘金社区对css的认知。

先叠个保护壳:作者才大二能力有限,各位大佬如果发现有不认同的地方,请大家轻点喷🙏

讲解

本文将会提到:什么是*,+以及二者结合代表什么。还有如何使用has选中先前的元素。

大家是否都遇到过这种情况,当我们鼠标放在一个图片上,我们不仅想让当前的图片悬停,并且周围的图片也要出现同样的效果。 image.png

我在看有些工作几年前端程序员写这种效果,如果不借助库的话甚至需要写JavaScript😧!!!😱哦,天呐!简直糟糕透顶😵‍💫,这是要干嘛!!!🔥

我们都知道JavaScript涉及的相关操作在浏览器中是非常消耗性能的,大多情况下能用CSS替代就不要用JavaScript

现在让我来用纯CSS带你实现它!!!🚀🚀🎇🎇

    .layout-container {
      transform-style: preserve-3d;
      transform: perspective(1000px);
    }

    .layout-container .item {
      transition: .5s;
      filter: brightness(0);
    }

    .layout-container .item:hover {
      filter: brightness(1);
      transform: translateZ(200px);
    }

Recording%202024-12-22%20125054_converted.gif 很好😄,这个很简单不是吗?我相信大部分人都能实现这个效果

我们来加大难度,如果我们要做到鼠标移动到当前图片,并且其右边的图片也要产生悬浮效果,怎么做?

你是不是第一反应是JavaScript,然后querySelectorAll加循环?如果你是这种想法,那么恭喜你,这篇文章对您来说是个宝藏。

不卖关子了😋,告诉你们,根本不需要!!!😡,只需加两个字符给你完美解决🚀

+

.layout-container .item:hover + .item {
      filter: brightness(0.6);
      transform: translateZ(150px) rotateY(40deg);
} 

吼吼吼😄,这不轻松的一批?还写什么JavaScript,都给我去写CSS!😡 Recording%202024-12-23%20130552_converted.gif 我们在hover后面写了个+ .item,什么意思呢?

  • +的意思是:+ 这个符号是相邻兄弟选择器,选中它的兄弟节点元素。(上面的视频因为做成gif被抽帧了,所以你可能会看左边的图片被选中的情况,实际上是没有的。)

注意,它只能选到后面的兄弟节点!!!😡,也就是我们只能选到与它相邻的右边的图片,无法选到相邻的左边图片。很多所谓的博客和教程千篇一律的AI水文,这对开发者进步来说极不友好。

  • + .item的意义就很明了,选中相邻的并且名字叫item的元素。

来,让我们思考一下这种方法有什么弊端?🤔

不卖关子了😄,缺点是假如我元素的类名换了,难道我的CSS也要跟着改动吗?这及不利于耦合。

那我们有什么办法解决它呢?如果你不知道的话,这篇文章对您来说绝对是个宝藏!🚀

*

没错就是这个简单的*号,先卖个关子,不说它的作用是啥,先看代码和效果。

    .layout-container .item:hover + * {
      filter: brightness(0.4);
      transform: translateZ(70px) rotateY(20deg);
    }

Recording%202024-12-23%20130552_converted.gif 可以发现,效果一模一样!!!🚀,这不就完美解决了耦合度过高的问题了吗?

我现在来解释+ *的意思。

-* 是通配选择器,它可以匹配任何元素,不管它是 divpspan 等任何 HTML 标签所对应的元素,所以这里只要它是符合前面相邻兄弟选择规则的那个元素,就会被选中并应用后续的样式规则。

这整段代码的意思是,当鼠标悬停在 .layout-container 类下的 .item 元素上时,其后面紧邻的那个兄弟元素(不管是什么类型的元素)会被选中,即相邻的图片被选中。

知道这些我们就可以玩骚操作了。

来看这段代码

    .layout-container .item:hover + * + * {
      filter: brightness(0.4);
      transform: translateZ(70px) rotateY(20deg);
    }

这里我们又写了一个+ *,我相信大佬们都能看出来这是什么意思,这表明选中兄弟和兄弟的兄弟。就是选中当前图片的下一张图片以及下一张图片的下一张图片。

有些绕口🥵,我们直接上图,

image.png

呼~ 爽啦,清晰明了~😋

继续提问!我们已经完成选中相邻的图片了,但是都是当前图片的右边,我们有没有办法选中当前图片的左边呢,也就是在它前面的节点。

实话实说,没有😭。至少在我在我的印象中,没有发现有任意一个属性只靠自己能选中前面的节点元素。

作者大大真的没有吗😰?咳咳,当然有,我们用JavaScript,然后querySelectorAll……,你以为我会继续说下去吗😒?告诉你不需要用!!

虽然单一的属性不能,但是不代表我们组合起来不行啊。

接下来你们将看到一个极为逆天的用法。

逆天的has()

我们或多或少都用过has(),为了避免有萌新没用过,这里简单介绍一下has()

(has()这个伪类选择器很值得去学习,希望大家能去认认真真学习这个元素🙏)

:has() 是一种伪类选择器,也被称为 “关系选择器”,它允许你根据元素是否包含特定的其他元素(满足括号内指定的条件)来选择该元素本身。

举个例子,比如

.box:has(.selected){
      background-color: red;
}
<div class="box">
    <span class="selected">我是被选中的元素🚀</span>
</div>

image.png .box:has(.selected)这串代码的意思是选中box中类名为selected的元素。

现在知道它的作用了吗?不知道就多理解一下,我们现在直接上代码。

    .layout-container .item:has(+ *:hover) {
      filter: brightness(0.6);
      transform: translateZ(150px) rotateY(-40deg);
    }

Recording%202024-12-23%20133732_converted.gif Perfect!我们做到了!😄,成功选中了当前图片左边的图片。

我现在来解释has(+ *:hover)这串代码是什么意思。

先来看(+ *:hover)这串代码,hover是鼠标移入,我们通过上面的学习已经知道了+是选择兄弟元素,*是通配符,选择任意元素,这串代码的意义已经很明显了:

鼠标移入的元素的上一个元素就是目标元素

has(+ *:hover)这串代码的意思我想大家也知道了,就是选中鼠标移入的元素的上一个元素。 Perfect,我们完美找到了上一个元素。🔥

知道这些我们也可以进行骚操作了

.layout-container .item:has(+ * + *:hover) {
      filter: brightness(0.6);
      transform: translateZ(70px) rotateY(-20deg);
    }

Recording%202024-12-23%20163611_converted.gif

(+ * + *:hover)这串代码相信我也不用再解释了,很明显它的意思是只想鼠标移入位置的上一个元素的上一个元素

我把图给大家,怎么样?这是不是更好理解了😄 image.png

总结

感谢大家的观看,如果对您有帮助的话,请在评论区随便说两句吧,这对作者非常重要。

作者并非把文章当作笔记来写,而是当作教学。大家什么都不说,我不知道大家喜欢看什么js?css?react?后面也不知道更新啥了😭。也不知道自己的文章哪里有缺陷需要改正😭

最后也不要忘记点赞收藏加关注哦~😘