使用复选框之类的图像

IT技术 javascript jquery css html
2021-02-03 10:48:37

我想有一个标准复选框的替代方案 - 基本上我想使用图像,当用户单击图像时,将其淡出并覆盖一个复选框。

本质上,我想做一些像 Recaptcha 2 那样的事情,当它让你点击满足特定条件的图像时。你可以在这里看到一个 Recaptcha 演示,但它有时可能会让你解决文本问题,而不是图像选择。所以这是一个截图:

Google Recaptcha 屏幕截图

当您单击其中一个图像(在本例中,包含牛排图片)时,您单击的图像会缩小尺寸并出现蓝色勾号,表明您已勾选它。

假设我想重现这个确切的例子。

我意识到我可以有 9 个隐藏的复选框,并附加一些 jQuery 以便当我单击图像时,它选择/取消选择隐藏的复选框。但是图像的缩小/覆盖刻度线呢?

6个回答

纯语义 HTML/CSS 解决方案

这很容易自己实现,不需要预先制定的解决方案。此外,它会教你很多东西,因为你对 CSS 似乎不太容易。

这是你需要做的:

您的复选框需要具有不同的id属性。这允许您<label>使用标签的 -for属性将 a 连接到它

例子:

<input type="checkbox" id="myCheckbox1" />
<label for="myCheckbox1"><img src="http://someurl" /></label>

将标签附加到复选框将触发浏览器行为:每当有人单击标签(或其中的图像)时,复选框将被切换。

接下来,您通过应用例如display: none;隐藏复选框

现在剩下要做的就是为label::before伪元素设置所需的样式(将用作可视复选框替换元素):

label::before {
    background-image: url(../path/to/unchecked.png);
}

在最后一个棘手的步骤中,您使用 CSS 的:checked伪选择器在选中复选框时更改图像:

:checked + label::before {
    background-image: url(../path/to/checked.png);
}

+相邻兄弟选择器)可确保您只更改标签直接按照标记隐藏复选框。

您可以通过将两个图像放入 spritemap 并仅应用更改background-position而不是交换图像来优化它

当然,您需要正确display: block;放置标签并应用和设置正确的widthheight

编辑:

我在这些说明之后创建的 codepen 示例和代码段使用相同的技术,但不是使用图像作为复选框,复选框替换完全使用 CSS 完成::before在标签上创建一个,一旦选中,就会有content: "✓";. 添加一些圆形边框和甜美的过渡效果,结果非常讨人喜欢!

这是一个展示该技术的有效代码笔,并且不需要复选框的图像:

http://codepen.io/anon/pen/wadwpx

这是一个片段中的相同代码:

ul {
  list-style-type: none;
}

li {
  display: inline-block;
}

input[type="checkbox"][id^="cb"] {
  display: none;
}

label {
  border: 1px solid #fff;
  padding: 10px;
  display: block;
  position: relative;
  margin: 10px;
  cursor: pointer;
  -webkit-touch-callout: none;
  -webkit-user-select: none;
  -khtml-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

label::before {
  background-color: white;
  color: white;
  content: " ";
  display: block;
  border-radius: 50%;
  border: 1px solid grey;
  position: absolute;
  top: -5px;
  left: -5px;
  width: 25px;
  height: 25px;
  text-align: center;
  line-height: 28px;
  transition-duration: 0.4s;
  transform: scale(0);
}

label img {
  height: 100px;
  width: 100px;
  transition-duration: 0.2s;
  transform-origin: 50% 50%;
}

:checked+label {
  border-color: #ddd;
}

:checked+label::before {
  content: "✓";
  background-color: grey;
  transform: scale(1);
}

:checked+label img {
  transform: scale(0.9);
  box-shadow: 0 0 5px #333;
  z-index: -1;
}
<ul>
  <li><input type="checkbox" id="cb1" />
    <label for="cb1"><img src="https://picsum.photos/seed/1/100" /></label>
  </li>
  <li><input type="checkbox" id="cb2" />
    <label for="cb2"><img src="https://picsum.photos/seed/2/100" /></label>
  </li>
  <li><input type="checkbox" id="cb3" />
    <label for="cb3"><img src="https://picsum.photos/seed/3/100" /></label>
  </li>
  <li><input type="checkbox" id="cb4" />
    <label for="cb4"><img src="https://picsum.photos/seed/4/100" /></label>
  </li>
</ul>

这很好!当您单击同一个标签两次时,我注意到一个小问题,它会选择图像。这修复了它:codepen.io/anon/pen/jPmNjg
2021-03-14 10:48:37
是的,理解它的工作方式会让你在未来思考,每次你想要点击一些 DOM 操作时。你以为你只能对:hover:)做出反应
2021-03-22 10:48:37
Tick 看起来会比 SVG 更好。CSS 内容让您受制于一些糟糕的系统字体。
2021-04-08 10:48:37
这将是我在 Pluralsight 上观看的下一件事情——一些 CSS 的东西:)
2021-04-10 10:48:37
很高兴你喜欢它!开始更多地摆弄 CSS,它很有趣,而且 CSS 可以做的事情比你想象的要多得多(除了垂直居中,这太难了 ;))。
2021-04-11 10:48:37

