仅使用 css 更改多个元素的样式

Posted

技术标签:

【中文标题】仅使用 css 更改多个元素的样式【英文标题】:Change multiple element's style with css only 【发布时间】:2022-01-04 23:59:15 【问题描述】:

我需要更改表格中多个元素的背景颜色,但我不能使用 javascript

起初我已经实现了一个代码来查看我需要的结果,这次使用的是 javascript。 代码有效,但正如我所说,我需要用没有 javascript 来实现一些东西。仅限 CSS。

如您所见,我在表格中有几行,一旦单击单元格 1 或 2,正确的行就会采用某种颜色模式。这种模式适用于我表中的所有行(最终实现将有 12 行)。

我找到了针对单个元素的解决方案,我在 div 元素中显示了该解决方案,但它仅适用于一个元素。我不知道如何使用我需要的颜色模式连续更改所有 td。

顺便说一句,每行将有 35 个单元格。不会像本例那样只有 5 个。

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>

【问题讨论】:

【参考方案1】:

我并不是说这是一个好主意,但它可以完成您想要做的事情,而无需任何 javascript。它使用与您的示例 div 相同的复选框 hack。

    在表格之前为每一行添加一个复选框。 在相应行中为相应的复选框添加标签。 (这允许单击单元格来切换复选框。) 绝对定位标签,使点击区域覆盖整个单元格。 使用一堆笨重的兄弟和第 n 个子选择器来定位适当的单元格并更改它们的颜色。

这显然不理想,但如果您没有其他选择,它对于相对较小的桌子是可行的。

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>

【讨论】:

我忘了提到我以编程方式完成了所有这些事件监听器,即在“for循环”中。正如我所说,将有 12 行,每行有 35 个单元格。使用循环设置 420 个事件侦听器 (12 x 35) 不是问题,但是使用您给我的这个解决方案逐个单元地进行操作将是一个不同的故事......我想它会完成这项工作,但是我希望有一个更简单的解决方案,因为所有行的模式都是相同的。 您可以通过默认为单元格着色来减少所需的 css 数量,然后使用更通用的选择器将未选中的行 td​​ 设置为白色背景,但它仍然有点难看。 我会坚持这个解决方案。默认情况下,我将所有单元格设置为彩色,现在当我单击“控制单元格”时,整行变为白色(或浅灰色,它是备用的)。这解决了我的问题,但最好不要在开始时将它们全部着色......但没关系。有用。让整行都可点击会很困难吗?...因为该操作是通过单击 LABEL 标记发生的,这只是第一个 TD。可能是所有细胞的标签?...还是更好的解决方案?...非常感谢! 如果您将position: relative 从 td 移动到 tr,标签将跨越整行,使整个内容可点击。 实际上我没有使用那条线。整个事情是一个日历(每月有 35 个单元格),所以左边的单元格是月份的名称。这是一个固定单元格,因此日历向左滚动,月份名称始终可见。【参考方案2】:

如果您可以影响后端的表格构造,请尝试以下操作:

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>
无论你得到什么解决方案,你都必须至少在每个表格单元格上设置颜色类。这样,如果后端决定改变颜色,它就会自动发生。 但是如果你想在 CSS 端设置模式,那么你可以使用input:checked~:nth-child(3 ... 36) 而不是使用input:checked~.cRed。这样它会自动重复所有 12 行:

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>

其他方式是使用锚标签:https://***.com/a/42269449/15273968 这与使用兄弟选择器的方法相同。但是您必须为 12 行中的每一行创建 2 个锚标记。


编辑:可以实现CSS只在下方滚动:

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

【讨论】:

是的?...我的意思是,我几乎要说“是的!!!”,因为它真的达到了我想要的,从美学上讲。我唯一关心的是表格结构......到目前为止(使用我的javascript解决方案)我有一个固定左侧单元格的表格(可点击的单元格,控制单元格),所以表格向左滚动,下面的单元格消失了控制单元(因为在手机中我不能一次显示 35 个单元,所以我需要让它滚动,但保持控制单元固定)。当然这是css,但是不知道如果我把表格结构从table标签改成div会不会有什么问题。 使用display: table-cell;,div 的行为应该与普通表格单元格完全一样。我认为应该没有问题。您必须从 JS 中删除 tablerowtd 此类特定标签查询。 你可以在没有javascript的情况下实现css只在下面滚动。除非您正在做更复杂的事情,否则您可以尝试答案中的新解决方案。 是的,滚动部分都是css。但我仍在努力使其与这种新方法(div 而不是 table)一起工作。我的原始表格设置了 min-height: 40px 的 tds,但它不适用于 div(它们都是 20px,不知道为什么......)。我在标签标签下放置了一个外部 div,并尝试了“.cell:nth-child(2) position: fixed; left: 0;”,但此时只有可点击的 div 假定为 min-height:40px ,而所有其他的都保持 20 像素。 您需要在 div 的子元素上设置 min-height。 &lt;div class="cell"&gt;&lt;div style="min-height: 40px;"&gt;A&lt;/div&gt;&lt;/div&gt;

以上是关于仅使用 css 更改多个元素的样式的主要内容,如果未能解决你的问题,请参考以下文章

仅更改某些 li 元素的列表样式[关闭]

仅使用 css 更改另一个 div 的样式

CSS样式如何修改

CSS - wordpress 如何更改下拉元素的字体样式

使用 CSS 更改兄弟悬停时的元素样式

js如何给目标元素的兄弟元素更改样式