Home > Net >  Change multiple element's style with css only
Change multiple element's style with css only

Time:11-28

I need to change multiple element's background color in a table, but I am not allowed to use javascript.

At first I've implemented a code to see the result I need, this time using javascript. The code works, but as I said I need to implement something with NO javascript. CSS only.

As you can see, I have a few rows in a table, and once clicked upon cells 1 or 2 the proper row assumes a certain color pattern. Such pattern applies to all rows in my table (there will be 12 rows in the final implementation).

I've found a solution for a single element, which I show in the div element, but it applies to one element only. I can't figure it out how to change all the td's in a row, with the color patter I need.

By the way, in each row there will be 35 cells. It won't be just 5, like in this example.

document.getElementById("td_1_0").addEventListener("click", ()=>{
    document.getElementById("td_1_1").classList.toggle("cRed");
    document.getElementById("td_1_2").classList.toggle("cYellow");
    document.getElementById("td_1_3").classList.toggle("cRed");
    document.getElementById("td_1_4").classList.toggle("cLime");
    document.getElementById("td_1_5").classList.toggle("cLime");
});
document.getElementById("td_2_0").addEventListener("click", ()=>{
    document.getElementById("td_2_1").classList.toggle("cRed");
    document.getElementById("td_2_2").classList.toggle("cYellow");
    document.getElementById("td_2_3").classList.toggle("cRed");
    document.getElementById("td_2_4").classList.toggle("cLime");
    document.getElementById("td_2_5").classList.toggle("cLime");
});
html {
    text-align: center;
}
table {
    width: 100%;
}
td {
    border: 1px black solid;
}
.cRed {
    background-color: red;
}
.cLime {
    background-color: lime;
}
.cYellow {
    background-color: yellow;
}
div {
    background-color: lightgray;
    height: 200px;
}
input:checked   div { background-color: cyan;}
<table>
    <tr>
        <td id="td_1_0">1</td>
        <td id="td_1_1">A</td>
        <td id="td_1_2">B</td>
        <td id="td_1_3">C</td>
        <td id="td_1_4">D</td>
        <td id="td_1_5">E</td>
    </tr>
    <tr>
        <td id="td_2_0">2</td>
        <td id="td_2_1">F</td>
        <td id="td_2_2">G</td>
        <td id="td_2_3">H</td>
        <td id="td_2_4">I</td>
        <td id="td_2_5">J</td>
    </tr>
</table>
    
<label>
    <input type="checkbox" hidden>
    <div>click to change (div)</div>
</label>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

I'm not saying this is a great idea, but it does what you're trying to do, without any javascript. It uses the same checkbox hack as your example div.

  1. Add a checkbox for each row, immediately before the table.
  2. Stick a label for the appropriate checkbox in the corresponding row. (This allows clicking the cell to toggle the checkbox.)
  3. Position the label absolutely so the click area covers the entire cell.
  4. Use a bunch of clunky sibling and nth-child selectors to target the appropriate cells and change their color.

This obviously isn't ideal, but it's workable for a relatively small table if you have no other options.

table {
    width: 100%;
}

td {
    border: 1px black solid;
    position: relative;
}

input[type=checkbox] {
  display: none;
}

label {
  position: absolute;
  inset: 0;
}

#row1:checked ~ table tr:first-child :nth-child(2) {
  background: red;
}

#row1:checked ~ table tr:first-child :nth-child(3) {
  background: yellow;
}

#row1:checked ~ table tr:first-child :nth-child(4) {
  background: red;
}

#row1:checked ~ table tr:first-child :nth-child(5) {
  background: green;
}

#row1:checked ~ table tr:first-child :nth-child(6) {
  background: green;
}


#row2:checked ~ table tr:nth-child(2) :nth-child(2) {
  background: red;
}

#row2:checked ~ table tr:nth-child(2) :nth-child(3) {
  background: yellow;
}

#row2:checked ~ table tr:nth-child(2) :nth-child(4) {
  background: red;
}

#row2:checked ~ table tr:nth-child(2) :nth-child(5) {
  background: green;
}

#row2:checked ~ table tr:nth-child(2) :nth-child(6) {
  background: green;
}
<input type="checkbox" id="row1" />
<input type="checkbox" id="row2" />
<table>
  <tr>
    <td><label for="row1"></label>1</td>
    <td>A</td>
    <td>B</td>
    <td>C</td>
    <td>D</td>
    <td>E</td>
  </tr>
  <tr tabIndex="0">
    <td><label for="row2"></label>2</td>
    <td>F</td>
    <td>G</td>
    <td>H</td>
    <td>I</td>
    <td>J</td>
  </tr>
</table>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

If you can influence table construction at the backend then try something like this:

Show code snippet

html {
  text-align: center;
}

input:checked~.cRed {
  background-color: red;
}