纯 CSS 解决方案

调用了三个简洁的设备:

  1. :checked选择
  2. ::before伪选择
  3. csscontent属性。

label:before {
  content: url("https://cdn1.iconfinder.com/data/icons/windows8_icons_iconpharm/26/unchecked_checkbox.png");
  position: absolute;
  z-index: 100;
}
:checked+label:before {
  content: url("https://cdn1.iconfinder.com/data/icons/windows8_icons_iconpharm/26/checked_checkbox.png");
}
input[type=checkbox] {
  display: none;
}
/*pure cosmetics:*/
img {
  width: 150px;
  height: 150px;
}
label {
  margin: 10px;
}
<input type="checkbox" id="myCheckbox1" />
<label for="myCheckbox1">
  <img src="https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcR0LkgDZRDTgnDrzhnXGDFRSItAzGCBEWEnkLMdnA_zkIH5Zg6oag">
</label>
<input type="checkbox" id="myCheckbox2" />
<label for="myCheckbox2">
  <img src="https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcRhJjGB3mQxjhI5lfS9SwXou06-2qT_0MjNAr0atu75trXIaR2d">
</label>
<input type="checkbox" id="myCheckbox3" />
<label for="myCheckbox3">
  <img src="https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcQuwWbUXC-lgzQHp-j1iw56PIgl_2eALrEENUP-ld72gq3s8cVo">
</label>

如何向这些复选框添加单选按钮行为?我的意思是当您单击图像时,已选择的图像会被取消选择。
2021-04-02 10:48:37
谁问自己与@Libertad 相同的问题,只需将输入类型更改为收音机,并给它们所有相同的名称“属性”,<input type="radio" name="myRadio" id="myRadio1" />也会更改您的 css 以隐藏项目符号:input[type=radio]{display: none;}
2021-04-10 10:48:37

