CSS catch siblings before element?

Asked

Viewed 190 times

5

Well basically, I have the following structure, where when the hover is activated in an element, the brothers on the right must receive an exclusive style, while those on the left must receive another style. Currently I have the same code working well in JS to stylize the brothers to the left of the element in hover however, I feel uncomfortable not being able to do everything only with CSS, so the question, it is possible to select all siblings before the selected one using CSS?

.main{
  width: 100%;
  height:50px;
}
.child{
  width:50px;
  height:50px;
  
  background-color:#F00;
  display: inline-block;
  margin-right: 5px;
}

.child:hover{
  background-color: #0F0;
}
/*define cor para todos os siblings depois deste*/
.child:hover ~ .child{
  background-color: #00F;
}
<div class="main">
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
</div>

3 answers

7


CSS does not have a selector that solves precedence, but in your case a "double Hover" can solve it (works on IE11, including):

.main{
  width: 100%;
  height:50px;
}

.child{
  width:50px;
  height:50px;
  
  background-color:#F00;
  display: inline-block;
  margin-right: 5px;
}

.main:hover .child{         /* o hover no main aciona a mudança no resto */
  background-color: #FF0;
}

.main:hover .child:hover,
.child:hover{
  background-color: #0F0;
}

.child:hover ~ .child{
  background-color: #00F;
}

 
<div class="main">
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
</div>

  • It is possible to activate a different color if the Hover is in the last element?

  • can use :last-Child, or even for an additional class in it. has several ways, which the best, depends on the project.

  • There are several posts about CSS on the site that may be interesting, see some: https://answall.com/questions/9183/70 https://answall.com/a/148591/70

5

I have a solution that may serve. But there are some things, the container have to be exactly the size of the kids to be cool. You have to put a Hover on the father followed by a rule :hover:not() in children.

See that now on :hover in the children they are divided into three parts, a color before the Hover, a color in the element hovado and another color in the elements irmaos.

    .main{
      width: 250px;
      background-color:silver;
      display: flex;
    }
    .main:hover > .child:not(:hover) {
      background-color:#ff0;
    }
    .child{
      width:50px;
      height:50px;
      background-color:#f00;
      border: 1px solid black;

    }
    .child:hover{
      background-color: #0F0;
    }
    /*define cor para todos os siblings depois deste*/
    .child:hover ~ .child{
      background-color: #00F !important;
    }
    <div class="main">
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
      <div class="child"></div>
    </div>

4

To reply by @Bacco is great, however where there are spacing if you accidentally hover :hover the parent element will be applied:

hover do elemento pai

Note how it turned yellow in the case of the example does not cause problems, but if you happen to need some more complex effect in the hover, this can lead to unexpected effects.

To improve recommend using pointer-events: none and pointer-events: auto in the child elements, example:

.main{
  width: 100%;
  height:50px;
  pointer-events: none;
}

.child{
  width:50px;
  height:50px;
  pointer-events: auto;
  
  background-color:#F00;
  display: inline-block;
  margin-right: 5px;
}

.main:hover .child{ /* o hover no main aciona a mudança no resto */
  background-color: #FF0;
}

.main:hover .child:hover,
.child:hover{
  background-color: #0F0;
}

.child:hover ~ .child{
  background-color: #00F;
}
<div class="main">
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
  <div class="child"></div>
</div>

Upshot:

resultado com pointer-events

Just to highlight, pointer-events only works on Internet Explorer 11 and more modern browsers, fortunately works on since very old versions of popular browsers:

  • Opera 9.5 (released 2008) - ps: no kennel mention that it is since Opera 9, but I am almost certain that this was only supported in 9.5, so if you have mistaken me I will review this part of the answer
  • Safari 4 (released in 2008)
  • Firefox 1.5 (released in 2005)

Only Internet Explorer was a bit time consuming to implement this, version 11 with support to pointer-events browser was only released in 2013.


Alternatives

A form suggested by @costamilam, reverse the order of the elements, this is possible with float:right and with display:flex + flex-direction:row-reverse.

Using float: right

.main {
  height:50px;
}

.child1,
.child2 {
  width:50px;
  height:50px;
  background-color:#F00;
  float: right;
  margin-right: 5px;
}

.child1:hover,
.child2:hover {
  background-color: #fc0;
}

.child1:hover ~ .child1,
.child2:hover + .child2 {
  background-color: #00F;
}
<h2>Todos elementos a esquerda</h2>

<div class="main">
  <div class="child1"></div>
  <div class="child1"></div>
  <div class="child1"></div>
  <div class="child1"></div>
  <div class="child1"></div>
</div>


<h2>Apenas um elemento a esquerda</h2>

<div class="main">
  <div class="child2"></div>
  <div class="child2"></div>
  <div class="child2"></div>
  <div class="child2"></div>
  <div class="child2"></div>
</div>

Using flex-direction:row-reverse

.main {
  gap: 10px;
  width: 100%;
  height:50px;
  display: flex;
  flex-direction: row-reverse;
}

.child1,
.child2 {
  width:50px;
  height:50px;      
  background-color:#F00;

  flex:1 1 auto;
}

.child1:hover,
.child2:hover {
  background-color: #fc0;
}

.child1:hover ~ .child1,
.child2:hover + .child2 {
  background-color: #00F;
}
<h2>Todos elementos a esquerda</h2>

<div class="main">
  <div class="child1"></div>
  <div class="child1"></div>
  <div class="child1"></div>
  <div class="child1"></div>
  <div class="child1"></div>
</div>

<h2>Apenas um elemento a esquerda</h2>

<div class="main">
  <div class="child2"></div>
  <div class="child2"></div>
  <div class="child2"></div>
  <div class="child2"></div>
  <div class="child2"></div>
</div>

Browser other questions tagged

You are not signed in. Login or sign up in order to post.