是否可以通过仅单击一个标签来触发两个更改?

时间:2018-07-23 17:48:38

标签: html css html5 css3 css-selectors

我一直在使用HTML和CSS来创建简单的两人游戏,而无需使用任何JavaScript。我使用标签,单选按钮和复选框来创建不同的状态并模仿一些逻辑,以便使该部分在板上移动。

它的工作原理“很好”,尽管可用性不是很好。例如,单击骰子后,磁贴移动,并且我显示一个按钮以切换到下一个玩家(再次使用标签和复选框控制)...这不是很好,如果改变玩家,效果会更好“自动。”

问题在于<label>只能针对一个元素,而且我不知道如何仅需单击一下即可触发两个“动作”(或副作用)。

下面的代码是一个mcve,它可以更好地形象地显示问题:有两个玩家(按回合指定),一个带有三个磁贴的板(由6个单选按钮表示:每个玩家和一个磁贴一个)和两个按钮来改变玩家的转弯(只有一个可见)。如果您单击转弯更改按钮,则转弯将转到下一个玩家。 (可以找到更复杂的示例here

问题是用户被迫按下按钮以更改转弯,否则同一位玩家将始终处于活动状态。有没有一种方法可以使单击标签时不仅激活磁贴,而且改变匝数?还是在没有它的情况下,有其他方法可以实现这一目标? (不使用JS)

#p1:checked ~ [for=p1],
#p1:checked ~ [for^=tile-p2],
#p1:checked ~ [name^=tile-p2],
#p2:checked ~ [for=p2],
#p2:checked ~ [for^=tile-p1],
#p2:checked ~ [name^=tile-p1]
{ 
  display: none; 
}

/* more rules to hide/show more elements */
<h1>Players:</h1>
<input type="radio" id="p1" name="player" checked /> P1
<input type="radio" id="p2" name="player" /> P2

<h1>Board: </h1>
Player 1:
<input type="radio" id="tile-p1-1" name="tile-p1" checked />
<label for="tile-p1-1">P1 to 1</label>
<input type="radio" id="tile-p1-2" name="tile-p1" />
<label for="tile-p1-2">P1 to 2</label>
<input type="radio" id="tile-p1-3" name="tile-p1" />
<label for="tile-p1-3">P1 to 3</label>
<br/>
Player 2:
<input type="radio" id="tile-p2-1" name="tile-p2" checked />
<label for="tile-p2-1">P2 to 1</label>
<input type="radio" id="tile-p2-2" name="tile-p2" />
<label for="tile-p2-2">P2 to 2</label>
<input type="radio" id="tile-p2-3" name="tile-p2" />
<label for="tile-p2-3">P2 to 3</label>

<h1>Change of turn:</h1>
<label for="p2">Change to Player 2</label>
<label for="p1">Change to Player 1</label>

是否可以通过仅单击一个<label><a>来触发两个“状态更改”?


有人尝试解决这个问题:

我尝试将<a>放在<label>内以触发两个可读的更改::target:checked(通过:target,我可以控制玩家的回合,并通过:checked将其定位为棋子位置)。它似乎是有效的HTML(至少根据W3C验证器而言),但是it doesn't really work。例如,在下一个代码段中,单击第一个链接将突出显示文本,单击第二个链接将标记该框,并且(我希望)单击第三个链接将同时执行这两项操作……但不能:

#test:target {
  color: red;
}

#cb:checked

a, label {
  display: block;
  text-decoration: underline;
  color: blue;
}
<input type="checkbox" id="cb" />
<div id="test">TEST</div>

<a href="#test">Highlight test</a>
<label for="cb">Check the box</label>
<label for="cb">
  <a href="#test">Highlight test AND check the box</a>
</label>

我还尝试使用不同的伪类::checked:invalid。它对复选框并没有多大作用,因为它们都可以同时应用,并且根据我的测试,required不适用于单个收音机(但是我可能做错了事):

div {
  color: purple;
}

#radio1:checked ~ div {
  color: blue;
}

#radio2:checked ~ div {
  color: fuchsia;
}

#radio1:invalid ~ div {
  color: red;
}

