Переключение радиовхода с использованием только 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();