一、且看效果
下面是我使用CSS绘制的一个人脸,如果我希望如果用户鼠标从上面进入,表情变成哭丧脸;从下方进入,变成笑脸,该如何实现?
相关代码如下所示:
<div class="face-x">
<div class="face"></div>
</div>
CSS相关代码(默认效果代码,不含hover交互处理):
.face {
width: 200px; height: 200px;
background: #FFD700; /* 经典亮黄色 */
border-radius: 50%;
position: relative;
border: 4px solid #333;
}
/* 使用伪元素绘制眼睛 */
.face::before {
content: '';
position: absolute;
top: 60px; left: 55px;
width: 20px; height: 20px;
background: #333;
border-radius: 50%;
/* 用阴影复制出另一只眼,省代码 */
box-shadow: 70px 0 #333;
}
/* 使用伪元素绘制嘴巴 */
.face::after {
content: '';
position: absolute;
top: 100px;
left: 60px;
width: 80px;
height: 20px;
border-bottom: 8px solid #333;
}
大家不妨自己思考下,有没有什么思路。
二、实现代码与原理
就像变魔术一样,在揭开谜底之前总觉得高深莫测,实际上也就那么回事。
我们直接看最关键的实现代码:
/* 不同方向hover,显示不同表情 */
.face-x {
width: fit-content;
position: relative;
border-radius: 50%;
}
.face-x::after {
content: '';
position: absolute;
inset: 0;
bottom: 50%;
/* background: #0008; */
}
.face-x:has(.face:hover) {
&::after {
display: none;
}
.face::after {
border-radius: 0 0 50% 50%;
}
}
.face-x:hover:not(:has(.face:hover)) {
&::after {
bottom: 0;
}
.face::after {
top: 120px;
border-radius: 0 0 50% 50%;
scale: 1 -1;
}
}
原理很简单:
创建一个50%高度的覆盖层覆盖在.face元素上,如果用户的鼠标进入后首先触碰的事这个覆盖层,就会匹配.face-x:hover:not(:has(.face:hover)),如果是从另外一个方向进入,由于没有覆盖层阻挡,就会匹配.face-x:has(.face:hover)。
如果匹配了前者,那么迅速将覆盖层的尺寸覆盖整个容器元素;如果匹配了后者,迅速隐藏覆盖层。
这样,两种匹配状态就不会冲突。
就是这么简单!

三、又是学到了的一天
我发现,这年头,大家学习前端技术的热情越来越低了,不仅是行业中,公司内也是如此。
以前内部小测,少说十几人参与,多的时候几十人,现在么,就那固定的四五个人。
包括社区里面,也明显感觉到没那么活跃了。
时代变了。
不过我还是相信,自身的实力才是在风雨中屹立不倒的根本,所以,我还是会继续学习的。
以不变应万变,不忘初心。

本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:https://www.zhangxinxu.com/wordpress/?p=12118
(本篇完)