#radio1:invalid + #radio2:checked ~ div {
  color: green;
}
<input type="radio" name="radio1" id="radio1" required />
<input type="radio" name="radio1" id="radio2" />

<div>Text to be green if radio2 is checked</div>

6 个答案:

答案 0 :(得分:9)

一个想法是考虑标签上的:focus状态,这将允许您触发两个更改。唯一的缺点是:focus状态仅在mousedown上启用,而在mouseup上禁用。

这是一个例子

label:focus + #test {
 color: red;
}

label {
  display: block;
  text-decoration: underline;
  color: blue;
}
<input type="checkbox" id="cb" >

<label for="cb"  tabindex=-1>Check the box and highlight the text</label>
<div id="test">TEST</div>

更新

使用上述逻辑并考虑骰子游戏的初始代码是使用动画的想法。技巧是创建具有2个状态的暂停动画,然后在:focus上运行动画以在状态之间进行切换。

当然,这并不是100%准确的,因为这取决于点击的速度,但是可以考虑以下方法:

.container {
  position: relative;
}

label {
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  width: 50px;
  height: 50px;
  line-height: 50px;
  background: #eeeeee;
  text-align: center;
  animation: changeOrder 0.6s infinite;
}

@keyframes changeOrder {
  from { z-index: 6;}
   to { z-index: 1; }
}
label:nth-of-type(1) { animation-delay: 0s; }
label:nth-of-type(2) { animation-delay: -0.1s; }
label:nth-of-type(3) { animation-delay: -0.2s; }
label:nth-of-type(4) { animation-delay: -0.3s; }
label:nth-of-type(5) { animation-delay: -0.4s; }
label:nth-of-type(6) { animation-delay: -0.5s; }


label:active {
  /*Mandatory to break the stacking context and allow 
       the pseudo element to be above everything*/
  position: static;
  /*For illustration*/
  margin-left: 50px;
  background: red;
}

label:active::before {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  bottom: 0;
  z-index: 10;
}
.player {
  display:inline-block;
  margin-top:80px;
}

.player:before {
 content:"Player One";
 animation: player .3s infinite step-end;
 animation-play-state: paused;
}

label:focus ~ .player:before{
 animation-play-state: running;
}

@keyframes player {
  0% {
     content:"Player One";
  }
  50% {
     content:"Player Two";
  }

}
<input type="radio" name="cb" id="cb1" value="1">
<input type="radio" name="cb" id="cb2" value="2">
<input type="radio" name="cb" id="cb3" value="3">
<input type="radio" name="cb" id="cb4" value="4">
<input type="radio" name="cb" id="cb5" value="5">
<input type="radio" name="cb" id="cb6" value="6">
<div class="container">
  <label for="cb1" tabindex="-1">1</label>
  <label for="cb2" tabindex="-1">2</label>
  <label for="cb3" tabindex="-1">3</label>
  <label for="cb4" tabindex="-1">4</label>
  <label for="cb5" tabindex="-1">5</label>
  <label for="cb6" tabindex="-1">6</label>
  <span class="player" ></span>
</div>

如果您想要一个静态的永久效果,这很简单,因为您只需要使持续时间很小并使用forwards

.container {
  position: relative;
}

label {
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  width: 50px;
  height: 50px;
  line-height: 50px;
  background: #eeeeee;
  text-align: center;
  animation: changeOrder 0.6s infinite;
}

@keyframes changeOrder {
  from { z-index: 6;}
   to { z-index: 1; }
}
label:nth-of-type(1) { animation-delay: 0s; }
label:nth-of-type(2) { animation-delay: -0.1s; }
label:nth-of-type(3) { animation-delay: -0.2s; }
label:nth-of-type(4) { animation-delay: -0.3s; }
label:nth-of-type(5) { animation-delay: -0.4s; }
label:nth-of-type(6) { animation-delay: -0.5s; }


label:active {
  /*Mandatory to break the stacking context and allow 
       the pseudo element to be above everything*/
  position: static;
  /*For illustration*/
  margin-left: 50px;
  background: red;
}

