实现一个Tab栏
1. 效果(移动端展示,PC端屏幕太宽,tab item数量少滚动不起来)
- 默认选中第一个
- 点击话费直充,被激活的item会自动居中
2. 原理
- 这里我没有使用a标签加 href="#xxid"这种形式,因为浏览器地址会带上hash
- 我使用了scrollIntoView,但是默认元素滚动到视口后,是贴边的,而且左右滚动的话,默认是向左滚动
- 所以我又使用了scroll-margin来指定滚动后距离边界的margin
- 注意这个scroll-margin需要计算一下,如果每个tab item的宽度是不同的话,宽度固定的话,写死就好了
3. 代码
<!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>Scroll Demo</title>
<style>
* {
margin: 0;
padding: 0;
}
body {
background-color: rgb(198 212 227);
font-size: 15px;
}
.container {
background-color: #ffffff;
color: rgb(217, 130, 100);
font-weight: 500;
font-size: 1rem;
line-height: 1.5rem;
width: 100vw;
overflow-x: hidden;
--item-rem: 2; /* 默认用两个字的宽度 */
}
nav {
display: flex;
align-items: center;
width: 100vw;
overflow-x: auto;
margin-bottom: 0.3rem;
scroll-behavior: smooth; /* 平滑过渡 */
transition: 0.3s; /* 过渡时间3s */
}
nav::-webkit-scrollbar {display: none;} /* 隐藏滚动条 */
.item {
margin: 0 2rem;
flex-shrink: 0; /* 防止压缩成竖直排列的文本 */
user-select: none; /* 禁止用户选中 */
-webkit-user-select: none; /* 禁止用户选中,兼容safari3+ */
cursor: pointer; /* 光标为pointer */
scroll-margin: calc(50vw - calc(var(--item-rem) * 1px)); /* 滚动后自动居中 */
}
/* 底部小横条 */
.item::after {
content: " ";
display: block;
height: 0.2rem;
}
/* 小横条颜色 */
.active::after {
background-color: red;
}
</style>
</head>
<body>
<div class="container">
<nav>
</nav>
</div>
<script>
function handleClick(e) {
if(e.target.tagName!=="SPAN") {
return;
}
// 所有元素先取消类名
const spans = document.getElementsByClassName('item');
for(let i=0; i<spans.length; i++) {
spans[i].classList.remove('active');
}
// 被点击元素添加类名
e.target.classList.add('active');
// 滚动到屏幕中间位置
e.target.scrollIntoView();
}
(function() {
const items = ['推荐', '爱心捐赠', '话费直充', '电子产品', '数码大清仓', '推荐', '爱心捐赠', '话费直充', '电子产品', '数码大清仓'];
const nav = document.querySelector('nav');
nav.addEventListener('click', handleClick);
items.forEach((item, index)=>{
const span = document.createElement('span');
span.className = index===0 ? 'item active' : 'item';
span.textContent = item;
span.style.setProperty('--item-rem', item.length*7.5); // 计算自身宽度的一般,因为1rem: 15px
nav.appendChild(span);
});
})()
</script>
</body>
</html>
分类:
JavaScript
, CSS
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通