css - 选中时输入单选按钮以定位外部标签

css - Input radio button to target outter label when checked

我在 codepen 上找到了以下代码,它可以正常工作并且看起来很棒!

.switch-field {
    display: flex;
    margin-bottom: 36px;
    overflow: hidden;
}

.switch-field input {
    position: absolute !important;
    clip: rect(0, 0, 0, 0);
    height: 1px;
    width: 1px;
    border: 0;
    overflow: hidden;
}

.switch-field label {
    background-color: #e4e4e4;
    color: rgba(0, 0, 0, 0.6);
    font-size: 14px;
    line-height: 1;
    text-align: center;
    padding: 8px 16px;
    margin-right: -1px;
    border: 1px solid rgba(0, 0, 0, 0.2);
    box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3), 0 1px rgba(255, 255, 255, 0.1);
    transition: all 0.1s ease-in-out;
}

.switch-field label:hover {
    cursor: pointer;
}

.switch-field input:checked + label {
    background-color: #a5dc86;
    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;
}
<form class="form">
    <div class="switch-field">
        <input type="radio" id="radio-three" name="switch-two" value="yes" checked/>
        <label for="radio-three">One</label>
        <input type="radio" id="radio-four" name="switch-two" value="maybe" />
        <label for="radio-four">Two</label>
        <input type="radio" id="radio-five" name="switch-two" value="no" />
        <label for="radio-five">Three</label>
    </div>
</form>

但不幸的是,我生成的 HTML 布局如下(标签内的输入):

<form class="form">
    <div class="switch-field">
        <label for="radio-three">
      <input type="radio" id="radio-three" name="switch-two" value="yes" checked/>
    One</label> 
        <label for="radio-four">
      <input type="radio" id="radio-four" name="switch-two" value="maybe" />
    Two</label>
        <label for="radio-five">
      <input type="radio" id="radio-five" name="switch-two" value="no" />
    Three</label>
    </div>
</form>

我想知道是否可以仅使用 CSS 来调整此 class 以使其工作,或者是否需要 JS。

.switch-field input:checked + label {
background-color: #a5dc86;
box-shadow: none;
}

非常感谢!

是的,将 .switch-field input 替换为 .switch-field label input

x1 x2 x3 ... xn—1 xn 形式的选择器(space 分隔)表示 xnxn−1 的后代,依此类推。

唯一的 CSS 可能的解决方案

pseudo-selector :focus-within。如果一个元素有任何具有焦点的子元素,则该父元素将应用样式。因此,用户检查的单选按钮将触发焦点事件,并在这样做时激活具有 :focus-within 的 CSS 规则集,这是以下示例中的标签。

.switch-field label:focus-within {
  background-color: #a5dc86;
  box-shadow: none;
}
<form class="form">
  <div class="switch-field">
    <label for="radio-three">
      <input type="radio" id="radio-three" name="switch-two" value="yes" checked/>
    One</label>
    <label for="radio-four">
      <input type="radio" id="radio-four" name="switch-two" value="maybe" />
    Two</label>
    <label for="radio-five">
      <input type="radio" id="radio-five" name="switch-two" value="no" />
    Three</label>
  </div>
</form>

下面是如何通过 javascript

实现所需功能的示例

var checkboxes = document.querySelectorAll("input[type=radio]");
var labels = document.querySelectorAll("label");
labels[0].classList.add("checkedLabel");

checkboxes.forEach(function(checkbox) {
  checkbox.addEventListener('change', function(e) {
    Array.from(labels).forEach(function(el) {
      el.classList.remove('checkedLabel');
    });
    this.parentElement.classList.add("checkedLabel");
  })
})
.checkedLabel {
  background-color: #a5dc86;
  box-shadow: none;
}
<form class="form">
  <div class="switch-field">
    <label for="radio-three">
      <input type="radio" id="radio-three" name="switch-two" value="yes" checked/>
    One</label>
    <label for="radio-four">
      <input type="radio" id="radio-four" name="switch-two" value="maybe" />
    Two</label>
    <label for="radio-five">
      <input type="radio" id="radio-five" name="switch-two" value="no" />
    Three</label>
  </div>
</form>

你应该使用 JS。

当输入元素在标签内时,我们不需要元素上的 id 和标签上的 'for' 属性,但当它在标签外时,我们需要它。

<label>
  Foo
  <input name="foo" type="checkbox" />
</label>

根据您的 HTML 代码,要更改标签的样式,需要 selector 影响父级,这目前是不可能的。 为什么? https://css-tricks.com/parent-selectors-in-css/

<input id="foo" name="foo" type="checkbox" />
<label for="foo">Foo</label>

因此,对于 select :checked 输入的标签,我们需要标签是相邻的,而不是父标签。

但是在你的代码中,HTML的标签和输入是隐式连接的。所以我认为解决方案是使用JS。

let form = document.querySelector("form");

form.addEventListener("change", (event) => {
  let target = event.target;
  let targetParent = target.parentElement;

  if (
    target.type === "radio" &&
    targetParent &&
    targetParent.tagName.toLowerCase() === "label"
  ) {
    let prior = form.querySelector('label.checked input[name="' + target.name + '"]');
    if (prior) {
      prior.parentElement.classList.remove("checked");
    }
    targetParent.classList.add("checked");
  }
}, false);
.switch-field {
  display: flex;
  margin-bottom: 36px;
  overflow: hidden;
}

.switch-field input {
  position: absolute !important;
  clip: rect(0, 0, 0, 0);
  height: 1px;
  width: 1px;
  border: 0;
  overflow: hidden;
}

.switch-field label {
  background-color: #e4e4e4;
  color: rgba(0, 0, 0, 0.6);
  font-size: 14px;
  line-height: 1;
  text-align: center;
  padding: 8px 16px;
  margin-right: -1px;
  border: 1px solid rgba(0, 0, 0, 0.2);
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.3), 0 1px rgba(255, 255, 255, 0.1);
  transition: all 0.1s ease-in-out;
}

.switch-field label:hover {
  cursor: pointer;
}

.switch-field label.checked {
  background-color: #a5dc86;
  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;
}
<form class="form">
  <div class="switch-field">
    <label class="checked">
      <input type="radio" name="switch-two" value="yes" checked />
      One
    </label>
    <label>
      <input type="radio" name="switch-two" value="maybe" />
      Two
    </label>
    <label>
      <input type="radio" name="switch-two" value="no" />
      Three
    </label>
  </div>
</form>