Переключение радиовхода с использованием только CSS
В следующем коде используется script для переключения/снятия отметки с радио при повторном нажатии на второй раз.
Мой вопрос: как это сделать, используя только CSS?
(function(lastimg) {
document.querySelector("#img-select").addEventListener('click', function(e){
if (e.target.tagName.toLowerCase() == 'input') {
if (lastimg == e.target) {
e.target.checked = false;
lastimg = null;
} else {
lastimg = e.target;
}
}
});
}());
.container {
display: flex;
flex-wrap: wrap;
max-width: 660px;
}
.container > label {
flex: 1;
flex-basis: 33.333%;
}
.container > div {
flex: 1;
flex-basis: 100%;
}
.container label img {
display: block;
margin: 0 auto;
}
.container input, .container input ~ div {
display: none;
padding: 10px;
}
.container #img1:checked ~ #img1txt,
.container #img2:checked ~ #img2txt,
.container #img3:checked ~ #img3txt,
.container #img4:checked ~ #img4txt {
display: block;
}
<div id="img-select" class="container">
<input id="img1" type="radio" name="img-descr">
<input id="img2" type="radio" name="img-descr">
<input id="img3" type="radio" name="img-descr">
<label for="img1">
<img src="http://lorempixel.com/200/200/food/1/" alt="">
</label>
<label for="img2">
<img src="http://lorempixel.com/200/200/food/6/" alt="">
</label>
<label for="img3">
<img src="http://lorempixel.com/200/200/food/8/" alt="">
</label>
<div id="img1txt">
<div>Recipe nr 1</div>
</div>
<div id="img2txt">
<div>Recipe nr 2</div>
</div>
<div id="img3txt">
<div>Recipe nr 3</div>
</div>
</div>
Ответы
Ответ 1
Вы не можете изменить функциональность переключателей с помощью CSS. CSS предназначен только для визуальных изменений.
Тем не менее, вы можете имитировать это поведение с помощью умного взлома. Для вашего примера я бы рекомендовал использовать CSS для визуальной замены метки для выбранного в настоящий момент радиокнопки с фиктивной меткой, прикрепленной к другой радиокнопке, представляющей "пустой" или "пустой" выбор. Таким образом, щелчок на фиктивной метке выберет "пустой" вариант, эффективно очистив ваш предыдущий выбор:
.container {
display: flex;
flex-wrap: wrap;
max-width: 660px;
}
.container > label {
flex: 1;
flex-basis: 33.333%;
}
.container > div {
flex: 1;
flex-basis: 100%;
}
.container label img {
display: block;
margin: 0 auto;
}
.container input, .container input ~ div {
display: none;
padding: 10px;
}
.container #img1:checked ~ #img1txt,
.container #img2:checked ~ #img2txt,
.container #img3:checked ~ #img3txt {
display: block;
}
.container label[for=noimg] {
display: none;
}
.container #img1:checked ~ label[for=img1],
.container #img2:checked ~ label[for=img2],
.container #img3:checked ~ label[for=img3] {
display: none;
}
.container #img1:checked ~ label[for=img1] + label[for=noimg],
.container #img2:checked ~ label[for=img2] + label[for=noimg],
.container #img3:checked ~ label[for=img3] + label[for=noimg] {
display: block;
}
<div id="img-select" class="container">
<input id="noimg" type="radio" name="img-descr">
<input id="img1" type="radio" name="img-descr">
<input id="img2" type="radio" name="img-descr">
<input id="img3" type="radio" name="img-descr">
<label for="img1">
<img src="http://lorempixel.com/200/200/food/1/" alt="">
</label>
<label for="noimg">
<img src="http://lorempixel.com/200/200/food/1/" alt="">
</label>
<label for="img2">
<img src="http://lorempixel.com/200/200/food/6/" alt="">
</label>
<label for="noimg">
<img src="http://lorempixel.com/200/200/food/6/" alt="">
</label>
<label for="img3">
<img src="http://lorempixel.com/200/200/food/8/" alt="">
</label>
<label for="noimg">
<img src="http://lorempixel.com/200/200/food/8/" alt="">
</label>
<div id="img1txt">
<div>Recipe nr 1</div>
</div>
<div id="img2txt">
<div>Recipe nr 2</div>
</div>
<div id="img3txt">
<div>Recipe nr 3</div>
</div>
</div>
Ответ 2
Если эффект не должен быть постоянным, вы можете добиться чего-то подобного с помощью :focus
вместо использования переключателей.
Чтобы создать элемент focusable, установите атрибут tabindex
в целое число. Используйте отрицательный, если вы не хотите, чтобы элемент был достигнут с помощью последовательной навигации по фокусу (нажатие клавиши "tab" ).
.container {
display: flex;
flex-wrap: wrap;
max-width: 660px;
}
.container > .img {
flex: 1;
position: relative;
}
.container > .img > .unselect {
display: none;
position: absolute;
top: 0; right: 0; bottom: 0; left: 0;
}
.container > .txt {
display: none;
order: 1;
flex-basis: 100%;
}
.container > .img:focus > .unselect,
.container > .img:focus + .txt {
display: block;
}
<div id="img-select" class="container">
<div class="img" tabindex="0">
<img src="http://lorempixel.com/200/200/food/1/" alt="">
<span class="unselect" tabindex="-1"></span>
</div>
<div class="txt">Recipe nr 1</div>
<div class="img" tabindex="0">
<img src="http://lorempixel.com/200/200/food/6/" alt="">
<span class="unselect" tabindex="-1"></span>
</div>
<div class="txt">Recipe nr 2</div>
<div class="img" tabindex="0">
<img src="http://lorempixel.com/200/200/food/8/" alt="">
<span class="unselect" tabindex="-1"></span>
</div>
<div class="txt">Recipe nr 3</div>
</div>
Ответ 3
Принята проблема с Bounty (без дополнительного noimg
)
.container {
display: flex;
flex-wrap: wrap;
max-width: 660px;
overflow: hidden;
position: relative;
}
.container img {
user-select: none;
pointer-events: none;
}
.container > label {
flex: 1;
flex-basis: 33.333%;
z-index: 1;
}
.container > div {
flex: 1;
flex-basis: 100%;
}
.container label img { margin: 0 auto }
.container input,
.container input ~ div {
display: none;
padding: 10px;
}
.container label[for=none] {
position: absolute;
bottom: 0;
top: 0;
left: 0;
right: 0;
z-index: 0;
}
.container #img1:checked ~ label[for=img1],
.container #img2:checked ~ label[for=img2],
.container #img3:checked ~ label[for=img3] {
pointer-events: none;
z-index: -1;
}
.container #img1:checked ~ #img1txt,
.container #img2:checked ~ #img2txt,
.container #img3:checked ~ #img3txt { display: block }
<div id="img-select" class="container">
<input id="img1" type="radio" name="img-descr">
<input id="img2" type="radio" name="img-descr">
<input id="img3" type="radio" name="img-descr">
<!-- Experimental -->
<input id="none" type="radio" name="img-descr" checked>
<label for="none"></label>
<label for="img1">
<img src="http://dummyimage.com/200/333" alt="">
</label>
<label for="img2">
<img src="http://dummyimage.com/200/666" alt="">
</label>
<label for="img3">
<img src="http://dummyimage.com/200/999" alt="">
</label>
<div id="img1txt">
<div>Recipe nr 1</div>
</div>
<div id="img2txt">
<div>Recipe nr 2</div>
</div>
<div id="img3txt">
<div>Recipe nr 3</div>
</div>
</div>
Ответ 4
Ответ заключается в том, что вы не можете отменить выбор или снять отметку с радиокнопки только в CSS, так как радиокнопка становится неконтролируемой только после нажатия на другой переключатель. Так как только один переключатель может быть активен сразу, это снимет флажок ранее установленного переключателя.
input:checked + label {
color: green;
}
input:not(:checked) + label {
color: red;
}
Таким образом, вам придется придерживаться используемой вами функции JS.
Вот несколько приятных статей с дальнейшим объяснением:
CSS Нажмите События
Как создать события кликов CSS
Ответ 5
Трюк использует :target
. Я добавил два пустых тега <a>
в каждом блоке и установил, что они полностью перекрывают блок, чтобы выполнить событие click. Первая ссылка предназначена для реального события :target
, а вторая ссылка предназначена только для его отмены, с небольшой помощью z-index
, чтобы это произошло.
jsFiddle
ul {
padding: 0;
margin: 0;
}
li {
display: inline-block;
vertical-align: top;
position: relative;
}
a {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
}
div {
display: none;
}
.target{
z-index: 1;
}
.target:target {
z-index: -1;
}
.target:target ~ div{
display: block;
}
<ul>
<li>
<a href="#link-1" id="link-1" class="target"></a>
<a href="#"></a>
<img src="//dummyimage.com/150/333">
<div>a</div>
</li>
<li>
<a href="#link-2" id="link-2" class="target"></a>
<a href="#"></a>
<img src="//dummyimage.com/150/666">
<div>b</div>
</li>
<li>
<a href="#link-3" id="link-3" class="target"></a>
<a href="#"></a>
<img src="//dummyimage.com/150/999">
<div>c</div>
</li>
</ul>
Ответ 6
попробуйте это
HTML Это потрясающе? да нет
<div class="switch-field">
<div class="switch-title">Three fields? Sure.</div>
<input type="radio" id="switch_3_left" name="switch_3" value="yes" checked/>
<label for="switch_3_left">One</label>
<input type="radio" id="switch_3_center" name="switch_3" value="maybe" />
<label for="switch_3_center">Two</label>
<input type="radio" id="switch_3_right" name="switch_3" value="no" />
<label for="switch_3_right">Three</label>
</div>
</form>
CSS:
.switch-field {
font-family: "Lucida Grande", Tahoma, Verdana, sans-serif;
padding: 40px;
overflow: hidden;
}
.switch-title {
margin-bottom: 6px;
}
.switch-field input {
display: none;
}
.switch-field label {
float: left;
}
.switch-field label {
display: inline-block;
width: 60px;
background-color: #e4e4e4;
color: rgba(0, 0, 0, 0.6);
font-size: 14px;
font-weight: normal;
text-align: center;
text-shadow: none;
padding: 6px 14px;
border: 1px solid rgba(0, 0, 0, 0.2);
-webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3), 0 1px rgba(255, 255, 255, 0.1);
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3), 0 1px rgba(255, 255, 255, 0.1);
-webkit-transition: all 0.1s ease-in-out;
-moz-transition: all 0.1s ease-in-out;
-ms-transition: all 0.1s ease-in-out;
-o-transition: all 0.1s ease-in-out;
transition: all 0.1s ease-in-out;
}
.switch-field label:hover {
cursor: pointer;
}
.switch-field input:checked + label {
background-color: #A5DC86;
-webkit-box-shadow: none;
box-shadow: none;
}
.switch-field label:first-of-type {
border-radius: 4px 0 0 4px;
}
.switch-field label:last-of-type {
border-radius: 0 4px 4px 0;
}
Ответ 7
У меня есть решение, которое находится на полпути через:
- Он очищает выбор при двойном щелчке, но не на клике (по запросу)
- Но (и что "на полпути" ), он не очистит выделение при двойном щелчке по выбранному в данный момент пункту (только при двойном щелчке на других элементах).
.container {
display: flex;
flex-wrap: wrap;
max-width: 660px;
overflow: hidden;
position: relative;
}
.container img {
user-select: none;
pointer-events: none;
}
.container > label {
flex: 1;
flex-basis: 33.333%;
}
.container > div {
flex: 1;
flex-basis: 100%;
}
.container label img {
margin: 0 auto
}
.container input,
.container input ~ div {
display: none;
padding: 10px;
}
.container label[for=none] {
position: absolute;
width: 200px;
height: 200px;
z-index: 1;
display: none;
}
.container #img1:checked ~ label[for=none],
.container #img2:checked ~ label[for=none],
.container #img3:checked ~ label[for=none] {
display: block;
}
@keyframes hideNone {
from {
z-index: 3;
}
to {
z-index: 3;
}
}
.container #img1:checked ~ label[for=img1],
.container #img2:checked ~ label[for=img2],
.container #img3:checked ~ label[for=img3] {
animation-name: hideNone;
animation-delay: 0.3s;
animation-duration: 99999s;
}
.container #img1:checked ~ label[for=none] {
left: 0;
}
.container #img2:checked ~ label[for=none] {
left: 220px;
}
.container #img3:checked ~ label[for=none] {
left: 440px;
}
.container #img1:checked ~ #img1txt,
.container #img2:checked ~ #img2txt,
.container #img3:checked ~ #img3txt {
display: block
}
<div id="img-select" class="container">
<input id="img1" type="radio" name="img-descr">
<input id="img2" type="radio" name="img-descr">
<input id="img3" type="radio" name="img-descr">
<input id="none" type="radio" name="img-descr" checked>
<label for="none"></label>
<input type="button" autofocus>
<label for="img1">
<img src="http://dummyimage.com/200/333" alt="">
</label>
<label for="img2">
<img src="http://dummyimage.com/200/666" alt="">
</label>
<label for="img3">
<img src="http://dummyimage.com/200/999" alt="">
</label>
<div id="img1txt">
<div>Recipe nr 1</div>
</div>
<div id="img2txt">
<div>Recipe nr 2</div>
</div>
<div id="img3txt">
<div>Recipe nr 3</div>
</div>
</div>
Ответ 8
Вы можете использовать переключатель в JQuery (http://api.jquery.com/toggle/):
$( ".target" ).toggle();