如何使用HTML和CSS实现带点击交互的水平时间轴进度条
水平时间轴选中填充效果实现方案
原有代码失效原因
- 错误给
<img>标签加checked属性、使用:checked伪类匹配,checked是表单单选/复选框的专属属性,普通标签不支持该状态,所有相关选择器完全不生效 - 进度条初始宽度写为
width: 2,缺少单位,样式不生效 - 基准线用固定
top:41%定位,进度宽度写死,不同分辨率下会错位 - 选择器层级错误,img标签是li的子元素,无法通过兄弟选择器
~匹配到父级外层的.line元素
修复步骤
1. 调整HTML结构
用隐藏单选框+label关联的方式实现纯CSS点击选中,替换原有ul内的li内容:
<div class="head"> <ul class="nav"> <li class="st st1"> <input type="radio" name="timeline" id="tab1" class="tab-radio" checked> <label for="tab1"> <img src="https://images.unsplash.com/photo-1593085512500-5d55148d6f0d?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8Mnx8Y2FydG9vbnxlbnwwfHwwfHw%3D&auto=format&fit=crop&w=600&q=60" alt=""> <p>Minions</p> </label> </li> <li class="st st2"> <input type="radio" name="timeline" id="tab2" class="tab-radio"> <label for="tab2"> <img src="https://images.unsplash.com/photo-1637858868799-7f26a0640eb6?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MTN8fGNhcnRvb258ZW58MHx8MHx8&auto=format&fit=crop&w=600&q=60" alt=""> <p>Happy</p> </label> </li> <li class="st st3"> <input type="radio" name="timeline" id="tab3" class="tab-radio"> <label for="tab3"> <img src="https://images.unsplash.com/photo-1638803040283-7a5ffd48dad5?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8NDF8fGNhcnRvb258ZW58MHx8MHx8&auto=format&fit=crop&w=600&q=60" alt=""> <p>Cartoon</p> </label> </li> <li class="st st4"> <input type="radio" name="timeline" id="tab4" class="tab-radio"> <label for="tab4"> <img src="https://images.unsplash.com/photo-1637855463319-9acb4e5aa44f?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8NDl8fGNhcnRvb258ZW58MHx8MHx8&auto=format&fit=crop&w=600&q=60" alt=""> <p>Cat</p> </label> </li> <li class="st st5"> <input type="radio" name="timeline" id="tab5" class="tab-radio"> <label for="tab5"> <img src="https://images.unsplash.com/photo-1578632767115-351597cf2477?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxzZWFyY2h8Mnx8YW5pbWV8ZW58MHx8MHx8&auto=format&fit=crop&w=600&q=60" alt=""> <p>anime</p> </label> </li> </ul> <div class="line"> <span class="progress"></span> </div> </div>
2. 替换原有无效CSS
删除之前所有:checked相关的错误样式,替换为以下代码:
/* 隐藏默认单选框样式 */ .tab-radio { display: none; } /* label占满整个导航项区域,点击即可触发选中 */ .nav li label { display: block; width: 100%; cursor: pointer; } /* 修正导航父元素定位 */ .head { position: relative; } /* 修正基准线定位,自动对齐圆形按钮 */ .line{ width: 80%; margin: auto; background: #eee; height: 7px; position: absolute; left: 10%; top: 122px; z-index: 1; border-radius: 50px; } /* 修正进度条初始样式,添加单位 */ .line .progress { width: 10%; height: 100%; background: #282d35; position: absolute; left: 0; top: 0; z-index: 2; border-radius: 50px; transition: all .8s ease; } /* 圆形按钮层级高于进度线 */ ul.nav li::after{ content: ''; display: block; width: 7px; height: 7px; background: #777; border-radius: 50%; margin: auto; border: 7px solid #fff; margin-top: 40px; box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, .2); position: relative; z-index: 3; transition: all .3s ease; } /* 选中状态下圆形按钮、文字变色 */ ul.nav li:has(.tab-radio:checked)::after{ background: blue; } ul.nav li:has(.tab-radio:checked) p{ color: #444; } /* 不同选项选中时,进度条填充到对应位置 */ #tab1:checked ~ .line .progress {width: 10%;} #tab2:checked ~ .line .progress {width: 32%;} #tab3:checked ~ .line .progress {width: 53%;} #tab4:checked ~ .line .progress {width: 75%;} #tab5:checked ~ .line .progress {width: 96%;}
兼容旧浏览器方案
如果需要兼容不支持:has()选择器的浏览器,加少量JS即可实现:
const navItems = document.querySelectorAll('.nav li') const progress = document.querySelector('.line .progress') const widthList = ['10%', '32%', '53%', '75%', '96%'] navItems.forEach((item, index) => { item.addEventListener('click', () => { navItems.forEach(i => i.classList.remove('active')) item.classList.add('active') progress.style.width = widthList[index] }) })
对应把CSS里:has()相关的选中样式改成.active类选择器即可。
内容的提问来源于stack exchange,提问作者Android Army
相关产品推荐
相关产品推荐