请参阅此 jQuery 插件:imgCheckbox(在npmbower 上

免责声明:解决此问题不需要 javascript。紧张关系在代码的可维护性和效率之间。虽然不需要插件(或任何 javascript),但它确实可以更快地构建并且通常更容易更改。

准系统解决方案:

使用非常简单的 HTML(没有复选框和标签等的混乱):

<img class="checkable" src="http://lorempixel.com/100/100" />

您可以使用 jQuery 的toggleClass来打开/关闭事件上的selectedcheckedclick

$("img.checkable").click(function () {
    $(this).toggleClass("checked");
});

被检查的项目是用

$(".checked")

加凉:

您可以基于此设置图像样式,但一个大问题是,如果没有其他 DOM 元素,您甚至无法使用::before::after添加诸如复选标记之类的东西。解决方案是用另一个元素包装您的图像(并且将点击侦听器附加到包装元素也是有意义的)。

$("img.checkable").wrap("<span class='fancychecks'>")

这使您的 html 非常干净,并且您的 js 非常可读。看看片段...

使用imgCheckbox jQuery 插件:

受上述解决方案的启发,我构建了一个插件,可以像以下那样轻松使用:

$("img").imgCheckbox();
  • 将检查图像的数据注入您的表单
  • 支持自定义复选标记
  • 支持自定义 CSS
  • 支持预选元素
  • 支持无线电组而不是简单的图像切换
  • 有事件回调
  • 合理的默认值
  • 轻巧且超级易于使用

看到它在行动(并看到源

我尝试使用您的插件,但如果我在初始化后添加更多图像,似乎没有办法销毁前一个实例以便可以包含新图像
2021-03-19 10:48:37
@IanKim 有趣的用例,你能解释更多关于你在 github 上的问题中尝试做的事情吗?github.com/jcuenod/imgCheckbox
2021-03-19 10:48:37
我也喜欢这种方法,但它有许多值得一提的缺点,最大的缺点是:假设用户打算选择图像,那么用户以这种方式提供的信息肯定会以某种方式进行处理,是它通过 AJAX 调用或通过表单提交。为了对用户提供的信息进行进一步处理,在必须反映和处理多个选择的复选框中设置复选框只是一种自然的、语义化的方式。
2021-03-22 10:48:37
这是真的,它在我的插件待办事项列表中 - 劫持表单提交并将数据注入表单。但你是对的,复选框是表单的语义
2021-03-27 10:48:37
这是一个很棒的插件!请发布一个 Webjar =)
2021-04-05 10:48:37

我想追加额外的分度,position: relative;class="checked"具有相同的宽度/高度,该图像具有与比在位置left: 0; top: 0;包含图标。它以 开头display: none;

现在您可以收听click-event:

$( '.captcha_images' ).click( function() {
    $(this + '.checked').css( 'display', 'block' );
    $(this).animate( { width: '70%', height: '70%' } );
});

通过这种方式,您可以获得图标并将图像调整为更小的方式。

注意:只是想向您展示我的想法背后的“逻辑”,此示例可能不起作用或存在一些错误。

你是对的。起初我想指出你的第一个答案并改进它(在编辑之前),因为我喜欢 No-JS 和漂亮的语义方式,但是我读到 OP 想要一些 jQuery 中的东西所以我改变了我的答案。我记得我在哪里得到了反对,因为 OP 不想要一个“更好”或“正确的方式”的解决方案,而是他写的确切方式。也许只是我过度阅读或没有理解某些东西,或者这取决于 OP?
2021-03-24 10:48:37
我展示的技术是如此简单和强大,它甚至经常应用于语义上没有任何复选框的情况,例如切换其他元素的显示等。是用例,它不仅是最简单、最灵活的解决方案,而且在语义上也是最好的。
2021-04-03 10:48:37

我注意到其他答案要么不使用<label>(为什么不使用?),要么需要匹配forid属性。这意味着如果您有冲突的 ID,您的代码将无法工作,您必须记住每次都制作唯一的 ID。

此外,如果您隐藏inputwithdisplay:nonevisibility:hidden,浏览器将不会关注它。

复选框及其文本(或在本例中为图像)可以包含在标签中:

.fancy-checkbox-label > input[type=checkbox] {
  position: absolute;
  opacity: 0;
  cursor: inherit;
}
.fancy-checkbox-label {
  font-weight: normal;
  cursor: pointer;
}
.fancy-checkbox:before {
  font-family: FontAwesome;
  content: "\f00c";
  background: #fff;
  color: transparent;
  border: 3px solid #ddd;
  border-radius: 3px;
  z-index: 1;
}
.fancy-checkbox-label:hover > .fancy-checkbox:before,
input:focus + .fancy-checkbox:before {
  border-color: #bdbdff;
}
.fancy-checkbox-label:hover > input:not(:checked) + .fancy-checkbox:before {
  color: #eee;
}
input:checked + .fancy-checkbox:before {
  color: #fff;
  background: #bdbdff;
  border-color: #bdbdff;
}
.fancy-checkbox-img:before {
  position: absolute;
  margin: 3px;
  line-height: normal;
}
input:checked + .fancy-checkbox-img + img {
  transform: scale(0.9);
  box-shadow: 0 0 5px #bdbdff;
}
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-T8Gy5hrqNKT+hzMclPo118YTQO6cYprQmhrYwIiQ/3axmI1hQomh7Ud2hPOy8SP1" crossorigin="anonymous">
<p>
  <label class="fancy-checkbox-label">
    <input type="checkbox">
    <span class="fancy-checkbox"></span>
    A normal checkbox
  </label>
</p>
<p>
  <label class="fancy-checkbox-label">
    <input type="checkbox">
    <span class="fancy-checkbox fancy-checkbox-img"></span>
    <img src="http://placehold.it/150x150">
  </label>
</p>