Есть ли способ вызвать два изменения, нажав только одну метку?
Я играл с HTML и CSS, чтобы создать простую настольную игру с двумя игроками без использования JavaScript. Я использую метки, переключатели и флажки для создания разных состояний и имитирую какую-то логику, поэтому кусок будет перемещаться по доске.
Он работает "отлично", хотя удобство использования не очень велико. Например, после нажатия на кубик, плитка перемещается, и я показываю кнопку, чтобы перейти к следующему игроку (снова контролируется меткой и флажком)... что не очень хорошо, было бы лучше, если бы он изменил игрока "автоматически."
Проблема в том, что <label>
может ориентироваться только на один элемент, и я не знаю, как запускать два "действия" (или побочные эффекты) одним щелчком мыши.
Следующий код - это mcve, чтобы лучше визуализировать проблему: есть два игрока (по очереди), доска с тремя фрагментами (представленная 6 переключателями: 1 на игрока и плитка) и две кнопки для изменения поворота игрока (только один видимый). Если вы нажмете кнопку изменения поворота, поворот перейдет к следующему игроку. (Более сложный пример можно найти здесь)
Проблема в том, что пользователи вынуждены нажимать кнопку, чтобы изменить поворот, иначе один и тот же игрок всегда будет активным. Есть ли способ сделать так, чтобы при нажатии на ярлык активизировалась не только плитка, но и поворот? Или в его отсутствие есть ли альтернатива для достижения этого? (без использования 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>
Ответы
Ответ 1
Одна из идей - рассмотреть состояние :focus
на ярлыке, которое позволит вам вызвать два изменения. Единственный недостаток заключается в том, что :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
Что касается вас, вопрос заключается в невозможности нацеливать несколько элементов с помощью атрибута for
элемента html label.
Но если перезагрузка страницы прекрасна, чтобы начать новую игру, вам не нужно будет сразу нацеливать два входа на ярлык.
Здесь простая игра в кости, использующая только 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>
Ответ 3
Я честно не думаю, что есть какой-либо метод, который может переключать несколько состояний флажка, используя только HTML и CSS.
Это не означает, что с CSS нельзя было бы сделать более интуитивно понятным, стилизовав элементы таким образом, чтобы переключение между игроками стало более похожим на просто часть процесса.
Я взломал быстрый и грязный примерный фрагмент, который предоставляет метод реализации (используя базовую непрозрачность и стили курсора). Однако этот метод можно использовать во множестве различных подходов.
Например, вы можете полностью перемещать матрицу за пределы экрана или переключать div, чтобы заблокировать элементы от просмотра/щелчка (используя абсолютное позиционирование и z-индекс).
Фактически, подход z-index может использоваться для того, чтобы разрешить переключение игрока без перемещения курсора вообще, тем самым делая его более интуитивным с точки зрения игрока.
Надеюсь, эти идеи помогут получить мяч - или умереть, катятся. 😁
/* 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>
Ответ 4
Отредактированный ответ, чтобы отразить изменения в исходном вопросе:
Попробуйте установить разные состояния, в которых каждое состояние отражает как активный игрок, так и позицию частей, например:
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>
Ответ 5
Это то, что вы ищете?
.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>
Ответ 6
Ваша :invalid
попытка не работает, потому что required
параметр в переключателе будет проверять, выбрана ли какая-либо из кнопок в группе (кто-то с тем же name
)
В качестве альтернативы вы можете использовать :not
selector with :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;
}
<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>