0

0

css改变单选框颜色的方法实现(附代码)

不言

不言

发布时间:2018-10-12 16:58:28

|

10605人浏览过

|

来源于segmentfault思否

转载

本篇文章给大家带来的内容是关于css改变单选框颜色的方法实现(附代码),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

是否曾经被业务提出"能改改这个单选框的颜色吧!让它和主题颜色搭配一下吧!",然后苦于原生不支持换颜色,最后被迫自己手撸一个凑合使用。若抛开input[type=radio]重新开发一个,发现要模拟选中、未选中、不可用等状态很繁琐,而涉及单选框组就更烦人了,其实我们可以通过label、::before、:checked和tabindex,然后外加少量JavaScript脚本就能很好地模拟出一个样式更丰富的“原生”单选框。下面我们一起来尝试吧!

单选框了解一下

由于我们的目标是改变单选框颜色,其他外观特征和行为与原来的单选框一致,那么我们就必须先了解单选框原来的外观特征和行为主要有哪些。
1.外观特征
1.1.常态样式

margin: 3px 3px 0px 5px;
border: none 0;
padding: 0;
box-sizing: border-box;
display: inline-block;
line-height: normal;
position: static;

注意:外观上我们必须要保证布局特性和原生的一致,否则采用自定义单选框替换后很大机会会影响整体的布局,最后导致被迫调整其他元素的布局特性来达到整体的协调,从而扩大了修改范围。

立即学习前端免费学习笔记(深入)”;

1.2.获得焦点的样式

outline-offset: 0px;
outline: -webkit-focu-ring-color auto 5px;

注意:这里的获取焦点的样式仅通过键盘Tab键才生效,若通过鼠标点击虽然单选框已获得焦点,但上述样式并不会生效。

1.3.设置为disabled的样式

color: rgb(84, 84, 84);

2.行为特征
 单选框的行为特征,明显就是选中与否,及选中状态的改变事件,因此我们必须保持对外提供change事件。
 另外值得注意的是,当通过键盘的Tab键让单选框获得焦点后,再按下Space键则会选中该单选框。

 有了上述的了解,我们可以开始着手撸代码了!

少废话,撸代码

435275490-5bb54e2fc18b1_articlex.png

上图中左侧就是原生单选框,右侧为我们自定义的单选框。从上到下依次为未选中选中获得焦点disabled状态的样式。

CSS部分

HeroPack
HeroPack

以电子游戏为灵感,用AI制作游戏化身。

下载
label.radio {
  /* 保证布局特性保持一致 */
  margin: 3px 3px 0px 5px;
  display: inline-block;
  box-sizing: border-box;

  width: 12px;
  height: 12px;
}

.radio__appearance{
  display: block; /* 设置为block则不受vertical-align影响,从而不会意外影响到.radio的linebox高度 */
  position: relative;
  box-shadow: 0 0 0 1px tomato; /* box-shadow不像border那样会影响盒子的框高 */
  border-radius: 50%;
  height: 90%;
  width: 90%;
  text-align: center;
}
label.radio [type=radio] + .radio__appearance::before{
  content: "";
  display: block;
  border-radius: 50%;
  width: 85%;
  height: 85%;

  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);

  transition: background .3s;
}
label.radio [type=radio]:checked + .radio__appearance::before{
  background: tomato;
}
label.radio [type=radio][disabled] + .radio__appearance{
  opacity: .5;
}
label.radio:focus{
  outline-offset: 0px;
  outline: #999 auto 5px;
}
/* 通过鼠标单击获得焦点时,outline效果不生效 */
label.radio.clicked{
  outline: none 0;
}
/* 自定义单选框的行为主要是基于原生单选框的,因此先将原生单选框隐藏 */
label.radio input {
  display: none;
}

HTML部分

<!-- 未选中状态 -->
<label class="radio" tabindex="0">
  <input type="radio" name="a">
  <i class="radio__appearance"></i>
</label>

<br>

<!-- 选中状态 -->
<label class="radio" tabindex="0">
  <input type="radio" name="a" checked>
  <i class="radio__appearance"></i>
</label>

<br>

<!-- disabled状态 -->
<label class="radio">
  <input type="radio" name="a" disabled>
  <i class="radio__appearance"></i>
</label>