label:active::before {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  bottom: 0;
  z-index: 10;
}
.player {
  display:inline-block;
  margin-top:80px;
}

.player:before {
 content:"Click the dice!";
 animation: player .1s forwards;
 animation-play-state: paused;
}

label:focus ~ .player:before{
 animation-play-state: running;
}

@keyframes player {
  2%,100% {
     content:"Dice clicked!";
  }

}
<input type="radio" name="cb" id="cb1" value="1">
<input type="radio" name="cb" id="cb2" value="2">
<input type="radio" name="cb" id="cb3" value="3">
<input type="radio" name="cb" id="cb4" value="4">
<input type="radio" name="cb" id="cb5" value="5">
<input type="radio" name="cb" id="cb6" value="6">
<div class="container">
  <label for="cb1" tabindex="-1">1</label>
  <label for="cb2" tabindex="-1">2</label>
  <label for="cb3" tabindex="-1">3</label>
  <label for="cb4" tabindex="-1">4</label>
  <label for="cb5" tabindex="-1">5</label>
  <label for="cb6" tabindex="-1">6</label>
  <span class="player" ></span>
</div>

更新2

这是另一个依赖于过渡且更准确的想法,但我需要依靠两个骰子,因为每个骰子都会触发特定状态以更改文本,因此我们需要找到一种方法来制作两个骰子彼此上方并点击更改其顺序:

.container {
  position:relative;
  margin-top:20px;
  overflow:hidden;
  min-height:50px;
}

label {
  display:block;
  position: absolute;
  top: 0;
  left: 0;
  width: 50px;
  height: 50px;
  line-height: 50px;
  background: #eeeeee;
  text-align: center;
  animation: changeOrder 0.6s infinite;
}
label:active {
  /*Mandatory to break the stacking context and allow 
       the pseudo element to be above everything*/
  position: static;
  width:0;
  height:0;
  overflow:hidden;
}

label:active::before {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  bottom: 0;
  z-index: 10;
}

@keyframes changeOrder {
  from { z-index: 6;}
   to { z-index: 1; }
}
label:nth-of-type(1),label:nth-of-type(7) { animation-delay: 0s; }
label:nth-of-type(2),label:nth-of-type(8) { animation-delay: -0.1s; }
label:nth-of-type(3),label:nth-of-type(9) { animation-delay: -0.2s; }
label:nth-of-type(4),label:nth-of-type(10) { animation-delay: -0.3s; }
label:nth-of-type(5),label:nth-of-type(11) { animation-delay: -0.4s; }
label:nth-of-type(6),label:nth-of-type(12) { animation-delay: -0.5s; }



label.second {
  left:100px;
}

.player {
  display:inline-block;
  margin-top:80px;
  height: 18px;
  overflow:hidden;
}
.player span {
  display:block;
  margin-top:-18px;
  transition:1000s;
}



label.first:focus ~ .player span{
  margin-top:0;
  transition:0s;
}
label.second:focus ~ .player span{
  margin-top:-36px;
  transition:0s;
}
<input type="radio" name="cb" id="cb1" value="1">
<input type="radio" name="cb" id="cb2" value="2">
<input type="radio" name="cb" id="cb3" value="3">
<input type="radio" name="cb" id="cb4" value="4">
<input type="radio" name="cb" id="cb5" value="5">
<input type="radio" name="cb" id="cb6" value="6">
<div class="container">
<label class="first" for="cb1" tabindex="-1">1</label>
<label class="first" for="cb2" tabindex="-1">2</label>
<label class="first" for="cb3" tabindex="-1">3</label>
<label class="first" for="cb4" tabindex="-1">4</label>
<label class="first" for="cb5" tabindex="-1">5</label>
<label class="first" for="cb6" tabindex="-1">6</label>
  
<label class="second" for="cb1" tabindex="-1">1</label>
<label class="second" for="cb2" tabindex="-1">2</label>
<label class="second" for="cb3" tabindex="-1">3</label>
<label class="second" for="cb4" tabindex="-1">4</label>
<label class="second" for="cb5" tabindex="-1">5</label>
<label class="second" for="cb6" tabindex="-1">6</label>

