单击不同的单选按钮后取消选中单选按钮
Unchecking a radio button after clicking a different one
我正在制作一个带有两个按钮(赞成票/反对票)的投票系统。我使用 input 和 label 标签来创建这个,但是有一个问题:
如果我使用单选按钮,我可以投赞成票或反对票,但不能取消投票。
如果我使用复选框,我可以取消投票,但我也可以投赞成票和反对票。
我想要实现的是能够只投赞成票或反对票,同时也能够取消投票(想想 reddit)。
我彻底寻找了一个答案,但我发现 CSS 无法做到这一点。那里有很多脚本,问题是我不知道 JavaScript 或 jQuery,所以我不知道如何实现代码。
我认为最简单的解决方案是在我点击赞成票时取消选中反对票按钮,反之亦然,但同样,我不知道这段代码会是什么样子或如何实现它。
也许有一个更简单的解决方案,即使用纯 CSS 来更改另一个按钮的外观,即使它已被选中?我不知道,但如果存在这样的解决方案,我宁愿使用它。
我的代码:
input[type=radio] {
display: none
}
#up {
width: 20px;
height: 16px;
background: url(http://c.thumbs.redditmedia.com/Y5Gt7Gtk59BlV-3t.png) left top;
position: absolute;
left: 50px;
top: 50px
}
#down {
width: 20px;
height: 16px;
background: url(http://c.thumbs.redditmedia.com/Y5Gt7Gtk59BlV-3t.png) left bottom;
opacity: 0.5;
position: absolute;
left: 50px;
top: 84px
}
#vote {
width: 21px;
height: 18px;
text-align: center;
font-size: 26px;
line-height: 18px;
position: absolute;
left: 50px;
top: 66px;
z-index: -1
}
#up:hover {
background-position: top;
cursor: pointer
}
#upvote:checked ~ #up {
background-position: top;
}
#upvote:checked ~ #vote {
color: #DC5B28;
z-index: 1
}
#down:hover {
background-position: bottom;
cursor: pointer;
opacity: 1
}
#downvote:checked ~ #down {
background-position: bottom;
opacity: 1
}
#downvote:checked ~ #vote {
color: #3580DD
}
#no {
position: absolute;
display: none;
background: url(http://c.thumbs.redditmedia.com/Y5Gt7Gtk59BlV-3t.png)
}
#upvote:checked ~ #no {
display: block;
background-position: left top;
left: 50px;
top: 50px
}
#downvote:checked ~ #no {
display: block;
background-position: left bottom;
left: 50px;
top: 84px;
opacity: 0.5
}
<input type="radio" name="vote" value="+1" id="upvote">
<label for="upvote" id="up"></label>
<input type="radio" name="vote" value="-1" id="downvote">
<label for="downvote" id="down"></label>
<input type="radio" name="vote" value="0" id="novote">
<label for="novote" id="no"></label>
<div id="vote">•</div>
如果你想要一个CSS-only的解决方案,你可以尝试添加一个默认隐藏的第三个选项,这代表没有投票。
然后,当用户投赞成票或反对票时,会显示第三个选项,它与所选选项重叠。
因此,当用户认为他再次单击所选选项时,他实际上是在选择不投票选项。
#vote {
position: relative;
}
#vote > input {
display: none; /* Hide radio buttons */
}
#vote > label {
cursor: pointer;
display: block;
width: 0;
border: 50px solid; /* We will make them look like... */
border-color: black transparent; /* ...triangles using borders */
}
#upvote + label {
border-top: none; /* Triangulating */
}
#downvote + label {
border-bottom: none; /* Triangulating */
margin-top: 15px; /* Space between triangles */
}
#vote > input:checked + label {
border-color: orange transparent; /* Highlight chosen option */
}
#vote > #novote-label {
display: none; /* Hide it by default */
position: absolute; /* Take it out of the normal flow */
border-top: none;
border-color: transparent;
}
#upvote:checked ~ #novote-label { /* Display it overlapping upvote */
display: block;
top: 0;
}
#downvote:checked ~ #novote-label { /* Display it overlapping downvote */
display: block;
bottom: 0;
}
<div id="vote">
<input type="radio" name="vote" value="+1" id="upvote" />
<label for="upvote"></label>
<input type="radio" name="vote" value="-1" id="downvote" />
<label for="downvote"></label>
<input type="radio" name="vote" value="0" id="novote" />
<label for="novote" id="novote-label"></label>
</div>
只需稍作改动,它也可以通过键盘访问:
#vote {
position: relative;
}
#vote > input { /* Hiding in a keyboard-accesible way */
opacity: 0;
position: absolute;
z-index: -1;
}
#vote > input:focus + label {
outline: 1px dotted #999; /* Keyboard friendly */
}
#vote > label {
cursor: pointer;
display: block;
width: 0;
border: 50px solid; /* We will make them look like... */
border-color: black transparent; /* ...triangles using borders */
}
#upvote + label {
border-top: none; /* Triangulating */
}
#downvote + label {
border-bottom: none; /* Triangulating */
margin-top: 15px; /* Space between triangles */
}
#vote > input:checked + label {
border-color: orange transparent; /* Highlight chosen option */
}
#vote > #novote-label {
display: none; /* Hide it by default */
position: absolute; /* Take it out of the normal flow */
border-top: none;
border-color: transparent;
}
#upvote:checked ~ #novote-label { /* Display it overlapping upvote */
display: block;
top: 0;
}
#downvote:checked ~ #novote-label { /* Display it overlapping downvote */
display: block;
bottom: 0;
}
<div id="vote">
<input type="radio" name="vote" value="+1" id="upvote" />
<label for="upvote"></label>
<input type="radio" name="vote" value="-1" id="downvote" />
<label for="downvote"></label>
<input type="radio" name="vote" value="0" id="novote" />
<label for="novote" id="novote-label"></label>
</div>
上面的代码片段使用边框来模拟 triangles/arrows。同样,也可以使用背景图片。
#vote {
position: relative;
}
#vote > input {
display: none;
}
#vote > label {
cursor: pointer;
display: block;
width: 20px;
height: 16px;
background-image: url('http://i.stack.imgur.com/36F2b.png');
}
#vote > #up {
background-position: left top;
}
#vote > #down {
background-position: left bottom;
}
#upvote:checked ~ #up {
background-position: top;
}
#downvote:checked ~ #down {
background-position: bottom;
}
#vote > #no {
display: none;
position: absolute;
background: none;
}
#upvote:checked ~ #no {
display: block;
top: 0;
}
#downvote:checked ~ #no {
display: block;
bottom: 0;
}
<div id="vote">
<input type="radio" name="vote" value="+1" id="upvote" />
<label for="upvote" id="up"></label>
<input type="radio" name="vote" value="-1" id="downvote" />
<label for="downvote" id="down"></label>
<input type="radio" name="vote" value="0" id="novote" />
<label for="novote" id="no"></label>
</div>
您有一个纯粹的 CSS 解决方案,这里是 javascript 版本。它将点击侦听器放在 "vote" 按钮的祖先上。单击并选中一个按钮时,它会取消选中同一容器中的其他投票按钮,因此一次只选中一个投票。它适用于任意数量的投票按钮(您可能会说 +1、+2 等)。
如果单击复选框取消选中它,例如取消投票时,该函数不执行任何操作。确保脚本放在容器之后,或者使用加载事件。侦听器可以附加到任意数量的容器,只要每个容器仅包含一组按钮即可。
<!-- A container for the vote buttons -->
<div id="voteContainer">
<input type="checkbox" name="vote" value="+1" id="upvote">
<label for="upvote" id="up">Up</label>
<br>
<input type="checkbox" name="vote" value="-1" id="downvote">
<label for="downvote" id="down">Down</label>
</div>
<script>
(function() {
var div = document.getElementById('voteContainer');
if (div) div.onclick = setVote;
// Looks at the state of els
function setVote(event) {
event = event || window.event;
var target = event.target || event.srcElement;
// If target checkbox is checked, uncheck all others
if (target.checked) {
var els = this.querySelectorAll('input[name=' + target.name + ']')
for (var i=0; i<els.length; i++) {
els[i].checked = els[i] === target;
}
}
}
}());
</script>
以上应该适用于所有现代浏览器和 IE 回到 IE 8。如果它需要在旧浏览器中工作,那可以很容易地完成,特别是如果页面中只有一组投票按钮 (它需要对 var els = ...
行进行小的修改。
标签元素不需要 ID 即可运行脚本。
我正在制作一个带有两个按钮(赞成票/反对票)的投票系统。我使用 input 和 label 标签来创建这个,但是有一个问题:
如果我使用单选按钮,我可以投赞成票或反对票,但不能取消投票。
如果我使用复选框,我可以取消投票,但我也可以投赞成票和反对票。
我想要实现的是能够只投赞成票或反对票,同时也能够取消投票(想想 reddit)。
我彻底寻找了一个答案,但我发现 CSS 无法做到这一点。那里有很多脚本,问题是我不知道 JavaScript 或 jQuery,所以我不知道如何实现代码。
我认为最简单的解决方案是在我点击赞成票时取消选中反对票按钮,反之亦然,但同样,我不知道这段代码会是什么样子或如何实现它。
也许有一个更简单的解决方案,即使用纯 CSS 来更改另一个按钮的外观,即使它已被选中?我不知道,但如果存在这样的解决方案,我宁愿使用它。
我的代码:
input[type=radio] {
display: none
}
#up {
width: 20px;
height: 16px;
background: url(http://c.thumbs.redditmedia.com/Y5Gt7Gtk59BlV-3t.png) left top;
position: absolute;
left: 50px;
top: 50px
}
#down {
width: 20px;
height: 16px;
background: url(http://c.thumbs.redditmedia.com/Y5Gt7Gtk59BlV-3t.png) left bottom;
opacity: 0.5;
position: absolute;
left: 50px;
top: 84px
}
#vote {
width: 21px;
height: 18px;
text-align: center;
font-size: 26px;
line-height: 18px;
position: absolute;
left: 50px;
top: 66px;
z-index: -1
}
#up:hover {
background-position: top;
cursor: pointer
}
#upvote:checked ~ #up {
background-position: top;
}
#upvote:checked ~ #vote {
color: #DC5B28;
z-index: 1
}
#down:hover {
background-position: bottom;
cursor: pointer;
opacity: 1
}
#downvote:checked ~ #down {
background-position: bottom;
opacity: 1
}
#downvote:checked ~ #vote {
color: #3580DD
}
#no {
position: absolute;
display: none;
background: url(http://c.thumbs.redditmedia.com/Y5Gt7Gtk59BlV-3t.png)
}
#upvote:checked ~ #no {
display: block;
background-position: left top;
left: 50px;
top: 50px
}
#downvote:checked ~ #no {
display: block;
background-position: left bottom;
left: 50px;
top: 84px;
opacity: 0.5
}
<input type="radio" name="vote" value="+1" id="upvote">
<label for="upvote" id="up"></label>
<input type="radio" name="vote" value="-1" id="downvote">
<label for="downvote" id="down"></label>
<input type="radio" name="vote" value="0" id="novote">
<label for="novote" id="no"></label>
<div id="vote">•</div>
如果你想要一个CSS-only的解决方案,你可以尝试添加一个默认隐藏的第三个选项,这代表没有投票。
然后,当用户投赞成票或反对票时,会显示第三个选项,它与所选选项重叠。
因此,当用户认为他再次单击所选选项时,他实际上是在选择不投票选项。
#vote {
position: relative;
}
#vote > input {
display: none; /* Hide radio buttons */
}
#vote > label {
cursor: pointer;
display: block;
width: 0;
border: 50px solid; /* We will make them look like... */
border-color: black transparent; /* ...triangles using borders */
}
#upvote + label {
border-top: none; /* Triangulating */
}
#downvote + label {
border-bottom: none; /* Triangulating */
margin-top: 15px; /* Space between triangles */
}
#vote > input:checked + label {
border-color: orange transparent; /* Highlight chosen option */
}
#vote > #novote-label {
display: none; /* Hide it by default */
position: absolute; /* Take it out of the normal flow */
border-top: none;
border-color: transparent;
}
#upvote:checked ~ #novote-label { /* Display it overlapping upvote */
display: block;
top: 0;
}
#downvote:checked ~ #novote-label { /* Display it overlapping downvote */
display: block;
bottom: 0;
}
<div id="vote">
<input type="radio" name="vote" value="+1" id="upvote" />
<label for="upvote"></label>
<input type="radio" name="vote" value="-1" id="downvote" />
<label for="downvote"></label>
<input type="radio" name="vote" value="0" id="novote" />
<label for="novote" id="novote-label"></label>
</div>
只需稍作改动,它也可以通过键盘访问:
#vote {
position: relative;
}
#vote > input { /* Hiding in a keyboard-accesible way */
opacity: 0;
position: absolute;
z-index: -1;
}
#vote > input:focus + label {
outline: 1px dotted #999; /* Keyboard friendly */
}
#vote > label {
cursor: pointer;
display: block;
width: 0;
border: 50px solid; /* We will make them look like... */
border-color: black transparent; /* ...triangles using borders */
}
#upvote + label {
border-top: none; /* Triangulating */
}
#downvote + label {
border-bottom: none; /* Triangulating */
margin-top: 15px; /* Space between triangles */
}
#vote > input:checked + label {
border-color: orange transparent; /* Highlight chosen option */
}
#vote > #novote-label {
display: none; /* Hide it by default */
position: absolute; /* Take it out of the normal flow */
border-top: none;
border-color: transparent;
}
#upvote:checked ~ #novote-label { /* Display it overlapping upvote */
display: block;
top: 0;
}
#downvote:checked ~ #novote-label { /* Display it overlapping downvote */
display: block;
bottom: 0;
}
<div id="vote">
<input type="radio" name="vote" value="+1" id="upvote" />
<label for="upvote"></label>
<input type="radio" name="vote" value="-1" id="downvote" />
<label for="downvote"></label>
<input type="radio" name="vote" value="0" id="novote" />
<label for="novote" id="novote-label"></label>
</div>
上面的代码片段使用边框来模拟 triangles/arrows。同样,也可以使用背景图片。
#vote {
position: relative;
}
#vote > input {
display: none;
}
#vote > label {
cursor: pointer;
display: block;
width: 20px;
height: 16px;
background-image: url('http://i.stack.imgur.com/36F2b.png');
}
#vote > #up {
background-position: left top;
}
#vote > #down {
background-position: left bottom;
}
#upvote:checked ~ #up {
background-position: top;
}
#downvote:checked ~ #down {
background-position: bottom;
}
#vote > #no {
display: none;
position: absolute;
background: none;
}
#upvote:checked ~ #no {
display: block;
top: 0;
}
#downvote:checked ~ #no {
display: block;
bottom: 0;
}
<div id="vote">
<input type="radio" name="vote" value="+1" id="upvote" />
<label for="upvote" id="up"></label>
<input type="radio" name="vote" value="-1" id="downvote" />
<label for="downvote" id="down"></label>
<input type="radio" name="vote" value="0" id="novote" />
<label for="novote" id="no"></label>
</div>
您有一个纯粹的 CSS 解决方案,这里是 javascript 版本。它将点击侦听器放在 "vote" 按钮的祖先上。单击并选中一个按钮时,它会取消选中同一容器中的其他投票按钮,因此一次只选中一个投票。它适用于任意数量的投票按钮(您可能会说 +1、+2 等)。
如果单击复选框取消选中它,例如取消投票时,该函数不执行任何操作。确保脚本放在容器之后,或者使用加载事件。侦听器可以附加到任意数量的容器,只要每个容器仅包含一组按钮即可。
<!-- A container for the vote buttons -->
<div id="voteContainer">
<input type="checkbox" name="vote" value="+1" id="upvote">
<label for="upvote" id="up">Up</label>
<br>
<input type="checkbox" name="vote" value="-1" id="downvote">
<label for="downvote" id="down">Down</label>
</div>
<script>
(function() {
var div = document.getElementById('voteContainer');
if (div) div.onclick = setVote;
// Looks at the state of els
function setVote(event) {
event = event || window.event;
var target = event.target || event.srcElement;
// If target checkbox is checked, uncheck all others
if (target.checked) {
var els = this.querySelectorAll('input[name=' + target.name + ']')
for (var i=0; i<els.length; i++) {
els[i].checked = els[i] === target;
}
}
}
}());
</script>
以上应该适用于所有现代浏览器和 IE 回到 IE 8。如果它需要在旧浏览器中工作,那可以很容易地完成,特别是如果页面中只有一组投票按钮 (它需要对 var els = ...
行进行小的修改。
标签元素不需要 ID 即可运行脚本。