用纯HTML,JS,CSS实现横向滚动标签页

这篇具有很好参考价值的文章主要介绍了用纯HTML,JS,CSS实现横向滚动标签页。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

前不久,在我的一个项目中,需要展示一个横向滚动的标签页,它支持鼠标横向拖动和点击切换。在实现的过程中,我发现这个小功能需要同时用到前端的三辆马车,但是实现难度不高,而且最终效果还不错,是个难得的初学者项目,于是萌生了写这篇文章的想法,希望对初学者有所帮助。同时为了避免初学者学习框架,我打算用纯原生的方式实现它。

我们最终的效果应该类似于下面:
用纯HTML,JS,CSS实现横向滚动标签页

需求分析

需求分析就是细化我们需要完成的功能,某个功能的完成需要哪些技术的参与。对于初学者,需求分析至关重要,它可以帮助我们理清思路,找到解决问题的突破口,所以应该引起足够的重视。以本篇目标为例,标签页的需求分析就可以像下面这样:

  1. 我们的展示主体是标签页,HTML就是实现主体的主要技术;
  2. 标签页需要可以拖动和点击,这涉及到鼠标事件的监听和处理,是JS的主场;
  3. 既然标签页可以拖动了,那是否要隐藏那个丑陋的滚动条,加个活动指示器,给鼠标变一个样式?很明显,这些都是CSS的优势。

如上,通过对展示,操作,样式的划分,我们进一步明确了HTML,JS,CSS需要完成的工作,甚至连实现都明朗了,所以对需求拆分得越详细,对实现就越有掌控力。

基本框架

对于前端来说,HTML始终是万物之源,所以一言不合先构筑个标准的HTML页面总是没错的。为了便于演示,我将所有的内容都放在一个HTML文件中,文件结构如下

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8">
	<meta name="viewport" content="width=device-width, initial-scale=1">
	<title>Tab演示</title>

	<!-- 这里是样式区,后续css代码会添加到这里 -->
	<style type="text/css">
		
	</style>
</head>
<body>
	<!-- 这里是页面区,后续HTML代码会添加到这里 -->
</body>
<!-- 这里是脚本区,后续JS代码会添加到这里,放在这里是因为方便写代码 -->
<script type="text/javascript">
	
</script>
</html>

这里和以往不同,我将script放到了最后,这是因为我想在写脚本的时候,页面标签直接可用,减少对页面加载的监听,降低复杂性。

实现基本功能

有了基本结构,下一步当然是画页面啦。从效果图中不难看出,页面主要包括一个一个的选项卡,对于HTML来说,这不就是列表嘛。于是,突破口就出现了,我们先往HTML里面加入列表

<ul>
		<li>肖申克的救赎</li>
		<li>霸王别姬</li>
		<li>阿甘正传</li>
		<li>泰坦尼克号</li>
		<li>这个杀手不太冷</li>
		<li>美丽人生</li>
		<li>千与千寻</li>
		<li>辛德勒的名单</li>
		<li>盗梦空间</li>
		<li>忠犬八公的故事</li>
</ul>

于是,我们有了原始的标签页。但是标签页是竖向的,并且有着丑陋的小黑点,不符合需求。
用纯HTML,JS,CSS实现横向滚动标签页
发现了这些问题,下一步当然解决这些问题了,这当然就是CSS的强项啦。首要问题就是让列表横过来。横过来就是改变了元素的相对位置,也就是对应CSS的布局功能。那说起布局,CSS的布局方式有很多,像float,position等等。标签页是横向多个紧密排列的,一个挨着一个,这当然是用flex啦。至于讨厌的小黑点,这是新东西,需要百度一下。查阅文档发现,ul有个属性list-style-type,只需把它设置为none就可以去除小黑点。
此时,页面上的所有选项卡都紧密排列了。为了让它更像一个选项卡,需要给它居中,限制一下宽度,加个背景色,加点padding。下面就是改完样式的代码

ul{
	display: flex;
	justify-content: center;
	align-content: center;
	list-style-type: none;
	background-color: #2397f3;
	width: 600px;
	overflow-x: scroll;
}

li{
	padding: 16px;
	flex-shrink: 0;
}

