fpiskur fpiskur - 3 months ago 14
CSS Question

CSS transitions - I need an explanation

I was trying to move some elements around with transition in CSS. I made it work fine by adding a separate selector for each element I want to transition, but it doesn't work when I use one selector for all (they end up in the same place anyway). Can someone please explain why it doesn't work like this?



body {
text-align: center;
}

.block {
position: relative;
display: inline-block;
}

.part1 {
font-family: Arial;
font-size: 50px;
font-weight: bold;
opacity: 0.2;
position: relative;
z-index: 1;
}

.part {
font-family: Arial;
font-size: 50px;
font-weight: bold;
opacity: 0.2;
position: absolute;
transition: top 2s ease-in, left 2s ease-in, right 2s ease-in;
}

.block .part:nth-child(2) {
top: 100px;
left: 100px;
}

.block .part:nth-child(3) {
top: 0;
left: 200px;
}

.block .part:nth-child(4) {
top: 0;
right: 200px;
}

.block .part:last-child {
top: 100px;
right: 100px;
}

.block .part1:hover ~ .part {
top: 0;
left: 0;
right: 0;
}

<span class="block">
<span class="part1">O</span>
<span class="part">O</span>
<span class="part">O</span>
<span class="part">O</span>
<span class="part">O</span>
</span>





As you can see, the left property doesn't transition for the fourth and fifth element.

Here's the working snippet:



body {
text-align: center;
}

.block {
position: relative;
display: inline-block;
}

.part1 {
font-family: Arial;
font-size: 50px;
font-weight: bold;
opacity: 0.2;
position: relative;
z-index: 1;
}

.part {
font-family: Arial;
font-size: 50px;
font-weight: bold;
opacity: 0.2;
position: absolute;
transition: top 2s ease-in, left 2s ease-in, right 2s ease-in;
}

.block .part:nth-child(2) {
top: 100px;
left: 100px;
}

.block .part:nth-child(3) {
top: 0;
left: 200px;
}

.block .part:nth-child(4) {
top: 0;
right: 200px;
}

.block .part:last-child {
top: 100px;
right: 100px;
}

.block .part1:hover ~ .part:nth-child(2) {
top: 0;
left: 0;
}

.block .part1:hover ~ .part:nth-child(3) {
left: 0;
}

.block .part1:hover ~ .part:nth-child(4) {
right: 0;
}

.block .part1:hover ~ .part:last-child {
top: 0;
right: 0;
}

<span class="block">
<span class="part1">O</span>
<span class="part">O</span>
<span class="part">O</span>
<span class="part">O</span>
<span class="part">O</span>
</span>





Why does this happen? I couldn't find the answer in documentation.

Answer

Your problem is because when you share the same :hover rule, you're setting left: 0 on your fourth and fifth elements, so they're going to get positionated accordingly to their parent which is relative (.block) then there's no room for them to animate as you desire. When you use a separate selector, left remains at it's default value of auto so then right correctly animates on these two elements.

If you do not specify left or right their default value is auto, not 0. Check MDN docs.

Comments