来源github,参考链接50 Projects In 50 Days - HTML, CSS & JavaScript
重点:
1、使用flex
布局
2、使用伪元素
3、计算进度条宽度,进行类名操作
实现代码:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Progress Steps</title>
<link rel="stylesheet" href="../css/index.css">
</head>
<body>
<div class="container">
<div class="progress-container">
<div id="progress" class="progress"></div>
<div class="circle active">1</div>
<div class="circle">2</div>
<div class="circle">3</div>
<div class="circle">4</div>
<div class="circle">5</div>
<div class="circle">6</div>
</div>
<button type="button" class="prev disabled">上一步</button>
<button type="button" class="next active">下一步</button>
</div>
</body>
<script src="../js/index.js"></script>
</html>
index.css
*{
margin: 0;
padding: 0;
box-sizing: border-box;
}
:root{
--color--: #dededf;
--color_active--: #2396ef;
--font_color--: #535455;
--default_color--: #fff;
}
body,html{
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
.container{
width: 100%;
text-align: center;
}
.progress-container{
width: 500px;
display: flex;
justify-content: space-between;
position: relative;
margin-bottom: 30px;
}
.progress-container::before{
content: "";
width: 100%;
background-color: var(--color--);
}
.progress-container > .progress,.progress-container::before{
height: 5px;
border-radius: 2px;
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
z-index: -1;
}
.progress-container > .progress{
background-color: var(--color_active--);
transition: all .3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.progress-container > .circle{
display: flex;
justify-content: center;
align-items: center;
border: 4px solid var(--color--);
width: 40px;
height: 40px;
color: var(--font_color--);
border-radius: 50%;
background-color: var(--default_color--);
transition: all .3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.progress-container > .circle.active{
border-color: var(--color_active--);
}
.prev,.next{
outline: none;
border: none;
display: inline-block;
background-color: var(--color--);
padding: 8px 16px;
margin: 0 10px;
border-radius: 5px;
color: var(--font_color--);
transition: all .3s cubic-bezier(0.25, 0.46, 0.45, 0.94);
cursor: pointer;
}
.prev:active,.next:active {
transform: scale(.9);
}
.prev.disabled,.next.disabled {
cursor: not-allowed;
background-color: var(--color--);
color: var(--font_color--);
}
.prev.active,.next.active {
background-color: var(--color_active--);
color: var(--default_color--);
}
index.js
const $ = v => document.querySelector(v);
const $$ = v => document.querySelectorAll(v);
const prevBtn = $(".prev");
const nextBtn = $(".next");
const progress = $("#progress");
const circleElements = $$(".circle");
const min = 0, max = circleElements.length - 1;
let currentActive = 0;
nextBtn.addEventListener("click", () => {
if(nextBtn.classList.contains("disabled")) return;
if(currentActive >= max - 1){
handleClass(nextBtn).addClass("disabled").removeClass("active");
}
if(currentActive <= max - 1){
currentActive++;
}
if(currentActive > 0){
handleClass(prevBtn).addClass("active").removeClass("disabled");
}
update();
});
prevBtn.addEventListener("click", () => {
if(prevBtn.classList.contains("disabled")) return;
if(currentActive <= 1){
handleClass(prevBtn).addClass("disabled").removeClass("active");
}
if(currentActive > 0){
currentActive--;
}
if(currentActive <= max - 1){
handleClass(nextBtn).addClass("active").removeClass("disabled");
}
update();
})
function handleClass(el){
let methods = {
addClass,
removeClass
};
function addClass(c){
el.classList.add(c);
return methods;
};
function removeClass(c){
el.classList.remove(c);
return methods;
}
return methods;
}
function update(){
circleElements.forEach((item, index) => {
if(index <= currentActive){
item.classList.add("active");
}else{
item.classList.remove("active");
}
});
progress.style.width = (100 / max * currentActive).toFixed(4) + "%";
}