值得注意的地方有两点。在ul的样式中,由于给ul加了宽度限制,导致它的内容超出了内容区,所以要给ul加上overflow-x的属性。同样由于宽度的原因,flex子项在宽度不够的情况下会默认缩小,表现在标签上就是文字换行啦,flex-shrink: 0;就是让子项保留原有大小。此时,再来刷新页面,可以看到选项卡的基本雏形已经出来了。虽然简陋,但是可以拖动滚动条左右滚动了。下一步,我们的目标就是去除这个丑陋的滚动条。网上搜索一番,发现火狐,IE和Chrome的方式不尽相同,为了兼容性,我们就都给写上。

ul{
	scrollbar-width: none; /* Firefox */
	-ms-overflow-style: none; /* IE 10+ */
}

ul::-webkit-scrollbar {
  display: none; /* Chrome Safari */
}

滚动条去除后,UI好看了,但是新问题出现了——选项卡滚动不了了。别着急,下一步就是添加鼠标拖动功能。

实现交互

在浏览器中,HTML标签有对系统事件的监听能力,响应这些事件,可以使页面实时响应用户的操作。通过对不同的事件的组合,可以实现各种丰富、有趣的功能,标签页也一样。

标签页的首要功能是可以随着鼠标的拖动而滚动元素,那么,首要任务就是监听鼠标的移动事件啦。但是光监听移动还不行,因为通常来说,用户在鼠标左键按下后才希望真正拖动,鼠标左键抬起后结束拖动。所以,这个拖动动作其实需要组合鼠标按下(mousedown),移动(mousemove),抬起(mouseup)三个事件。那么这三个方法加在哪,怎么加呢?

在Web API中,JS操作HTML的入口点是Document对象,Document提供了操作(增删改查)HTML元素的API。这一过程是有标准流程的。

  1. 通过Document查找目标元素;
  2. 对目标元素进行元素,样式变更等操作;
  3. 变更完成;

这一过程是重复且繁杂的,为了减少编写这样的样板代码,加快开发速度,一大堆前端框架应运而生。所以,在学习前端框架时,牢记这一基本步骤,有助于快速理解框架的运行原理。毕竟无论框架怎么变,最终都是要落实到这一过程上。

算法明确后,接下来就是具体实现。

查找目标元素

在查找目标前,需要首先明确目标是谁。用户肯定不希望在页面的其他地方拖动鼠标,标签页跟着滚动了,这很奇怪。所以我们的目标元素应该是无序列表。那么,怎样通过Document知道无序列表呢,查阅Document的API,发现它有个querySelector的方法,这个方法会从上到下查找满足条件的选择器,并返回第一个满足条件的元素,参数则是选择器的名称。上面已经明确过我们的目标是无序列表,所以查找目标元素的最终代码如下

const ul=document.querySelector('ul');

为列表滚起来

每一个HTML元素,在JS中都是Element的对象。上一步我们已经得到了一个Element对象ul,注意,这里的ul对象和ul标签不尽相同。一个是JS的对象对HTML标签的表示,一个是HTML标签。现在有了一个对象,那么就可以通过调用合适的方法来操作这个对象了。通过查阅Element对象的API,发现它有个addEventListener()的方法,这个方法可以完成该对象表示的HTML标签对某些事件的监听。这个方法接收两个参数,第一个参数是事件名称,这在上一节已经说过。第二个参数则是对这个事件的处理,这也是我们实现魔法的地方。

首先,在用户按下鼠标左键后,开始记录鼠标移动情况。在鼠标左键抬起后,停止记录。所以按下和抬起的主要功能就是维护记录开关,控制标签滚动的动作得在鼠标移动的回调里处理。

但在真正写逻辑前,还有两个问题没有处理。
1、怎样让标签滚动?
2、滚动的逻辑怎样写?
问题一当然需要查阅Element的API啦。搜索滚动相关的,发现两个相关性比较大的方法——scrollBy()scrollTo(),都可以滚动内容。唯一的区别是前者的参数是滚动的偏移,后者是最终值。由于鼠标移动是一点一点的,所以选择前者会更方便一点。确定了方法,也就解答了问题一。对于问题二,简单来说就是怎样提供问题一所需的参数。scrollBy()需要两个参数,横向和纵向的滚动偏移值,由于我们只希望标签页可以横向滚动,所以纵向的偏移始终是0,那么横向的呢?通常事件回调都会传递一个事件对象,称作MouseEvent,我们去查查事件对象的API,发现里面带有好几个关于坐标的属性——clientXmovementXscreenXmovementX直接就满足我们的需求,它代表上一次鼠标移动到这一次移动间的偏移,而刚好scrollBy()需要的参数就是偏移,妥了。
综上,得出以下代码