JavaScript部分

var radios = document.querySelectorAll(".radio")
radios.forEach(radio => {
  // 模拟鼠标点击后:focus样式无效
  radio.addEventListener("mousedown", e => {
    var tar = e.currentTarget
    tar.classList.add("clicked")
    var fp = setInterval(function(){
      if (document.activeElement != tar){
        tar.classList.remove("clicked")
        clearInterval(fp)
      }
    }, 400)
  })
  // 模拟通过键盘获得焦点后,按`Space`键执行选中操作
  radio.addEventListener("keydown", e => {
    if (e.keyCode === 32){
      e.target.click()
    }
  })
})

这个实现有3个注意点:

1、通过label传递鼠标点击事件到关联的input[type=radio],因此可以安心隐藏单选框又可以利用单选框自身特性。但由于label控件自身的限制,如默认不是可获得焦点元素,因此无法传递键盘按键事件到单选框,即使添加tabindex特性也需手写JS来实现;

2、当tabindex大于等于0时表示该元素可以获得焦点,为0时表示根据元素所在位置安排获得焦点的顺序,而大于0则表示越小越先获得焦点;

3、由于单选框的display为inline-block,因此单选框将影响line box高度。当自定义单选框内元素采用inline-block时,若vertical-align设置稍有不慎就会导致内部元素所在的line box被撑高,从而导致自定义单选框所在的line box高度变大。因此这里采用将内部元素的display均设置为block的做法,直接让vertical-align失效,提高可控性。

通过opacity:0实现

 上面我们通过label关联display:none的input[type=radio]从而利用input[type=radio]简化自定义单选框的实现,但依然要手写JS实现按Space键选中的行为特征,有没有另一种方式可以更省事呢?我们只是想让用户看不到原生单选框,那么直接设置为opacity:0不就可以了吗?!

CSS部分

.radio {
  /* 保证布局特性保持一致 */
  margin: 3px 3px 0px 5px;
  display: inline-block;
  box-sizing: border-box;

  width: 13px;
  height: 13px;
}
/* 自定义单选框的行为主要是基于原生单选框的,因此先将原生单选框透明,且沾满整个父元素 */
.radio input {
  opacity: 0;
  position: absolute;
  z-index: 1; /* 必须覆盖在.radio__appearance上才能响应鼠标事件 */
  width: 100%;
  height: 100%;
}
.radio__container-box{
  position: relative;
  width: 100%;
  height: 100%;
}
.radio__appearance{
  display: block; /* 设置为block则不受vertical-align影响,从而不会意外影响到.radio的linebox高度 */
  position: relative;
  box-shadow: 0 0 0 1px tomato; /* box-shadow不像border那样会影响盒子的框高 */
  border-radius: 50%;
  height: 90%;
  width: 90%;
  text-align: center;
}
.radio [type=radio] + .radio__appearance::before{
  content: "";
  display: block;
  border-radius: 50%;
  width: 85%;
  height: 85%;

  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);

  transition: background .3s;
}
.radio [type=radio]:checked + .radio__appearance::before{
  background: tomato;
}
.radio [type=radio][disabled] + .radio__appearance{
  opacity: .5;
}
.radio:focus-within .radio__appearance{
  outline-offset: 0px;
  outline: #999 auto 5px;
}
/* 通过鼠标单击获得焦点时,outline效果不生效 */
.radio.clicked .radio_appearance{
  outline: none 0;
}

HTML部分

<!-- 未选中状态 -->
<span class="radio">
  <span class="radio__container-box">
    <input type="radio" name="a">
    <i class="radio__appearance"></i>
  </span>
</span>

<br>

<!-- 选中状态 -->
<span class="radio">
  <span class="radio__container-box">
    <input type="radio" name="a" checked>
    <i class="radio__appearance"></i>
  </span>
</span>

<br>

<!-- disabled状态 -->
<span class="radio">
  <span class="radio__container-box">
    <input type="radio" name="a" disabled>
    <i class="radio__appearance"></i>
  </span>
</span>

JavaScript部分