<div class="player">
 <span> Player One Clicked<br>
  Which player?<br>
  Player Two clicked
 </span>
</div>
</div>

作为旁注,我使用了:focus:active,因此我们可以依赖那些状态,因为即使嵌套了元素,它们也可以一起触发:

div {
  display:block;
  outline: none;
  padding:10px 0;
}
.first:active + div{
  color:red
}
.second:active + div{
  color:red
}

.first:focus + div{
  border:1px solid red
}
.second:focus + div{
  border:1px solid red
}
<div class="first" tabindex=-1 >
  Click me (only last text will change)
  <div class="second" tabindex=-1 >
    Click me (both text will change)
  </div>
  <div>
    I will be updated
  </div>
</div>
<div>
  I will be updated
</div>

答案 1 :(得分:4)

关于您的疑问,无法通过html标签元素的for属性来定位多个元素。

但是如果重新加载页面就可以开始新游戏了,那么您实际上并不需要一次用标签定位两个输入。

这是仅使用CSS的简单骰子游戏:

.board {
  width: 100%;
  height: 200px;
  background: green;
  position: relative;
}

.board .title {
  color: white;
  font-weight: 300;
  text-align: center;
}

.board .title #p2-turn {
  display: none;
}

.dice {
  width: 50px;
  height: 50px;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  background: white;
  cursor: pointer;
  text-align: center;
}

.dice .pips {
  position: absolute;
  width: 100%;
  height: 100%;
  left: 0;
  animation: diceRoll 600ms infinite;
  z-index: 10;
}

.dice:active .pips {
  animation-play-state: paused;
}


.dice .pips:nth-child(2) { animation-delay: 100ms; }
.dice .pips:nth-child(3) { animation-delay: 200ms; }
.dice .pips:nth-child(4) { animation-delay: 300ms; }
.dice .pips:nth-child(5) { animation-delay: 400ms; }
.dice .pips:nth-child(6) { animation-delay: 500ms; }

.dice.dice--p2 {
  display: none;
}

.results {
  position: absolute;
  left: 0;
  top: 30px;
  bottom: 0;
  right: 0;
  background: black;
  color: white;
  display: none;
  text-align: center;
  line-height: 100px;
}

.results > .result {
  display: none;
}


@keyframes diceRoll {
  from { 
    z-index: 6;
  }
  to { 
    z-index: 1;
  }
}

/* LOGIC */

[name="p1-result"]:checked ~ .board .title #p1-turn {
  display: none;
}

[name="p1-result"]:checked ~ .board .title #p2-turn {
  display: block;
}

[name="p1-result"]:checked ~ .board .dice--p1 {
  display: none;
}

[name="p1-result"]:checked ~ .board .dice--p2 {
  display: block;
}

[name="p1-result"]:checked ~ [name="p2-result"]:checked ~ .results {
  display: block;
}



#p1-result-2:checked ~ #p2-result-1:checked ~ .results #p1-results,
#p1-result-3:checked ~ #p2-result-1:checked ~ .results #p1-results,
#p1-result-4:checked ~ #p2-result-1:checked ~ .results #p1-results,
#p1-result-5:checked ~ #p2-result-1:checked ~ .results #p1-results,
#p1-result-6:checked ~ #p2-result-1:checked ~ .results #p1-results,
#p1-result-3:checked ~ #p2-result-2:checked ~ .results #p1-results,
#p1-result-4:checked ~ #p2-result-2:checked ~ .results #p1-results,
#p1-result-5:checked ~ #p2-result-2:checked ~ .results #p1-results,
#p1-result-6:checked ~ #p2-result-2:checked ~ .results #p1-results,
#p1-result-4:checked ~ #p2-result-3:checked ~ .results #p1-results,
#p1-result-5:checked ~ #p2-result-3:checked ~ .results #p1-results,
#p1-result-6:checked ~ #p2-result-3:checked ~ .results #p1-results,
#p1-result-5:checked ~ #p2-result-4:checked ~ .results #p1-results,
#p1-result-6:checked ~ #p2-result-4:checked ~ .results #p1-results,
#p1-result-6:checked ~ #p2-result-5:checked ~ .results #p1-results,