const ul=document.querySelector('ul');
let isMouseDown=false;
ul.addEventListener('mousedown',(e)=>{
	isMouseDown=true;
})
ul.addEventListener('mousemove',(e)=>{
	if(isMouseDown){
		ul.scrollBy(-e.movementX,0);
	}
})
ul.addEventListener('mouseup',(e)=>{
	isMouseDown=false;
})

可以看到,在mousemove的处理上,偏移加了个负号。因为在HTML页面中左上角为坐标原点,右边为X轴正方向。一直往右,则X坐标是增大的,而movementX的值是当前鼠标坐标与上一次坐标点的差值,上一次肯定比这一次小,两者的差值肯定是正值。基于同样的原因,scrollBy()参数正值代表增大X值,也就是显示右边的内容,隐藏左边的内容。两者结合的效果就是,鼠标往右拖,标签页右边隐藏的内容展示了出来,这和直觉相悖。通常我们希望鼠标往右拖,页面展示左边的内容,隐藏右边的。基于这样的分析,我们需要给movementX的值取反。

显示当前选中的标签页

现在,标签页可以滚动了,但是还不能选中。我希望点击某个标签时,标签下方出现一个小横条表示选中状态。很明显,显示小横条是一个CSS的问题,而点击标签切换小横条是JS的问题,这一次我们需要同时处理JS和CSS的问题。

首先来显示小横条。显示小横条有两个思路,一种是在HTML中搞个div标签,另一种是使用::after伪元素。我选择后一种,这样可以保持HTML的干净。
接下来需要确定小横条的样式

  • 覆盖在选中的标签上
  • 位置是标签底部
  • 和标签一样长

我们知道正常的HTML文档流是从左到右,从上到下的,新加的元素会追加到已有元素的右边或者下边。小横条需要覆盖在标签上,那么就要改变这一默认行为,position属性就是实现这个功能的关键。absolutefixed都可以脱离正常文档流,使元素覆盖在祖先元素上,不同的是前者是相对于最近的定位祖先,后者是相当于视口的。小横条是跟随着标签显示的,显然要使用前者。确定了位置,还有大小和样式。既然使用了绝对定位,那么bottom,'left',right相应就能限定它的位置和大小了,小横条的样式就直接用border-bottom吧。于是,小横条的样式就出来了

.current::after{
			content: "";
			position: absolute;
			border-bottom: 4px solid #FFC109;
			border-radius: 2px;
			bottom: 0;
			left: 0;
			right: 0;
}

结束了吗,还没有!使用了绝对定位,必须时刻记得给绝对定位的元素找个锚点,也就是参照,不然top,leftrightbottom去参考谁呢?那么怎样告诉绝对定位的参照物呢,还是position属性。只不过这一次它要出现在参照物的CSS里面。而由前面的样式分析,小横条始终跟着标签页走,也就是说小横条的参照物就是标签页。所以,还要在标签页的样式上加上position的属性。当然,为了区分更明显,我还改变了一下颜色。

.current{
			color: white;
			position: relative;
}

至此,小横条可以正常显示出来了。

小横条跟随鼠标点击显示

有了前面拖动功能的经验支持,这一次轻车熟路了,鼠标点击某个标签页,小横条显示在对应的标签页下方。这一次事件的对象变成了单个标签页,所以点击事件要加在单个标签页上。但是这一次标签页太多了,我们不能还是按照之前的查找-设置方法,这样太繁杂了。巧合的是,前面我们已经得到了ul对象了,通过它的children属性,可以得到所有的li,这不就妥了吗。
小横条要切换到不同的标签页上显示,也就是小横条这个样式要根据点击对象的不同而动态增加或者删除。查阅Element的API,发现有个className的属性,改变它的值就可以增减样式了。

let last=null;
for(let l of ul.children){
		l.addEventListener('click',(e)=>{
			if(last){
				last.className='';
			}
			e.target.className='current';
			last=e.target;
	})
}

代码的实现中,多了个last对象。因为通常标签页只能同时选中一个,当新的标签页被选中之后,上一个选中的标签页应该恢复原始样式,这就是last对象的作用。我们先取消选中上一个元素,然后再选中当前点击的对象,这样就完成了小横条跟随点击选中的效果了。

总结

