You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过复选框结合多类名实现Div元素筛选

多类名产品复选框筛选功能修复

问题场景

页面通过foreach从数据库拉取产品并生成卡片,使用类名实现复选框筛选。当前问题:勾选「Blue」等复选框时无结果,原JS仅匹配仅含单个筛选类名的元素,无法识别包含目标类名但同时有其他类名的产品卡片。

原代码核心问题

原JS逻辑错误:遍历复选框时逐个设置元素显示状态,导致后续复选框的设置覆盖前面的筛选结果;且未正确处理多条件交集筛选,也没有准确判断元素是否包含目标类名。

修复后的JavaScript代码

function change() {
  // 获取所有复选框输入元素
  const checkboxInputs = Array.from(document.querySelectorAll('.checkbox input'));
  // 收集所有被勾选的筛选类名
  const checkedFilters = checkboxInputs
    .filter(input => input.checked)
    .map(input => input.getAttribute('rel'));

  // 获取所有产品卡片
  const allCards = document.querySelectorAll('.card');

  if (checkedFilters.length === 0) {
    // 无勾选时显示所有卡片
    allCards.forEach(card => card.style.display = 'block');
  } else {
    // 检查每个卡片是否包含所有勾选的筛选类名
    allCards.forEach(card => {
      const meetsAllFilters = checkedFilters.every(filter => card.classList.contains(filter));
      card.style.display = meetsAllFilters ? 'block' : 'none';
    });
  }
}
// 页面加载时初始化筛选状态
change();

修复说明

  1. 收集筛选条件:先获取所有被勾选的复选框对应的筛选类名,避免逐个处理导致的覆盖问题
  2. 准确类名判断:使用classList.contains()方法,不管元素有多少类名,都能准确判断是否包含目标类名
  3. 多条件交集筛选:当勾选多个条件时,仅显示同时满足所有条件的产品卡片(比如同时选Blue和Long,只显示同时有filt-blue和filt-long类的卡片)
  4. 逻辑简化:无勾选时直接显示全部卡片,逻辑清晰易懂

完整页面代码(保留原HTML/CSS)

HTML

<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous" id="bootstrap-css">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.0/css/all.css" integrity="sha384-lZN37f5QGtY3VHgisS14W3ExzMWZxybE1SJSEsQp9S+oqd12jhcu+A56Ebc1zFSJ" crossorigin="anonymous">

<div class="filter">
  <div class="checkbox">
    <label class="checkbox-button">
      <input type="checkbox" class="checkbox-button__input" id="choice1-1" name="choice1" onchange="change()" rel="filt-blue">
      <span class="checkbox-button__control"></span>
    </label>
    <span><b>blue</b></span>
  </div>
</div>
<div class="filter">
  <div class="checkbox">
    <label class="checkbox-button">
      <input type="checkbox" class="checkbox-button__input" id="choice1-2" name="choice1" onchange="change()" rel="filt-red">
      <span class="checkbox-button__control"></span>
    </label>
    <span><b>red</b></span>
  </div>
</div>

<hr>

<div class="filter">
  <div class="checkbox">
    <label class="checkbox-button">
      <input type="checkbox" class="checkbox-button__input" id="choice1-1a" name="choice2" onchange="change()" rel="filt-long">
      <span class="checkbox-button__control"></span>
    </label>
    <span><b>long</b></span>
  </div>
</div>
<div class="filter">
  <div class="checkbox">
    <label class="checkbox-button">
      <input type="checkbox" class="checkbox-button__input" id="choice1-2a" name="choice2" onchange="change()" rel="filt-short">
      <span class="checkbox-button__control"></span>
    </label>
    <span><b>short</b></span>
  </div>
</div>

<div class="cards">
  <div class="card filt-blue filt-long">
    <h6 class="card-title"><b><?php echo $fetch['title'];?></b></h6>
    <center><img src="/images/products/<?php echo $fetch['Img'];?>" class="card-img-top" style="width:160px;margin:0 auto;"></center>
    <div class="card-body">
      <small><?php echo $fetch['detail'];?></small>
      <h6><b>Starting from - &pound;<?php echo $fetch['SFprice'];?></b></h6>
    </div>
  </div>

  <div class="card filt-blue filt-short">
    <h6 class="card-title"><b><?php echo $fetch['title'];?></b></h6>
    <center><img src="/images/products/<?php echo $fetch['Img'];?>" class="card-img-top" style="width:160px;margin:0 auto;"></center>
    <div class="card-body">
      <small><?php echo $fetch['detail'];?></small>
      <h6><b>Starting from - &pound;<?php echo $fetch['SFprice'];?></b></h6>
    </div>
  </div>