#p1-result-1:checked ~ #p2-result-2:checked ~ .results #p2-results,
#p1-result-1:checked ~ #p2-result-3:checked ~ .results #p2-results,
#p1-result-1:checked ~ #p2-result-4:checked ~ .results #p2-results,
#p1-result-1:checked ~ #p2-result-5:checked ~ .results #p2-results,
#p1-result-1:checked ~ #p2-result-6:checked ~ .results #p2-results,
#p1-result-2:checked ~ #p2-result-3:checked ~ .results #p2-results,
#p1-result-2:checked ~ #p2-result-4:checked ~ .results #p2-results,
#p1-result-2:checked ~ #p2-result-5:checked ~ .results #p2-results,
#p1-result-2:checked ~ #p2-result-6:checked ~ .results #p2-results,
#p1-result-3:checked ~ #p2-result-4:checked ~ .results #p2-results,
#p1-result-3:checked ~ #p2-result-5:checked ~ .results #p2-results,
#p1-result-3:checked ~ #p2-result-6:checked ~ .results #p2-results,
#p1-result-4:checked ~ #p2-result-5:checked ~ .results #p2-results,
#p1-result-4:checked ~ #p2-result-6:checked ~ .results #p2-results,
#p1-result-5:checked ~ #p2-result-6:checked ~ .results #p2-results {
  display: block;
}

#p1-result-1:checked ~ #p2-result-1:checked ~ .results #draw,
#p1-result-2:checked ~ #p2-result-2:checked ~ .results #draw,
#p1-result-3:checked ~ #p2-result-3:checked ~ .results #draw,
#p1-result-4:checked ~ #p2-result-4:checked ~ .results #draw,
#p1-result-5:checked ~ #p2-result-5:checked ~ .results #draw,
#p1-result-6:checked ~ #p2-result-6:checked ~ .results #draw {
  display: block;
}
<input type="radio" name="p1-result" id="p1-result-1" value="1">
<input type="radio" name="p1-result" id="p1-result-2" value="2">
<input type="radio" name="p1-result" id="p1-result-3" value="3">
<input type="radio" name="p1-result" id="p1-result-4" value="4">
<input type="radio" name="p1-result" id="p1-result-5" value="5">
<input type="radio" name="p1-result" id="p1-result-6" value="6">

<input type="radio" name="p2-result" id="p2-result-1" value="1">
<input type="radio" name="p2-result" id="p2-result-2" value="2">
<input type="radio" name="p2-result" id="p2-result-3" value="3">
<input type="radio" name="p2-result" id="p2-result-4" value="4">
<input type="radio" name="p2-result" id="p2-result-5" value="5">
<input type="radio" name="p2-result" id="p2-result-6" value="6">


<div class="board">
  <h2 class="title">
    Player
    <span class="turn" id="p1-turn">1</span>
    <span class="turn" id="p2-turn">2</span>
    turn 
  </h2>
  <div class="dice dice--p1">
    roll
    <label class="pips" for="p1-result-1"></label>
    <label class="pips" for="p1-result-2"></label>
    <label class="pips" for="p1-result-3"></label>
    <label class="pips" for="p1-result-4"></label>
    <label class="pips" for="p1-result-5"></label>
    <label class="pips" for="p1-result-6"></label>
  </div>

  <div class="dice dice--p2">
    <label class="pips" for="p2-result-1"></label>
    <label class="pips" for="p2-result-2"></label>
    <label class="pips" for="p2-result-3"></label>
    <label class="pips" for="p2-result-4"></label>
    <label class="pips" for="p2-result-5"></label>
    <label class="pips" for="p2-result-6"></label>
  </div>
</div>

<div class="results">
  <div class="result" id="p1-results">Player 1 won!</div>
  <div class="result" id="p2-results">Player 2 won!</div>
  <div class="result" id="draw">Draw!</div>
</div>

这很容易修改,以显示玩家当前的图块并确定一定的结果。

答案 2 :(得分:3)

老实说,我认为没有任何一种方法可以仅使用HTML和CSS来切换多个复选框状态。