var radios = document.querySelectorAll(".radio")
radios.forEach(radio => {
  // 模拟鼠标点击后:focus样式无效
  radio.addEventListener("mousedown", e => {
    var tar = e.currentTarget
    tar.classList.add("clicked")
    var fp = setInterval(function(){
      if (!tar.contains(document.activeElement){
        tar.classList.remove("clicked")
        clearInterval(fp)
      }
    }, 400)
  })
})

总结

对于复选框我们可以稍加修改就可以了,然后通过VUE、React等框架稍微封装一下提供更简约的API,使用起来就更方便了。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Golang 测试体系与代码质量保障:工程级可靠性建设
Golang 测试体系与代码质量保障:工程级可靠性建设

Go语言测试体系与代码质量保障聚焦于构建工程级可靠性系统。本专题深入解析Go的测试工具链(如go test)、单元测试、集成测试及端到端测试实践,结合代码覆盖率分析、静态代码扫描(如go vet)和动态分析工具,建立全链路质量监控机制。通过自动化测试框架、持续集成(CI)流水线配置及代码审查规范,实现测试用例管理、缺陷追踪与质量门禁控制,确保代码健壮性与可维护性,为高可靠性工程系统提供质量保障。

6

2026.02.28

Golang 工程化架构设计:可维护与可演进系统构建
Golang 工程化架构设计:可维护与可演进系统构建

Go语言工程化架构设计专注于构建高可维护性、可演进的企业级系统。本专题深入探讨Go项目的目录结构设计、模块划分、依赖管理等核心架构原则,涵盖微服务架构、领域驱动设计(DDD)在Go中的实践应用。通过实战案例解析接口抽象、错误处理、配置管理、日志监控等关键工程化技术,帮助开发者掌握构建稳定、可扩展Go应用的最佳实践方法。

6

2026.02.28

Golang 性能分析与运行时机制:构建高性能程序
Golang 性能分析与运行时机制:构建高性能程序

Go语言以其高效的并发模型和优异的性能表现广泛应用于高并发、高性能场景。其运行时机制包括 Goroutine 调度、内存管理、垃圾回收等方面,深入理解这些机制有助于编写更高效稳定的程序。本专题将系统讲解 Golang 的性能分析工具使用、常见性能瓶颈定位及优化策略,并结合实际案例剖析 Go 程序的运行时行为,帮助开发者掌握构建高性能应用的关键技能。

8

2026.02.28

Golang 并发编程模型与工程实践:从语言特性到系统性能
Golang 并发编程模型与工程实践:从语言特性到系统性能

本专题系统讲解 Golang 并发编程模型,从语言级特性出发,深入理解 goroutine、channel 与调度机制。结合工程实践,分析并发设计模式、性能瓶颈与资源控制策略,帮助将并发能力有效转化为稳定、可扩展的系统性能优势。

14

2026.02.27

Golang 高级特性与最佳实践:提升代码艺术
Golang 高级特性与最佳实践:提升代码艺术

本专题深入剖析 Golang 的高级特性与工程级最佳实践,涵盖并发模型、内存管理、接口设计与错误处理策略。通过真实场景与代码对比,引导从“可运行”走向“高质量”,帮助构建高性能、可扩展、易维护的优雅 Go 代码体系。

17

2026.02.27

Golang 测试与调试专题:确保代码可靠性
Golang 测试与调试专题:确保代码可靠性

本专题聚焦 Golang 的测试与调试体系,系统讲解单元测试、表驱动测试、基准测试与覆盖率分析方法,并深入剖析调试工具与常见问题定位思路。通过实践示例,引导建立可验证、可回归的工程习惯,从而持续提升代码可靠性与可维护性。

2

2026.02.27

漫蛙app官网链接入口
漫蛙app官网链接入口

漫蛙App官网提供多条稳定入口,包括 https://manwa.me、https

130

2026.02.27

deepseek在线提问
deepseek在线提问

本合集汇总了DeepSeek在线提问技巧与免登录使用入口,助你快速上手AI对话、写作、分析等功能。阅读专题下面的文章了解更多详细内容。

8

2026.02.27

AO3官网直接进入
AO3官网直接进入

AO3官网最新入口合集,汇总2026年可用官方及镜像链接,助你快速稳定访问Archive of Our Own平台。阅读专题下面的文章了解更多详细内容。

208

2026.02.27

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Sass 教程
Sass 教程

共14课时 | 0.9万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.5万人学习

CSS教程
CSS教程

共754课时 | 37.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号