</div>

<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>

CSS

@media(max-width:768px){
   .card{
    width:100% !important;
    margin:12px 6px !important;
    }
  }
  .card {
  text-align:left;
  border-radius:4px;
  margin:24px;
  width:320px;
  min-height:340px;
  transition: all 0.2s;
  border:var(--image-select-border);
}
.cards {
  display: flex;
  flex-wrap: wrap;
  justify-content:center;
}
.card-body {
  flex: 1 1 auto;
  padding:12px;
}
.card-title {
  margin-bottom:16px;
  padding:12px;
}
@media(max-width:768px){
.card-img-top{
  width:240px !important;
}
}
@media(max-width:768px){
.filtbtn{
  width:90% !important;
  margin-left:5% !important;
  float:none !important;
}
}
.filterDiv {
  display: none;
}
.show {
  display: block;
}
@media(max-width:768px){
#opts{
  margin-left:5% !important;
}
}
.optsel{
  border-bottom:2px solid #0d6efd;
  border-top: none;
  border-left: none;
  border-right: none;
}
.sidebar {
  height:100%;
  width:0;
  position:fixed;
  z-index:1;
  top:76px;
  right:0;
  background-color:#111;
  overflow-x:hidden;
  transition: 0.5s;
  padding-top: 60px;
}
.sidebar a {
  padding:8px 12px;
  text-decoration: none;
  font-size:16px;
  color: #818181;
  display: block;
  transition: 0.3s;
}
.sidebar .closebtn {
  position: absolute;
  top: 0;
  margin-right:12px;
  font-size:18px;
  color:#222 !important;
  background-color:#fff;
  width:100%;
}
@media(max-width:768px){
  .closebtn{
    top:4px !important;
  }
}
.openbtn {
  font-size: 20px;
  cursor: pointer;
  background-color: #111;
  color: white;
  padding: 10px 15px;
  border: none;
}
.openbtn:hover {
  background-color: #444;
}
#main {
  transition: margin-right .5s; /* If you want a transition effect */
  padding: 20px;
}
/* On smaller screens, where height is less than 450px, change the style of the sidenav (less padding and a smaller font size) */
@media screen and (max-height: 450px) {
  .sidebar {padding-top: 15px;}
  .sidebar a {font-size: 22px;}
}
.optbtn{
  background-color:#fff;
  color: #222;
  cursor: pointer;
  padding:14px;
  width: 100%;
  border: none;
  text-align: left;
  outline: none;
  font-size: 16px;
  transition: 0.4s;
}
.accordion {
  background-color:#111;
  color: #fff !important;
  cursor: pointer;
  padding: 18px;
  width: 100%;
  border: none;
  text-align: left;
  outline: none;
  font-size: 15px;
  transition: 0.4s;
}
.notaccordion {
  background-color:#111;
  color: #fff !important;
  cursor: pointer;
  padding: 18px;
  width: 100%;
  border: none;
  text-align: center;
  outline: none;
  font-size:18px;
  transition: 0.4s;
  font-weight:bolder;
}
.active, .accordion:hover {
  opacity:0.9;
}
.accordion:after {
  content: '\002B';
  color: #777;
  font-weight: bold;
  float: right;
  margin-left: 5px;
}
.active:after {
  content: "\2212";
}
.filterpanel {
  padding:0 18px;
  background-color:#fff;
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.2s ease-out;
}
.checkbox{
  color:#222 !important;
  padding:12px 12px;
}
.checkbox-button {
  cursor: pointer;
}
.checkbox span{
  margin-left:12px;
}
.checkbox input[type=checkbox] {
    box-sizing: border-box;
    padding: 0;
}
.checkbox input {
    font-size: 1rem;
    line-height: 1.5;
    padding: 11px 23px;
    border: 1px solid black;
    border-radius: 0;
    outline: 0;
    background-color: transparent;
}
.checkbox-button__input {
    opacity: 0;
    position: absolute;
}
.checkbox-button__control {
    position: relative;
    display: inline-block;
    width: 20px;
    height: 20px;
    vertical-align: middle;
    background-color: inherit;
    color: #017b5f;
    border: 2px solid #666;
}
.checkbox-button__input:checked+.checkbox-button__control:after {
    content: "";
    display: block;
    position: absolute;
    top: 2px;
    left: 2px;
    width: 12px;
    height: 12px;
    background-color:#0d6efd;
}
.checkbox-button__input:checked+.checkbox-button__control {
    border-color:black;
    border:2px solid black;
}

内容的提问来源于stack exchange,提问作者DaTZcodie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 22:30:50