这并不是说CSS不能通过使元素样式化的方式使之更加直观,使玩家之间的切换更像是过程的一部分。

我整理了一个简单的示例片段,提供了一种实现方法(使用基本的不透明度和游标样式)。但是,该方法可以在许多不同的方法中使用。

例如,您可以将模具完全移出屏幕,或切换div以阻止显示/单击元素(使用绝对定位和z-index)。

实际上,可以使用z-index方法来实现玩家切换,而不必完全移动光标,从而从玩家的角度来看更加直观。

Die rolling.

希望这些想法将有助于取得成功-或消亡,滚动。

/* Simple Checkbox Hack */

input[type=checkbox] {
  position: absolute;
  left: -9999px;
  }

.die { 
  position: absolute;
  height: 5em;
  width: 5em;
  background: lightgray;
  border: 1pt solid gray;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: 16px;
  line-height: 5em;
  margin: .5em;
  cursor: pointer;
  }



/* Default State */

.p1, .p2 {
  width: 30em;
  height: 2em;
  line-height: 2em;
  color: white;
  text-align: center;
  opacity: 0.3;
  cursor: not-allowed;
  }

.p1 {
  background: green;
  }

.p2 {
  background: blue;
  }



/* Toggled State */

input[type=checkbox]:checked ~ .p1 {
   opacity: 1;
   cursor: pointer;
}
input[type=checkbox]:checked ~ .die {
   opacity: 0.3;
   cursor: not-allowed;
}
<small style="color: gray;"> (For this example, die can be clicked more than once.) </small>
<br>
<input type="checkbox" id="toggle-1">
<label class="die" for="toggle-1">Roll me!</label>
<br> <br> <br> <br> <br> <br>
<div class="p1">Player 1 - Click to start.</div>
<div class="p2">Player 2 - Click to start.</div>

答案 3 :(得分:3)

编辑后的答案以反映对原始问题的更改:

尝试设置不同的状态,每个状态都同时反映活动玩家的位置,例如:

input {
  position: absolute;
  bottom: 1em;
  right: 1em;
  margin: 2px;
}

.status {
  margin: 1em;
  font-family: sans-serif;
  display: none;
}
.active1:checked ~ #status1,
.active2:checked ~ #status2,
.win1:checked ~ #status3,
.win2:checked ~ #status4 {
  display: block
}

#board {
  position: relative;
  top: 0;
  left: 0;
  border: 1px solid black;
  padding: 2px 3px;
  margin: 1em auto;
  width: 27em;
  height: 12em;
}
#board:before {
  display: block;
  position: absolute;
  bottom: 0;
  left: 0;
  margin: 2px;
  height: 9em;
  width: 9em;
  background: silver;
  content: ' ';
}
#board:after {
  display: block;
  position: absolute;
  bottom: 0;;
  right: 0;
  margin: 2px;
  height: 9em;
  width: 9em;
  background: silver;
  content: ' ';
}

.piece {
  position: absolute;
  z-index: 2;
  width: 1em;
  height: 1em;
  padding: 1em;
  margin: 1px;
  border-radius: 666em;
  line-height: 1em;
  text-align: center;
}
#piece1 {
  background: white;
  color: black;
  border: 1px solid black;
}
#piece2 {
  background: black;
  color: white;
  border: 1px solid white;
}
.win2:checked ~ #piece1,
.win1:checked ~ #piece2 {
  display: none;
}
.active1:checked ~ #piece1,
.active2:checked ~ #piece2 {
  border: 1px solid red;
}
.p1_1:checked ~ #piece1,
.p2_1:checked ~ #piece2 {
  left: 3em;
  bottom: 3em;
}
.p1_2:checked ~ #piece1,
.p2_2:checked ~ #piece2 {
  left: 12em;
  bottom: 3em;
}
.p1_3:checked ~ #piece1,
.p2_3:checked ~ #piece2 {
  right: 3em;
  bottom: 3em;
}