input:checked~.cLime {
  background-color: lime;
}

input:checked~.cYellow {
  background-color: yellow;
}

.table {
  display: table;
  width: 100%;
}

.row {
  display: table-row;
}

.cell {
  display: table-cell;
  border: 1px black solid;
}

.cell:first-child {
  visibility: collapse;
  width: 1%;
}

.cell:not(.clickable) {
  pointer-events: none;
}
<div class="table">
  <label for="1" class="row">
      <input id="1" class="cell" type="checkbox" hidden>
      <div class="cell clickable">1</div>
      <div class="cell cRed">A</div>
      <div class="cell cYellow">B</div>
      <div class="cell cRed">C</div>
      <div class="cell cLime">D</div>
      <div class="cell cLime">E</div>
    </label>
  <label for="2" class="row">
      <input id="2" class="cell" type="checkbox" hidden>
      <div class="cell clickable">2</div>
      <div class="cell cRed">A</div>
      <div class="cell cYellow">B</div>
      <div class="cell cRed">C</div>
      <div class="cell cLime">D</div>
      <div class="cell cLime">E</div>
    </label>
</div>
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
Whatever solution you'll get you'll have to set at least color classes on each table cell. This way if backend decides to change colors then it'll happen automatically.

But if you want to set the pattern at CSS side then you can use input:checked~:nth-child(3 ... 36) instead of using input:checked~.cRed. This way it'll repeat for all 12 rows automatically:

Show code snippet

html {
  text-align: center;
}

input:checked~:nth-child(3),
input:checked~:nth-child(5) {
  background-color: red;
}

input:checked~:nth-child(6),
input:checked~:nth-child(7) {
  background-color: lime;
}

input:checked~:nth-child(4) {
  background-color: yellow;
}

.table {
  display: table;
  width: 100%;
}

.row {
  display: table-row;
}

.cell {
  display: table-cell;
  border: 1px black solid;
}

.cell:first-child {
  visibility: collapse;
  width: 1%;
}

.cell:not(.clickable) {
  pointer-events: none;
}
<div class="table">
  <label for="1" class="row">
      <input id="1" class="cell" type="checkbox" hidden>
      <div class="cell clickable">1</div>
      <div class="cell">A</div>
      <div class="cell">B</div>
      <div class="cell">C</div>
      <div class="cell">D</div>
      <div class="cell">E</div>
    </label>
  <label for="2" class="row">
      <input id="2" class="cell" type="checkbox" hidden>
      <div class="cell clickable">2</div>
      <div class="cell">A</div>
      <div class="cell">B</div>
      <div class="cell">C</div>
      <div class="cell">D</div>
      <div class="cell">E</div>
    </label>
</div>
<iframe name="sif4" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>


Other way is using anchor tags: https://stackoverflow.com/a/42269449/15273968
It's a same approach as using siblings selector. But you'll have to create 2 anchor tags for each of 12 rows.


Edit: You can achieve CSS only scroll beneath:

Show code snippet

<!DOCTYPE html>
<html>

<head>
  <style>
    html {
      text-align: center;
    }
    
    input:checked~:nth-child(3),
    input:checked~:nth-child(5) {
      background-color: red;
    }
    
    input:checked~:nth-child(6),
    input:checked~:nth-child(7) {
      background-color: lime;
    }
    
    input:checked~:nth-child(4) {
      background-color: yellow;
    }
    
    .table {
      display: table;
      width: 700px;
    }
    
    .row {
      display: table-row;
    }
    
    .cell {
      display: table-cell;
      left: 0;
      border: 1px black solid;
    }
    
    .cell:not(.clickable) {
      pointer-events: none;
      z-index: -100;
    }
    
    .cell:first-child {
      display: none;
    }
    
    .clickable {
      background-color: white;
      position: sticky;
      left: 0;
      width: 2rem;
      z-index: 100;
      background-color: wheat;
    }
    
    .container {
      height: 100px;
      width: 400px;
      overflow-x: scroll;
      border: 1px solid green;
    }
  </style>
</head>

<body>
  <div class=container>
    <div class="table">
      <label for="1" class="row">
        <input id="1" class="cell" type="checkbox" hidden>
        <div class="cell clickable">1</div>
        <div class="cell">A</div>
        <div class="cell">B</div>
        <div class="cell">C</div>
        <div class="cell">D</div>
        <div class="cell">E</div>
      </label>
      <label for="2" class="row">
        <input id="2" class="cell" type="checkbox" hidden>
        <div class="cell clickable">2</div>
        <div class="cell">A</div>
        <div class="cell">B</div>
        <div class="cell">C</div>
        <div class="cell">D</div>
        <div class="cell">E</div>
      </label>
    </div>
  </div>
</body>

</html>
<iframe name="sif5" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related