Reputation: 695
I am struggling to find the CSS that does 2 things, change the colour of all child elements, and do it as a transition. I've created a simple test case of the following JSFiddle:
<div class="parent">Level 1
<div>Level 2
<div class="child">Level 3 (!important means this should become red on hover)
</div>
</div>
</div>
I am trying to come up with the CSS to transition the text to a different colour. Here's the skeleton of what I'm working with:
.parent {
transition: all 2s ease-out;
}
.parent:hover {
color: red !important;
}
.child {
color: blue;
}
I want to specify a rule at the parent level that will cause all children to change colour. I know using !important
is discouraged, but this seems like a valid case for using it, as this rule is flagging the section as 'in error' and should override other rules.
Here is what I've done to make it work, but it requires that I have rules for all child elements that set the colour. Which is fine in this simple example, but in the real system poses a problem because we may not know all the rules that change the colour.
div {
font-size: 3rem;
text-indent: 1rem;
}
.child {
color: blue;
}
.parent,
.parent .child {
transition: all 3s;
}
.parent:hover,
.parent:hover .child {
color: red !important;
}
<div class="parent">
Level 1
<div>
Level 2
<div class="child">
Level 3 (!important means this should become red on hover)
</div>
</div>
</div>
Is it possible to transition all the children to a new colour without knowing all classes that must be specified? I tried using a .parent *
selector, but each level of nesting increases the transition period as in this fiddle
Update
I have a better understanding of what's going on. @Hunter resolved the unnecessary !important
rule. So, the real issue is that the transition-duration property seems to be additive for children, see how slow it takes to remove the red colour when no longer hovering over the text, ideally the colour of each nested element should transition at the same time.
div {
padding-left: 1rem;
}
.a-child { color: blue; }
.parent * {
transition: color 2s;
}
.parent:hover * {
color: red;
}
<div class="parent">
<div>
Level 1
<div>
Level 2
<div>
Level 3
<div>
Level 4
<div class="a-child">
Level 5
</div>
</div>
</div>
</div>
</div>
</div>
Upvotes: 5
Views: 2497
Reputation: 1185
The universal selector's performance has improved significantly, but it is still of a concern, albeit a minor one. I'd suggest that you use .parent div
, if all children are <div>
s.
CSS:
div {
font-size: 3rem;
text-indent: 1rem;
}
.child {
color: blue;
}
.parent,
.parent div {
transition: all 3s;
}
.parent:hover,
.parent:hover div {
color: red;
}
HTML:
<div class="parent">
Level 1
<div>
Level 2
<div class="child">
Level 3 (!important means this should become red on hover)
</div>
</div>
</div>
Here's a JSFiddle.
edit
To avoid recursive transation delays just set color
of black children explicitly, like the blue .a-child
:
div {
padding-left: 1rem;
}
.parent * {
color: black; /* explicitly set color of children */
transition: color 2s;
}
.a-child { color: blue; }
.parent:hover * {
color: red;
}
<div class="parent">
<div>
Level 1
<div>
Level 2
<div>
Level 3
<div>
Level 4
<div class="a-child">
Level 5
</div>
</div>
</div>
</div>
</div>
</div>
The reason for recursive delay, is that color
property of the parent is set to red until the transition
is completed then, and only then, color
value returns to default (inherited from <body>
i.e. black).
The color
property of second-level <div>
is not explicitly set, thus it inherits the value from its parent; that's why it remains red until the transition
of its parent is completed to inherit the black color, and start transitioning to black, this happens recursively creating the delay effect.
That's why the blue <div>
starts transitioning instantly to blue when the mouse hovers off; because it has its color
property explicitly set to blue
.
Upvotes: 7
Reputation: 6894
By using the *
selector and by placing your .parent
text in a separate div, you can select every child to the parent and apply the transition as well as the color change.
Placing the .parent
content in a separate div fixes the delay on the out transition.
CSS
.parent * {
transition: all 2s ease-out;
}
.parent:hover * {
color: red;
}
HTML
<div class="parent">
<div>Level 1</div> <!-- <-- Place in div -->
<div>
...
By using this, there is also no need for !important
.
div {
font-size: 3rem;
text-indent: 1rem;
}
.child {
color: blue;
}
.parent * {
transition: all 2s ease-out;
}
.parent:hover * {
color: red;
}
<div class="parent">
<div>Level 1</div>
<div>
Level 2
<div class="child">
Level 3
</div>
</div>
</div>
Upvotes: 2