label {
  display: none;
  position: absolute;
  bottom: 0;
  z-index: 3;
  width: 9em;
  height: 9em;
  margin: 2px;
  text-indent: -666666em;
  /*background: green;*/
  opacity: .25;
  cursor: pointer;
}
label.pos1 {
  left: 0;
}
label.pos2 {
  left: 9em;
  margin: 2px 3px;
}
label.pos3 {
  right: 0
}
label.restart {
   top: 0;
   left: 0;
   width: 27em;
   height: 12em;
   padding: 0 1px;
   /*background: orange;*/
}
label.win1,
label.win2 {
  /*background: blue;*/
}
.active1.p2_1:checked ~ label.active1.opp1,
.active1.p2_2:checked ~ label.active1.opp2,
.active1.p2_3:checked ~ label.active1.opp3,
.active2.p1_1:checked ~ label.active2.opp1,
.active2.p1_2:checked ~ label.active2.opp2,
.active2.p1_3:checked ~ label.active2.opp3 {
  display: block;
}
.active1.p1_1:checked ~ label.active1.pos1,
.active1.p1_2:checked ~ label.active1.pos2,
.active1.p1_3:checked ~ label.active1.pos3,
.active2.p2_1:checked ~ label.active2.pos1,
.active2.p2_2:checked ~ label.active2.pos2,
.active2.p2_3:checked ~ label.active2.pos3 {
  display: none;
}
.active1.p2_1:checked ~ label.win1.pos1,
.active1.p2_2:checked ~ label.win1.pos2,
.active1.p2_3:checked ~ label.win1.pos3,
.active2.p1_1:checked ~ label.win2.pos1,
.active2.p1_2:checked ~ label.win2.pos2,
.active2.p1_3:checked ~ label.win2.pos3 {
  display: block;
}
.win1:checked ~ label.restart,
.win2:checked ~ label.restart {
  display: block;
}
<html>
  <head>
    <meta charset="utf-8">
    <title>some game</title>
  </head>
  <body>
    <div id="board">
      <input id="s1" class="active1 p1_1 p2_2" type="radio" name="state" value="1">
      <input id="s2" class="active1 p1_1 p2_3" type="radio" name="state" value="2" checked="checked">
      <input id="s3" class="active1 p1_2 p2_1" type="radio" name="state" value="3">
      <input id="s4" class="active1 p1_2 p2_3" type="radio" name="state" value="4">
      <input id="s5" class="active1 p1_3 p2_1" type="radio" name="state" value="5">
      <input id="s6" class="active1 p1_3 p2_2" type="radio" name="state" value="6">
      <input id="s7" class="active2 p1_1 p2_2" type="radio" name="state" value="7">
      <input id="s8" class="active2 p1_1 p2_3" type="radio" name="state" value="8">
      <input id="s9" class="active2 p1_2 p2_1" type="radio" name="state" value="9">
      <input id="s10" class="active2 p1_2 p2_3" type="radio" name="state" value="10">
      <input id="s11" class="active2 p1_3 p2_1" type="radio" name="state" value="11">
      <input id="s12" class="active2 p1_3 p2_2" type="radio" name="state" value="12">
      <input id="s13" class="win1 p1_1" type="radio" name="state" value="13">
      <input id="s14" class="win1 p1_2" type="radio" name="state" value="14">
      <input id="s15" class="win1 p1_3" type="radio" name="state" value="15">
      <input id="s16" class="win2 p2_1" type="radio" name="state" value="16">
      <input id="s17" class="win2 p2_2" type="radio" name="state" value="17">
      <input id="s18" class="win2 p2_3" type="radio" name="state" value="18">
      <div id="status1" class="status">Player 1:</div>
      <div id="status2" class="status">Player 2:</div>
      <div id="status3" class="status">Player 1 won!</div>
      <div id="status4" class="status">Player 2 won!</div>
      <div id="piece1" class="piece">p1</div>
      <div id="piece2" class="piece">p2</div>
      <label for="s1" class="active2 pos2 opp1">Player 2: move piece to position 2</label>
      <label for="s2" class="active2 pos3 opp1">Player 2: move piece to position 3</label>
      <label for="s3" class="active2 pos1 opp2">Player 2: move piece to position 1</label>
      <label for="s4" class="active2 pos3 opp2">Player 2: move piece to position 3</label>
      <label for="s5" class="active2 pos1 opp3">Player 2: move piece to position 1</label>
      <label for="s6" class="active2 pos2 opp3">Player 2: move piece to position 2</label>
      <label for="s7" class="active1 pos1 opp2">Player 1: move piece to position 1</label>
      <label for="s8" class="active1 pos1 opp3">Player 1: move piece to position 1</label>
      <label for="s9" class="active1 pos2 opp1">Player 1: move piece to position 2</label>
      <label for="s10" class="active1 pos2 opp3">Player 1: move piece to position 2</label>
      <label for="s11" class="active1 pos3 opp1">Player 1: move piece to position 3</label>
      <label for="s12" class="active1 pos3 opp2">Player 1: move piece to position 3</label>
      <label for="s13" class="win1 pos1">Player 1: move piece to position 1</label>
      <label for="s14" class="win1 pos2">Player 1: move piece to position 2</label>
      <label for="s15" class="win1 pos3">Player 1: move piece to position 3</label>
      <label for="s16" class="win2 pos1">Player 2: move piece to position 1</label>
      <label for="s17" class="win2 pos2">Player 2: move piece to position 2</label>
      <label for="s18" class="win2 pos3">Player 2: move piece to position 3</label>
      <label for="s2" class="restart">Restart game</label>
    </div>
  </body>
