gpt4 book ai didi

html - 单击并拖动标签时,自定义复选框不会切换

转载 作者:行者123 更新时间:2023-12-05 06:18:15 28 4
gpt4 key购买 nike

我的自定义复选框有问题。

如果您单击一个复选框元素,移动鼠标光标然后在复选框区域内释放单击,则该复选框被选中。

但是,如果您对自定义复选框(此处为标签内的 div)执行相同操作,则不会选中该复选框。

这是一个问题,因为如果你想快速选中一个复选框,你可能会在按下鼠标按钮之后和释放鼠标之前移动鼠标,从而不会切换复选框。

用户有义务点击而不移动鼠标。

我知道我可以使用 JS 来模拟带有 div 的复选框,但我希望 HTML 在语义上是正确的,所以:是否可以在没有 js 的情况下修复它?

代码如下:

/* 1. Hide the checkbox */

.hidden {
/* https://zellwk.com/blog/hide-content-accessibly/ */
border: 0;
clip: rect(0, 0, 0, 0);
height: auto;
margin: 0;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
white-space: nowrap;
}

/* 2. Use a label to retrieve the click event */

label {
/* not used directly to prevent the bug in firefox https://bugzilla.mozilla.org/show_bug.cgi?id=608180 */
pointer-events: none;
display: inline-flex;
}

label > input {
/*usefull for testing only*/
pointer-events : all;
}

label > .customCheckbox {
cursor: pointer;
display: inline-flex;
justify-content: center;
align-items: center;
position: relative;

--size:200px;
width: var(--size);
height: var(--size);
font-size: calc(var(--size)/2);
pointer-events: all;
}

label > .customCheckbox::selection{
/* prevent highliting the text within the custom checkbox */
background: none;
}

label > .customCheckbox:after {

z-index: -1;
content: "✔";
display: inline-flex;
justify-content: center;
align-items: center;

position: absolute;
width: 100%;
height: 100%;

box-sizing: border-box;
border-radius: calc(var(--size)/4);
border: solid black calc(var(--size)/10);
}

label > input:not(:checked) + div.customCheckbox:after {
background:#0000;
content: "\a0";
}
<input type="checkbox"/>   

<label >
<input type="checkbox" class="hidden"/>
<div class="customCheckbox"></div>
</label >

我需要将复选框放在标签内,因为我不能使用“for”属性。

非常感谢您的帮助!

编辑:对于那些想知道的人,这里是 js 解决方案(不理想但因为我不能在 CSS 中做到这一点,总比没有好):

let checkboxes = document.getElementsByClassName("customCheckbox");

for(let i=0; i<checkboxes.length; i++){
checkboxes[i].addEventListener('mouseover', (e)=>{handleMouseOverCheckbox(e)})
checkboxes[i].addEventListener('mousedown', (e)=>{handleMouseOverCheckbox(e)})
}

function handleMouseOverCheckbox(e) {
e.srcElement.previousElementSibling.disabled = "true";
if (e.buttons == 1) {
e.srcElement.previousElementSibling.checked= !e.srcElement.previousElementSibling.checked;
}}

编辑 2:这是我能想到的最佳解决方案,感谢 @zer00ne

codepen.io/DesignThinkerer/pen/bGVBLjM

最佳答案

标签内的复选框没有问题。当为了可访问性而不是使用 display: none 完全删除该复选框而更改该复选框时,就会出现问题。当 DOM 中存在诸如输入或按钮之类的交互式元素时,无论它如何隐藏,它仍然是一个因素,除非应用 display: none

Ooriginal Post 中,复选框几乎不可能被点击,因为它的高度为 0px,宽度为 1px,但是当点击 div 时,复选框被点击... 有时不是。通常,如果标签能够检测到点击,则该点击也会触发嵌套复选框的点击事件。在没有发生的 OP 代码中,因为标签有 pointer-events: none

所以 div 被点击并且通过一些神奇的奇迹这获得了通常不会归因于它的功能? Div 不是交互式的,它们不能影响未嵌套在自身内的元素(即像位于 div 之前的复选框)。不,div 是无用的,它的复选框本身会被点击,因为它是惰性标签中默认获得焦点的唯一元素。在输入上获得焦点并不一定能保证点击事件——事实上,焦点事件选择一个元素,点击事件将元素设置为事件元素。那么当用户在下一次点击清除标签之前双击或快速移动鼠标时会发生什么? OP 中描述的不良行为。

在下面的演示中,复选框根据 OP 隐藏(还将宽度和高度设置为 0)并从标签中删除 pointer-events: none 并将其添加到复选框。在此设置中,标签获得焦点和点击事件,点击事件将触发复选框。由于 pointer-events: nonez-index: -1,复选框已与任何额外的点击隔离开来,应该会按预期运行。

