1. 效果(移动端展示,PC端屏幕太宽,tab item数量少滚动不起来)
- 默认选中第一个
![image](https://img2023.cnblogs.com/blog/2261524/202302/2261524-20230210200109690-1559752174.png)
- 点击话费直充,被激活的item会自动居中
![image](https://img2023.cnblogs.com/blog/2261524/202302/2261524-20230210200136814-876730634.png)
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>