如何通过复选框结合多类名实现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();
修复说明
- 收集筛选条件:先获取所有被勾选的复选框对应的筛选类名,避免逐个处理导致的覆盖问题
- 准确类名判断:使用
classList.contains()方法,不管元素有多少类名,都能准确判断是否包含目标类名 - 多条件交集筛选:当勾选多个条件时,仅显示同时满足所有条件的产品卡片(比如同时选Blue和Long,只显示同时有
filt-blue和filt-long类的卡片) - 逻辑简化:无勾选时直接显示全部卡片,逻辑清晰易懂
完整页面代码(保留原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 - £<?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 - £<?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
相关产品推荐
相关产品推荐