作为概念证明,我添加了一些 JavaScript 来证明上述代码的稳定性。这两个事件处理程序用于演示目的。 JS 不会促进、稳定或修改 HTML/CSS 行为的性能。

  1. 在复选框(通过标签)上发生任何更改事件时,将触发 function changeHandler() 以收集选中复选框的所有值并将它们显示在输出中。

    • 如果复选框中有复选标记,并且显示的值对应于所述选中的复选框,则它作为有效行为成功通过。
  2. 单击 button.show 将触发 function clickHandler() 以将 .reveal 类切换到每个复选框。

    • 在快速点击的同时观察显示的复选框是否被选中,其对应的自定义标签也被选中。另请注意,该值也应显示。

顺便说一句

  • "....target doesn't work in IE IIRC"

    event.target 是每个现代浏览器中使用的标准属性。 event.srcElement 是 IE 使用的弃用属性,几乎完全不受支持。

  • pointer-events: all assigned to input and .customCheckbox

    all 仅适用于 SVG。只有 noneauto 的值与 HTML 相关。 auto 是默认值。


演示

除了 OP 中提供的代码外,我无法重现所描述的行为。如果您可以在我的演示中重现该行为,请录制一段简短的视频并发布该视频以及机器/设备、操作系统和浏览器(我假设一切都是最新的)。

const main = document.forms.main;

main.onchange = checkHandler;

function checkHandler(e) {
const fc = this.elements;
const chx = [...fc.hidden];
const ui = e.target;

if (ui.matches('.hidden')) {
let text = chx.flatMap(c => c.checked ? [c.value] : []);
fc.view.value = '';
fc.view.value = text.join(', ');
}
}

main.onclick = clickHandler

function clickHandler(e) {
const fc = this.elements;
const chx = [...fc.hidden];
const ui = e.target;

if (ui.matches('button.show')) {
chx.forEach(c => c.classList.toggle('reveal'));
}
}
:root,
body {
--size: 10rem;
font: 400 small-caps 2vw/1.5 Times;
width: 100%;
height: 100%;
box-sizing: border-box;
}

*,
*::before,
*::after {
box-sizing: inherit;
font: inherit;
}

.display {
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
align-items: center;
width: max-content;
max-height: min-content;
margin: 10px;
border: calc(var(--size) / 20) solid #000;
border-radius: 24px;
}

.view {
display: inline-block;
min-width: 35ch;
font-size: 1.5rem;
height: 1.5rem;
line-height: 1;
}

.show {
display: inline-block;
width: 12ch;
padding: 1px 3px;
margin: 4px;
border: 2px solid #000;
border-radius: 8px;
background: none;
text-align: center;
font-size: 1.25rem;
cursor: pointer;
}

.mask {
position: relative;
z-index: 2;
display: block;
width: var(--size);
height: var(--size);
padding: 0;
margin: 0 5px;
border: solid black calc(var(--size) / 10);
border-radius: calc(var(--size) / 4);
font-size: calc(var(--size) * 0.8);
background: none;
cursor: pointer;
}

.icon {
position: absolute;
z-index: 1;
top: -1.5rem;
right: 1rem;
display: inline-block;
margin: 0;
padding: 0;
border: 0;
}

.hidden {
position: relative;
z-index: -1;
display: inline-block;
width: 0;
height: 0;
margin: 0;
padding: 0;
border: 0;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
pointer-events: none;
opacity: 0;
}

.reveal {
z-index: 0;
top: -24px;
left: 4px;
width: 1px;
height: 1px;
opacity: 1;
}

.icon::after {
content: attr(data-blank);
}

.hidden:checked+.icon::after {
content: attr(data-check);
}
<!DOCTYPE html>
<html>

<head lang='en'>
<meta charset='utf-8'>
<style></style>
</head>

<body>
<form name='main'>
<fieldset name='display' class='display'>
<output name='view' class='view'></output>
<button name='show' class='show' type='button'>Show</button>
</fieldset>
<fieldset name='display' class='display'>
<label name='mask' class='mask'>
<input name='hidden' class="hidden" type="checkbox" value='Check I'>
<fieldset name='icon' class='icon' data-check='✔' data-blank=' '></fieldset>
</label>


<label name='mask' class='mask'>
<input name='hidden' class="hidden" type="checkbox" value='Check II'>
<fieldset name='icon' class='icon' data-check='✔' data-blank=' '></fieldset>
</label>


<label name='mask' class='mask'>
<input name='hidden' class="hidden" type="checkbox" value='Check III'>
<fieldset name='icon' class='icon' data-check='✔' data-blank=' '></fieldset>
</label>


<label name='mask' class='mask'>
<input name='hidden' class="hidden" type="checkbox" value='Check IV'>
<fieldset name='icon' class='icon' data-check='✔' data-blank=' '></fieldset>
</label>
</fieldset>
</form>

<script></script>
</body>

</html>

关于html - 单击并拖动标签时,自定义复选框不会切换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61305418/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com