</html>

这只是非常的一个简单示例,其中每个玩家都可以将自己的棋子移到他想要的任何位置,并且如果对手的棋子“碰巧”进入该字段,他就会获胜。

在现实世界中,您可以考虑使用一些HTML-和CSS- 预处理器,例如Pug / JadeSass来迭代所有可能的状态组合。

更新

我想不通,所以我玩了一下...

:focus似乎是一个不错的起点,所以我尝试了一下(提示:确保在tabindex="0"上设置<label>。但是事物总是有秩序的,我找不到使用~来实现双向关系的方法。

所以我回到昨天的评论中,关于使“下一个播放器”按钮的用户体验更加“流畅”。 Here是我的代码(基本思想是将“下一个玩家”按钮更改为“确认移动”状态,在该状态下玩家可以确认自己的移动或选择要移至的另一个磁贴)。不,这不是您的问题的答案,但这似乎是您的问题的解决方案(它或多或少地“很好地”缩放,至少是线性的,不是立方的) 。 html / css似乎有点笨拙,无法在这里发布,而Jade / Sass我无法工作,因此以下是这些文件的链接:

答案 4 :(得分:-1)

这是您要找的吗?

.boxes {
  height: 80px;
  width: 80px;
  background-color: white;
  border: 1px solid black;
  position: relative;
}

.boxes span {
  position: absolute;
  width: 100%;
  height: 100%;
}

.boxes a div {
  display: none;
}

.boxes a:target div {
  display: block;
  height: 80px;
  width: 80px;
  background-color: black;
  border: 1px solid black;
  position: absolute;
  margin-left: 150px;
}

.boxes a:target span {
  background-color: black;
}

a {
  color: white;
}
<div class="boxes">
  <a href="#firstgroup" id="firstgroup">
    <span>Box A</span>
    <div>Box B</div>
  </a>
</div>

<div class="boxes">
  <a href="#secondgroup" id="secondgroup">
    <span>Box C</span>
    <div>Box D</div>
  </a>
</div>

这使用:target只需一个触发器即可更改多个元素的属性。

答案 5 :(得分:-1)

您的:invalid尝试无效,因为单选按钮中的required参数将验证组中的任何个按钮(共享相同{ {1}})被选中

作为替代方案,您可以将name选择器与:not一起使用

:checked

#radio1:not(:checked) + #radio2:checked ~ div
div {
  color: purple;
}

#radio1:checked ~ div {
  color: blue;
}

#radio2:checked ~ div {
  color: fuchsia;
}

#radio1:not(:checked) ~ div {
  color: red;
}

#radio1:not(:checked) + #radio2:checked ~ div {
  color: green;
}

也许这足以使您的游戏正常运行:)