2

I have three divs, of which the first needs to have a set background color on page load (this is to show that this is the default choice and preselected)

I want that when the user clicks the 2nd or 3rd div that

  1. the 1st div's background color is removed / white
  2. the clicked div has the background color (grey)

Should the user click on the 1st div again, it should behave like the 2nd or 3rd div and take the background color.

I have the following code per below, but I can't remove the background color of the 1st div when any other div is clicked.

Could anyone help me please?

JSFiddle: https://jsfiddle.net/AlphaX/1zp8yehu/1/

.one {background-color: grey;}

[tabindex]:focus { background-color: grey;}
<div class="parent" tabindex="0">


<div class="one" tabindex="1">
one
</div>

<div class="two" tabindex="2">
two
</div>

<div class="three" tabindex="3">
three
</div>

</div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
AlphaX
  • 615
  • 1
  • 11
  • 25
  • Does this answer your question? [Is there a "previous sibling" selector?](https://stackoverflow.com/questions/1817792/is-there-a-previous-sibling-selector) – disinfor Feb 08 '21 at 22:23
  • No, because I tried the solutions there already before posting and it's not applicable to my case of changing elements on click. – AlphaX Feb 08 '21 at 22:34

3 Answers3

2

:focus-within can help you here:

.active {
  background-color: grey;
}

.parent:focus-within * { /* rest all background when one element is focused */
  background: none;
}

.parent [tabindex]:focus { /* set the background of only the focused one */
  background-color: grey;
}
<div class="parent" tabindex="0">


  <div class="one active" tabindex="1">
    one
  </div>

  <div class="two" tabindex="2">
    two
  </div>

  <div class="three" tabindex="3">
    three
  </div>

</div>

A more tricky code if you want to have all of them transparent when clicking outside:

.active {
  position:relative;
  z-index:0;
}
.active::before {
  content:"";
  position:absolute;
  z-index:-1;
  top:0;
  left:0;
  right:0;
  bottom:0;
  background: grey;
  animation:h 0.1s forwards paused;
}

.parent:focus-within *::before {
  animation-play-state:running;
}

.parent [tabindex]:focus { 
  background-color: grey;
}

@keyframes h {
  1%,100% {
    background:transparent;
  }
}
<div class="parent" tabindex="0">


  <div class="one active" tabindex="1">
    one
  </div>

  <div class="two" tabindex="2">
    two
  </div>

  <div class="three" tabindex="3">
    three
  </div>

</div>

And to keep the last clicked element colored

.parent [tabindex] {
  transition:999s;
  background: rgba(255,255,255,0);
}
.parent:focus-within [tabindex] {
  transition:0s;
  background: rgba(255,255,254,0); /* a little different coloration to make sure we trigger the transition */
}
.parent [tabindex]:focus,
.parent [tabindex].active:focus{ 
  background-color: rgb(128,128,128);
  transition:0s;
}

.parent .active{ 
  background-color: rgb(128,128,127); /* a little different coloration to make sure we trigger the transition */
}
<div class="parent" tabindex="0">


  <div class="one active" tabindex="1">
    one
  </div>

  <div class="two" tabindex="2">
    two
  </div>

  <div class="three" tabindex="3">
    three
  </div>

</div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • Hi Temani! Good to see you again! I was expecting you to show up on my CSS question ;-) Thanks so much! Any chance you could elaborate on how this works? It's exactly what I'm looking for. – AlphaX Feb 08 '21 at 22:13
  • @AlphaX focus-within is a selector that can be applied to a parent and is activated only if there is a child having focus so I reset all the background if it's the case and only the focused one will get it – Temani Afif Feb 08 '21 at 22:16
  • @AlphaX added another idea too – Temani Afif Feb 08 '21 at 22:23
  • Thanks a lot! I'm just seeing that when you click outside the selection (background color) is gone. Is there a way to keep the background color on the last selected div, even if you click outside? – AlphaX Feb 08 '21 at 22:36
  • 1
    Your third code is perfect! I'll try implementing now on my site. You impress me every time, no matter what I think how much I have learned. Thanks a lot! – AlphaX Feb 08 '21 at 22:50
  • @AlphaX I optimized the last code a little – Temani Afif Feb 08 '21 at 22:55
  • that looks much better, thanks a lot! I have one problem left, the last div has a link text and when you click on the link the code doesn't work (div colours don't change). Is it possible to expand the functionality, so it also works when the text link is clicked in the div? – AlphaX Feb 08 '21 at 23:12
  • @AlphaX can you take a look at my answer below? I don't quite get it why you guys play with tabindex and focus when the question is about clicking. – Robo Robok Feb 08 '21 at 23:14
  • @AlphaX but clicking on a link will redirect you to another page, no? – Temani Afif Feb 08 '21 at 23:17
  • No, in my case (woocommerce checkout page) it unfolds a login form just below. If I can contact you directly, I'll send you a link – AlphaX Feb 08 '21 at 23:19
  • @AlphaX you can find my website link in my profile where you can send me a message if you want – Temani Afif Feb 08 '21 at 23:24
1

You can use the trick with invisible inputs:

input[name='_'] {
    display: none;
}

label span {
    display: block;
}

:checked + span {
    background-color: grey;
}
<label>
    <input type="radio" name="_" checked>
    <span>one</span>
</label>
<label>
    <input type="radio" name="_">
    <span>two</span>
</label>
<label>
    <input type="radio" name="_">
    <span>three</span>
</label>

Even though the radio inputs are not visible, their labels can still control them. And the :checked + span selector applies style to an element only if there's a :checked element right before it.

Voilà!

Robo Robok
  • 21,132
  • 17
  • 68
  • 126
-2

.one, .two. .three {background-color: white;}

.one[tabindex]:focus, .two[tabindex]:focus, .three[tabindex]:focus { background-color: grey;}
<div class="parent" tabindex="0">


<div class="one" tabindex="1">
one
</div>

<div class="two" tabindex="2">
two
</div>

<div class="three" tabindex="3">
three
</div>

</div>
MaksimL
  • 314
  • 2
  • 12
  • Thanks @maksiml However, this doesn't have the first div with a set background color on page load, they are all just white. – AlphaX Feb 08 '21 at 22:11