在前端开发中,切换开关是常见的交互组件,很多场景下我们希望它能搭配动态变化的SVG图标,同时不想引入JavaScript增加代码负担。本文将教你用纯CSS实现这样的组件,先来看效果参考图:

一、基础HTML结构搭建
首先我们需要构建开关的基础结构,包含一个隐藏的原生复选框作为状态控制源,以及对应的开关容器和内部的SVG图标。结构代码如下:
<div class="toggle-switch">
<input type="checkbox" id="toggle" class="toggle-input">
<label for="toggle" class="toggle-label">
<span class="toggle-icon">
<!-- 太阳图标,开关关闭时显示 -->
<svg class="icon sun-icon" viewBox="0 0 24 24">
<circle cx="12" cy="12" r="5" fill="currentColor"/>
<line x1="12" y1="1" x2="12" y2="3" stroke="currentColor" stroke-width="2"/>
<line x1="12" y1="21" x2="12" y2="23" stroke="currentColor" stroke-width="2"/>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64" stroke="currentColor" stroke-width="2"/>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78" stroke="currentColor" stroke-width="2"/>
<line x1="1" y1="12" x2="3" y2="12" stroke="currentColor" stroke-width="2"/>
<line x1="21" y1="12" x2="23" y2="12" stroke="currentColor" stroke-width="2"/>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36" stroke="currentColor" stroke-width="2"/>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22" stroke="currentColor" stroke-width="2"/>
</svg>
<!-- 月亮图标,开关打开时显示 -->
<svg class="icon moon-icon" viewBox="0 0 24 24">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z" fill="currentColor"/>
</svg>
</span>
</label>
</div>二、核心CSS样式编写
接下来编写样式,核心思路是利用checkbox的选中状态,通过相邻兄弟选择器控制开关样式和图标显示。首先隐藏原生复选框,设置开关的基础外观:
/* 隐藏原生复选框 */
.toggle-input {
display: none;
}
/* 开关容器样式 */
.toggle-label {
display: inline-block;
width: 60px;
height: 30px;
background-color: #ccc;
border-radius: 15px;
position: relative;
cursor: pointer;
transition: background-color 0.3s ease;
}
/* 开关选中时的背景色 */
.toggle-input:checked + .toggle-label {
background-color: #4CAF50;
}
/* 图标容器样式 */
.toggle-icon {
position: absolute;
top: 3px;
left: 3px;
width: 24px;
height: 24px;
transition: transform 0.3s ease;
color: #fff;
}
/* 开关选中时图标位置偏移 */
.toggle-input:checked + .toggle-label .toggle-icon {
transform: translateX(30px);
}
/* 图标通用样式 */
.icon {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
transition: opacity 0.3s ease, transform 0.3s ease;
}
/* 默认隐藏月亮图标 */
.moon-icon {
opacity: 0;
transform: rotate(-90deg);
}
/* 太阳图标默认显示 */
.sun-icon {
opacity: 1;
transform: rotate(0deg);
}
/* 开关选中时切换图标显示 */
.toggle-input:checked + .toggle-label .sun-icon {
opacity: 0;
transform: rotate(90deg);
}
.toggle-input:checked + .toggle-label .moon-icon {
opacity: 1;
transform: rotate(0deg);
}三、效果说明与扩展
完成上述代码后,点击开关就能看到背景色变化,同时太阳和月亮图标会平滑切换,还带有旋转动画效果。这里的核心逻辑是:
- 用
checkbox的:checked伪类作为状态触发源,避免JS依赖 - 通过
opacity和transform属性实现图标的淡入淡出和旋转动态效果 - 所有过渡效果都通过
transition属性控制,保证动画流畅自然
如果需要调整开关大小,只需要修改.toggle-label的宽高,同时对应调整.toggle-icon的偏移量和图标尺寸即可。如果希望更换其他SVG图标,只需要替换对应的svg代码内容,保持图标样式逻辑不变就能正常使用。