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

不使用JavaScript如何实现元素的显示与隐藏?

问题背景

我在开发应用时,最初通过DOMTokenList的add()、remove()方法切换类名,控制元素显示隐藏。随着功能叠加,这类重复代码越来越多,初始写法的示例如下:

button.addEventListener("click", () => {
   elem1.classList.add("display-none");
   elem2.classList.remove("display-none");
   elem3.classList.remove("display-none");
   elem4.classList.add("display-none");
});

button2.addEventListener("click", () => {
   elem1.classList.remove("display-none");
   elem2.classList.add("display-none");
   elem3.classList.add("display-none");
   elem4.classList.remove("display-none");
});

我一共有7段逻辑和上述示例高度相似的代码,因此开始探索更简洁的实现方案,首先尝试了纯CSS写法,代码如下:

.box {
    --displayRed: block;
    --displayGreen: none;
    --displayBlue: none;
    height: 100px;
    width: 100px;
}

.box--red { 
    display: var(--displayRed);
    background-color: #ff0000;
}

.box--green { 
    display: var(--displayGreen);
    background-color: #00ff00;
}

.box--blue { 
    display: var(--displayBlue);
    background-color: #0000ff;
}

.box--red:target {
  --displayRed: block;
  --displayGreen: none;
  --displayBlue: none;
}

.box--green:target {
  --displayRed: none;
  --displayGreen: block;
  --displayBlue: none;
}

.box--blue:target {
  --displayRed: none;
  --displayGreen: none;
  --displayBlue: block;
}
<div>
    <div class="box">
        <div id="boxRed" class="box box--red"></div>
        <div id="boxGreen" class="box box--green"></div>
        <div id="boxBlue" class="box box--blue"></div>
    </div>
    
    <nav>
      <ul>
        <li><a href="#boxRed">显示红色方块</a></li>
        <li><a href="#boxGreen">显示绿色方块</a></li>
        <li><a href="#boxBlue">显示蓝色方块</a></li>
      </ul>
    </nav>
</div>
问题描述

我原本预期点击对应颜色方块的跳转链接时,当前显示的方块会自动隐藏,仅展示链接对应颜色的方块。但实际测试时,点击链接只会触发页面滚动,原本显示的红色方块不会自动隐藏。
我查阅了CSS伪类、选择器的官方文档,找了相关教程,也参考了社区里纯CSS实现元素显隐的相关问答,始终没找到可行的实现方案,欢迎提供有效的实现思路。


解决方案

你的纯CSS:target方案不生效的核心原因是CSS变量存在作用域限制:在.box--red:target选择器下修改的CSS变量,只会作用在被锚点命中的红色方块自身和它的子元素,无法影响同级的绿色、蓝色方块,因此其他方块的display属性始终取初始值,不会自动隐藏。

下面提供两类可直接落地的实现方案,按需选择即可:

方案1:纯CSS实现(无JavaScript)

(1):target 简化版(适配现代浏览器)

不需要借助CSS变量,直接通过:target伪类匹配当前命中的方块控制显隐,配合:has()伪类实现默认展示逻辑,代码量极小:

.box {
  height: 100px;
  width: 100px;
  /* 默认所有方块隐藏 */
  display: none;
}
.box--red { background-color: #ff0000; }
.box--green { background-color: #00ff00; }
.box--blue { background-color: #0000ff; }

/* 锚点命中的方块显示 */
.box:target {
  display: block;
}
/* 无任何锚点命中时,默认显示红色方块 */
.box-container:not(:has(:target)) .box--red {
  display: block;
}

对应HTML只需要给方块的父容器加一个box-container类即可,原有导航链接不需要修改。

(2)单选框方案(兼容老旧浏览器)

如果需要兼容不支持:has()的浏览器,可以用单选框+<label>的经典纯CSS Tab实现,兼容性覆盖到IE9及以上:

/* 隐藏原生单选框 */
.color-tab {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.box {
  height: 100px;
  width: 100px;
  display: none;
}
.box--red { background-color: #ff0000; }
.box--green { background-color: #00ff00; }
.box--blue { background-color: #0000ff; }

/* 单选框选中时,对应颜色的方块显示 */
#tabRed:checked ~ .box-container .box--red,
#tabGreen:checked ~ .box-container .box--green,
#tabBlue:checked ~ .box-container .box--blue {
  display: block;
}

对应HTML调整如下:

<div>
  <!-- 单选框组,默认选中红色 -->
  <input type="radio" name="colorTab" id="tabRed" class="color-tab" checked>
  <input type="radio" name="colorTab" id="tabGreen" class="color-tab">
  <input type="radio" name="colorTab" id="tabBlue" class="color-tab">

  <div class="box-container">
      <div class="box box--red"></div>
      <div class="box box--green"></div>
      <div class="box box--blue"></div>
  </div>
  
  <nav>
    <ul>
      <li><label for="tabRed">显示红色方块</label></li>
      <li><label for="tabGreen">显示绿色方块</label></li>
      <li><label for="tabBlue">显示蓝色方块</label></li>
    </ul>
  </nav>
</div>

方案2:极简JavaScript实现(适配多组切换场景)

你之前的JS代码冗余是因为逐元素、逐按钮写了重复的类名切换逻辑,只要做一层统一封装,不管有多少组显隐切换,核心JS代码只需要写一次:

  1. 给所有触发按钮加data-target属性,标记要显示的分组名
  2. 给所有需要切换显隐的元素加data-group属性,标记所属分组
    示例代码:
// 统一绑定所有切换按钮的事件,不需要逐个写监听
document.querySelectorAll('[data-toggle-target]').forEach(trigger => {
  trigger.addEventListener('click', () => {
    const currentGroup = trigger.dataset.toggleTarget;
    // 遍历所有待切换元素,属于当前分组的显示,否则隐藏
    document.querySelectorAll('[data-toggle-group]').forEach(elem => {
      elem.classList.toggle('display-none', elem.dataset.toggleGroup !== currentGroup);
    })
  })
})

后续新增切换分组时,只需要给对应按钮和元素加数据属性即可,不需要修改JS逻辑,比你原来逐行写add/remove的维护成本低很多。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 22:24:16