自定义单选框输入的:focus样式设计

19

我有一个自定义的单选框输入样式,实现方式大致如下:

<input type="radio" id="testradio" class="visuallyhidden custom-radio">
<label for="testradio">...</label>

.custom-radio + label:before {
  content: ""
  // Styling goes here
}

.custom-radio:focus + label:before {
  outline: 1px solid black;
]

这个方法很棒,除了一个烦人的细节:键盘导航的焦点样式。我可以通过Tab键选择一组单选按钮,并使用箭头键更改所选项,但默认的:focus轮廓不会出现,因为输入标签是隐藏的。

我尝试添加自己的焦点样式,但这最终表现与默认的浏览器样式不同。默认情况下,Chrome(和其他浏览器)仅在您使用键盘选择单选框时绘制轮廓,而不是在单击它们时。然而,CSS :focus样式似乎也适用于单击单选框(或在此情况下单击标签),这看起来非常糟糕。

基本上我的问题是:如何应用:f ocus样式到单选框,以完全模拟默认的浏览器行为,即不会从鼠标点击焦点中出现?还是有其他方法可以自定义此单选框,以帮助我保留默认行为?

编辑:这里是一个JSFiddle演示我在谈论什么。在第一行上,您可以单击单选按钮,然后使用箭头键导航-只有在使用键盘时轮廓才会出现。在第二行上,单击单选按钮会立即触发焦点样式。

http://jsfiddle.net/7Ltcks3n/1/


1
我正在使用input:focus,但它在处理鼠标点击时与浏览器默认行为不同。 - Andrew K
你提供的CSS中input:focus在哪里? - LcSalazar
我是用“.custom-radio:focus + label:before”完成的。请查看更新后的JSFiddle以获取更简单的示例。 - Andrew K
2
你如何使输入的内容“visuallyhidden”?使用 display:none 吗?或者你是否尝试过使用 position:fixed; top: -99px 来代替呢? - Ilya Streltsyn
你的第二个CSS规则末尾实际上没有],是吗? - Sebastian Simon
我认为你正在寻找:checked伪选择器? - webbist
7个回答

6
我相信这正是你正在寻找的,我的朋友。具备模仿默认浏览器轮廓的功能。您应该能够在您的代码中使用下面的技巧来实现此效果。
以下是演示代码,更多内容请阅读源文章:https://ghinda.net/article/mimic-native-focus-css/
.unreal-focus {
  outline-width: 2px;
  outline-style: solid;
  outline-color: Highlight;
}

/* WebKit gets its native focus styles.
 */
@media (-webkit-min-device-pixel-ratio:0) {
  .unreal-focus {
    outline-color: -webkit-focus-ring-color;
    outline-style: auto;
  }
}

5
问题在于,显然 Blink 浏览器在单选框被点击后仍然保持焦点,但 Firefox 和 Safari 不会这样做。
为了解决这个问题,你可以在 mousedowntouchstart 上向文档添加一个类来隐藏你添加的环形元素,并在 keydown 上将其删除。
工作示例:

var className = 'focus-radio-hide-ring';
var add = function() {
    document.documentElement.classList.add(className);
};
var remove = function() {
    document.documentElement.classList.remove(className);
};
window.addEventListener('mousedown', add, true);
window.addEventListener('touchstart', add, true);
window.addEventListener('keydown', remove, true);
.custom-radio {
 position: absolute;
 opacity: 0;
}
.custom-radio + label {
 cursor: pointer;
}
.custom-radio + label:before {
 content: "";
 display: inline-block;
 vertical-align: middle;
 width: 0.75em;
 height: 0.75em;
 margin-right: 0.25em;
 background: #EEEEEE;
 border: 1px solid #AAAAAA;
 border-radius: 50%;
}
.custom-radio:checked + label:before {
 background: #6666FF;
}

