AlphaX
AlphaX

Reputation: 661

Change background color of div on click (CSS only)

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>

Upvotes: 2

Views: 6000

Answers (3)

Temani Afif
Temani Afif

Reputation: 273990

: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>

Upvotes: 2

Robo Robok
Robo Robok

Reputation: 22815

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à!

Upvotes: 1

MaksimL
MaksimL

Reputation: 314

.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>

Upvotes: -2

Related Questions