总的来说,这个项目的难点不在于实现有多难,而是新。很多初学者,面对这种新问题往往束手无策,找不到切入点。本篇尝试以例子的形式,以初学者的思维方式分析需求,拆解问题,提炼方法,最终解决问题。从最朴素的直觉出发,引导思考,找到一条易于接受和理解的方法。

所以,遇到新问题不要慌,对问题拆解后,看能不能找到突破口,如果找不到,再从涉及到的几个主要对象中寻找灵感,通常都会有所收获。最后就是多逛逛MDN,关键时刻真能派上大用场。

最后,情人节快乐,祝有情人终成眷属!

参考文章来源地址https://www.toymoban.com/news/detail-481286.html

  • [1] 使用CSS隐藏元素滚动条
  • [2] Element
  • [3] 事件参考
  • [4] MouseEvent

到了这里,关于用纯HTML,JS,CSS实现横向滚动标签页的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • HTML+JS+CSS歌词滚动效果

    这些代码主要实现了歌词的初始化、显示和随音频播放的同步滚动。其中, initWords 函数用于将歌词字符串解析成数据数组, parseTime 函数用于将时间字符串转换为秒数。通过 setOffset 函数实现歌词的滚动和高亮显示。最后,添加了一个滚动事件监听器,以便用户通过滚动调整

    2024年01月17日
    浏览(46)
  • HTML5+CSS3+JS小实例:鼠标滚轮水平滚动

    实例:鼠标滚轮水平滚动 技术栈:HTML+CSS+JS 效果: 源码: 【html】

    2024年02月06日
    浏览(40)
  • HTML5+CSS3+JS小实例:悬停滚动文字的导航栏

    实例:悬停滚动文字的导航栏 技术栈:HTML+CSS+JS 效果: 源码: 【html】

    2024年02月11日
    浏览(92)
  • css:横向滚动布局

    2024年02月16日
    浏览(37)
  • 在html中使用js实现图片的无缝滚动(四种状态)

    获取整个ul和ul下面的所有li, 把ul里面的li内容添加一份,因为需要完成图片滚动效果所以需要二份完成无缝对接, 定义初始速度。 设置定时器 在定时中进行判断 实现原理:因为ul是跟着父元素div进行定位的,所以ul的offsetleft的值初始值为0。 只需要改变ul的left值就可以完成

    2024年02月09日
    浏览(38)
  • 2022-11 CSS:flex布局父子宽度问题-小程序scrollView-div横向滚动字体超出隐藏-居中

    如上图第二行子元素宽度会跟随第一行宽度 解决方案: 对第二行设置: width: max-content; 使其宽度跟随自身内容 如上图,左侧宽高为112rpx,宽度不生效 解决方案: 对左侧图片设置宽高的同时, 设置最小宽高 效果如下: 例1:

    2024年02月09日
    浏览(59)
  • vue实现简单的鼠标拖拽横向滚动和 鼠标滚轮横向滚动

    第一种,按住鼠标拖拽滚动 以下代码项目中直接使用即可,此种方法是通过鼠标拖拽进行滚动,滑动滚轮无效果。 当然快捷键,shift+鼠标滚轮可以控制横向滚动,对用户来说体验不友好。 css代码 第二种方法是通过鼠标的滚轮进行滚动 css代码

    2024年02月11日
    浏览(47)
  • html模拟聊天框实现,仅用html,css,js实现

    更多静态模板,小米官网,原神官网,各种可视化大屏请前往https://lilisen.cn/了解 html模拟聊天框一共分为两大部分,一部分是 登录 ,一部分是 聊天框内容 聊天框登录代码(内含登录的js,html)         发送表情包          这里发送表情按钮可以发送表情包,具体实现

    2024年02月07日
    浏览(38)
  • html+css+js实现转盘抽奖

     

    2024年01月25日
    浏览(36)
  • Flutter vs 前端 杂谈:SliverAppBar、手动实现Appbar、前端Html+JS怎么实现滚动变化型Appbar - 比较

    Flutter vs 前端 杂谈 SliverAppBar的弹性背景的显隐效果使用Html+JS怎么实现 作者 : 李俊才 (jcLee95):https://blog.csdn.net/qq_28550263 邮箱 : 291148484@163.com 本文地址 :https://blog.csdn.net/qq_28550263/article/details/134149018 在 Flutter 中,最简单的 appbar 就是 Appbar 组件,它没有任何难点,任何刚

    2024年02月05日
    浏览(59)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包