/* Add styles here: */ 
.custom-radio:focus + label:before {
 box-shadow: 0 0 4px 1px rgba(0, 0, 0, 1);
}
/* Add disable them again here: */ 
.focus-radio-hide-ring .custom-radio:focus + label:before {
 box-shadow: none;
}
<p><input placeholder="Tab from here"></p>

<input id="testradio" type="radio" class="custom-radio">
<label for="testradio">Example</label>


2

我长期以来一直面临这个问题,现在我找到了解决方案。

https://jsfiddle.net/hahkarthick/nhorqnvt/3/

input:focus, input:hover{
    outline: 2px auto rgb(229, 151, 0);
    outline-offset: -2px;
 }
<input id="inp" type=radio>radio1
<input type=radio>radio2
<input type=radio>radio3
<input type=radio>radio4
<input type=radio>radio5

input:focus, input:hover{
outline: 2px auto rgb(229, 151, 0);
outline-offset: -2px;

}


这似乎只适用于您所设置的样式,一旦您尝试自定义样式,它就会出现问题。 - jmona789
1
这在我的Windows 10 / Chrome上无法工作。不稳定,不跨浏览器。 - Coastal-Cam
@camiblanch 到目前为止,我已在最新版本64上测试了Chrome并且完美地运行,但我没有在Mac上进行测试。 - Harish Karthick

2
我根据你的原始代码,而不是提供的 fiddle 示例,编写了下面的片段。据我所知,您正在尝试用自己的样式元素(label:before)替换默认的单选按钮。
由于没有指定默认单选按钮如何隐藏,因此我只使用了opacity:0并调整了标签元素的位置来覆盖它。同样的效果可以通过将单选按钮移动到屏幕外来实现:position:absolute; top:-999;left:-999;(或类似的内容)。
我尝试在单选按钮上使用display:nonevisibility:hidden,但这是一个问题,因为当它们不可见时,显然触发不了 focus 动作
我还给label:before元素添加了一些样式,以便它显示出来。
针对您的问题:
.custom-radio:focus + label:before {
  outline: 1px solid black;
  outline: 1px auto -webkit-focus-ring-color;
}

outline:0 1px solid black;” 在标签被点击时会显示一个默认的边框。这在 Firefox 和 IE 中运行良好,但是在 Chrome 中,你需要将颜色更改为“-webkit-focus-ring-color”,因为它使用蓝色来显示单选按钮的轮廓线。

.visuallyhidden {
  opacity: 0;
}
.custom-radio + label {
  position: relative;
  left: -25px;
  margin-right: -15px;
}
.custom-radio + label:before {
  content: "X";
  margin: 5px;
  // Styling goes here
}

.custom-radio:focus + label:before {
  outline: 1px solid black;
  outline: 1px auto -webkit-focus-ring-color;
}
<input type="radio" name="testradio" id="testradio1" class="visuallyhidden custom-radio">
<label for="testradio1">radio 1</label>
<input type="radio" name="testradio" id="testradio2" class="visuallyhidden custom-radio">
<label for="testradio2">radio 2</label>
<input type="radio" name="testradio" id="testradio3" class="visuallyhidden custom-radio">
<label for="testradio3">radio 3</label>


1

我不确定在您的设置中是否可能,但如果有可用的包装器div,则在这种情况下非常方便。

这是我正在使用的HTML:

<div class="hvf__form-item hvf__form-item--radio">
  <input type="radio" id="amount-to-give--25" name="hvf-radios-amount" class="hvf__radio" required value="25">
  <label for="amount-to-give--25">€25</label>
</div>

拥有包装 div,使我能够使用 :focus-within 为每个 radio 元素添加轮廓。

.hvf__form-item--radio:focus-within {
  outline: 2px dashed var(--color-grey--darkest);
  outline-offset: 4px;
}

0

0

您可以通过脚本实现此行为。首先,您需要将keypress事件绑定到单选按钮,并在处理程序中添加轮廓样式,每当单选按钮获得焦点或处于活动状态时(通过向活动输入添加自定义单选按钮类)。这样,您就可以在鼠标单击时省略轮廓样式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接