In my original code, both squares pulsate when hovering anywhere on the SVG canvas. But I need them to pulsate only when hovering over the smallest square. I suspect that :has()
could solve this but can't figure out how to implement it. Perhaps it can be solved without :has()
?
My original code:
.wrapper:hover .rect_small {
animation: pulsate 2s ease forwards;
transform-origin: center;
}
.wrapper:hover .rect_large {
animation: pulsate 2s ease forwards 1s;
transform-origin: center;
}
@keyframes pulsate {
0% {
fill: black;
transform: scale(1);
}
5% {
fill: red;
transform: scale(1.5);
}
100% {
fill: black;
transform: scale(1);
}
}
.g_large {
animation: rotate_large 5s linear infinite;
transform-origin: center;
}
@keyframes rotate_large {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.g_small {
animation: rotate_small 5s linear infinite;
transform-origin: center;
}
@keyframes rotate_small {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(720deg);
}
}
<svg width="200" height="200" viewBox="0 0 200 200" fill="none">
<g class="wrapper">
<rect width="200" height="200" fill="black"/>
<g class="g_large"><rect class="rect_large" x="50" y="50" width="100" height="100" fill="black" stroke="white" stroke-width="2"/></g>
<g class="g_small"><rect class="rect_small" x="75" y="75" width="50" height="50" fill="black" stroke="white" stroke-width="2"/></g>
</g>
</svg>
My code with implementation of :has()
as a potential solution but to no avail. When hovering over the smallest square, only the smallest square pulsates. The large square doesn't even with the :has()
selector:
.rect_small:hover {
animation: pulsate 2s ease forwards;
transform-origin: center;
}
.rect_large:has(.rect_small:hover) {
animation: pulsate 2s ease forwards 1s;
transform-origin: center;
}
@keyframes pulsate {
0% {
fill: black;
transform: scale(1);
}
5% {
fill: red;
transform: scale(1.5);
}
100% {
fill: black;
transform: scale(1);
}
}
.g_large {
animation: rotate_large 5s linear infinite;
transform-origin: center;
}
@keyframes rotate_large {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.g_small {
animation: rotate_small 5s linear infinite;
transform-origin: center;
}
@keyframes rotate_small {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(720deg);
}
}
<svg width="200" height="200" viewBox="0 0 200 200" fill="none">
<g class="wrapper">
<rect width="200" height="200" fill="black"/>
<g class="g_large"><rect class="rect_large" x="50" y="50" width="100" height="100" fill="black" stroke="white" stroke-width="2"/></g>
<g class="g_small"><rect class="rect_small" x="75" y="75" width="50" height="50" fill="black" stroke="white" stroke-width="2"/></g>
</g>
</svg>
The .rect_large
is a sibling and not a parent of .rect_small
. You can check with :has
on the .wrapper
the .rect_small
was hovered. and then animate the large one:
.rect_small:hover {
animation: pulsate 2s ease forwards;
transform-origin: center;
}
.wrapper:has(.rect_small:hover) .rect_large {
animation: pulsate 2s ease forwards 1s;
transform-origin: center;
}
@keyframes pulsate {
0% {
fill: black;
transform: scale(1);
}
5% {
fill: red;
transform: scale(1.5);
}
100% {
fill: black;
transform: scale(1);
}
}
.g_large {
animation: rotate_large 5s linear infinite;
transform-origin: center;
}
@keyframes rotate_large {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
.g_small {
animation: rotate_small 5s linear infinite;
transform-origin: center;
}
@keyframes rotate_small {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(720deg);
}
}
<svg width="200" height="200" viewBox="0 0 200 200" fill="none">
<g class="wrapper">
<rect width="200" height="200" fill="black"/>
<g class="g_large"><rect class="rect_large" x="50" y="50" width="100" height="100" fill="black" stroke="white" stroke-width="2"/></g>
<g class="g_small"><rect class="rect_small" x="75" y="75" width="50" height="50" fill="black" stroke="white" stroke-width="2"/></g>
</g>
</svg>