JS实现页面侧边栏效果探究

作者:小括号时间:2026-10-24 07:06:17浏览:323

本文探讨利用JavaScript与CSS3实现页面侧边栏滑出效果。通过解决display属性动画化导致的渲染性能问题,结合position定位覆盖与Flex布局特性,实现无需改变DOM结构且具备pointer-events穿透控制的平滑侧边栏交互,并包含移动端适配方案。

实际效果大致如下所示:

发现:display动画的应用

这个标题或许反映了初次见到该效果时的直观感受。第一反应往往是:“页面主体竟然可以被整体移出可视区域?”

发现:display动画的应用

这项技术的起因是笔者近期为社团官网设计一个交互功能:点击头像后,从左侧或右侧滑出一个展示用户个人信息的“面板”。

实现此类效果通常有多种方案,例如利用position定位配合overflow溢出隐藏,或者使用opacity/visibility结合pointer-events属性处理元素穿透。但笔者当时的思路是探索如何为“真正的隐藏”状态(即display属性)添加动画过渡。

在HTML渲染过程中,存在可能影响页面性能的“回流”(Reflow)和“重绘”(Repaint)机制。触发这些过程的原因包括元素位置移动、尺寸改变、节点增删以及本文关注的display显示与隐藏切换等。由于元素变动需要页面快速响应,这种切换在视觉上往往显得“突兀”。 此外,浏览器具备一定智能优化机制——当检测到连续触发页面回流的代码时,它会读取完所有指令后再合并执行。这正是下方代码产生如图所示视觉效果的原因:


/** css代码 */
width: 50px;
height: 50px;
background-color: red;
display: none;
transform: translateX(0);
transition: all .6s ease; //似乎没用?

//js代码
ds.style.display="block";
ds.style.transform="translateX(100px)";

发现:display动画的应用

然而,当操作以下属性时,由于浏览器渲染机制中部分API会强制页面进行即时渲染(以获取精确信息),包括:offsetTop、offsetLeft、offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight、getComputedStyle() (IE中使用currentStyle)。这会直接导致前后两行代码相当于触发了两次渲染。

因此,将上述JavaScript代码调整为以下形式:


//js代码
ds.style.display="block";
ds.offsetHeight;
ds.style.transform="translateX(100px)";

即可实现预期效果。

发现:display动画的应用 目前csdn官网PC端blink发布页面的图片上传功能就采用了类似机制!

随后考虑到该方法仍需JavaScript干预页面结构,于是有了后续优化方案……

实现:如何实现文首展示的效果

此方案基于position定位会“重合”的特性:当两个行内元素均设置了定位属性(但未添加top/left/bottom/right偏移)时,后出现的元素会覆盖先前的元素;此时可通过margin属性调整位置以展示内容。

该方案仅适用于行内元素,行内块元素不适用。 ——云小梦

其大致结构如下:


<div class="page_list">
	<div class="z_two_page">
		<!-- 这里放右侧弹框展示的信息 -->
	</div>
	<div class="box">
		<!-- "页面"的遮罩层 -->
		<div class="zb_mask"></div>
		<!-- 这里放“页面”数据结构(也就是原本应该在body标签下的所有东西) -->
	</div>
	<!-- 这是占位元素 -->
	<div class="space"></div>
</div>

实际运行效果如下:


<div class="page_list">
	<div class="z_two_page">哈哈哈</div>
	<div class="box">
		<div class="zb_mask"></div>
		
		<div id="boxs">
		 <div class="left" style="background-color:#ffc5c5;"></div>
		 <div class="right" style="background-color:#7171f7;">
			 flex下两列布局左边固定右边宽高自适应
		 </div>
		</div>
		<div class="color"></div>
		<a href="#" rel="external nofollow" class="a">千万小心像对a设置全局样式(这叫啥样式重置)</a>
		<div class="center">
			<div class="ds"></div>
			<button class="but">到指定地点</button>
		</div>
		<form id="form" action="#">
			<input type="submit" value="="踢脚板 />
		</form>
		<img id="img" src="compress/compress/img/mxc_16x16.png" />
	</div>
	
	<div class="space"></div>
</div>

如上所示,class为“box”的div内部包含了“原本的页面整体”部分。为了达成预期效果,我们采用了flex布局!

flex简写形式包含三个属性:flex-grow、flex-shrink和flex-basis ——

  • flex-grow:指定容器剩余空间多余时的分配规则,默认值为0,即不分配多余空间;
  • flex-shrink:指定容器剩余空间不足时的分配规则,默认值为1,即空间不足时需分配;
  • flex-basis:指定固定的分配数量,默认值为auto。

设置上述属性时,需同时设置width或height属性;


/* 列表仅水平滚动 */
.page_list { width: 100vw; display: flex; overflow-y: hidden; }
/* 主内容宽度100%,白色背景覆盖 */
.box { flex: 0 0 100vw; height: 100%; background-color: #fff; position: relative; overflow-y: auto;overflow-x: hidden;transition: all .6s ease; }
/** 遮罩层样式 */
.zb_mask{
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	z-index: 100;
	background-color: rgba(0,0,0,.2);
	pointer-events: none;
	opacity: 0;
	transition: all .6s ease;
}
/* 空标签元素,作用是腾出水平滚动空间 */
.space { flex: 0 0 12rem; }
/* 按钮固定定位,藏在内容白色背景后面 */
.z_two_page { width: 12rem; position: fixed; right: 0; top: 0; }

大致逻辑是:在默认状态下仅展示box内容(即与不加额外div效果相同),它是通过background覆盖后续class为“space”的占位元素;在展示“哈哈哈”时,box向右移动。

这里需要注意的是:为什么“哈哈哈”所属div在前而“页面”所属div在后? 因为根据前述原理,此处采用position覆盖机制,其规则为“后面的覆盖前面的”,因此若采用这种布局方式,初始被隐藏的元素必须放置在前面。

代码中flex的前两个属性值为0,表示在空间增大或缩小时保持原状(这是本文的基础!),第三个元素则设置了展示时的“默认大小”:如你所见,box承载的是页面,所以它是100vw,而class为“z_two_page”的元素这里设置了12rem ,你可以随意替换该值!

那如何将“哈哈哈”展示在视野中? —— JavaScript控制“代表页面的元素”整体移动即可。

此处涉及“遮罩层效果”,传统JavaScript实现通常需操作display属性,并可结合前述“display动画效果”增强体验。 但本文CSS代码中添加了 pointer-events 属性:元素是否穿透;设置为none时即可无需在意对应元素是否存在(从事件角度看,此时有和没有效果一致),也无需控制display属性,从而大幅提升性能!


let right=document.querySelector(".right");
let box=document.querySelector(".box");
let mask=document.querySelector(".zb_mask");
right.onclick=function(){
 box.style.marginLeft="-12rem";
 mask.style.cssText+="opacity: 1;pointer-events: all;"
}
mask.onclick=function(){
 box.style.marginLeft="0";
 mask.style.cssText+="opacity: 0;pointer-events: none;"
}

最后,考虑到移动端页面展示的一些问题,例如:右侧留白问题、原生手势对页面整体的影响等,我们一般在CSS中设置 html{max-width: 100vw;overflow-x: hidden;} 。若希望用户在移动端仅能通过点击弹出侧边栏,可在CSS中添加限制 —— 设置上述功能仅在PC端生效:


@media (any-hover: none) {
	.page_list{
		overflow-x: hidden;
	}
}

到此这篇关于JS实现页面侧边栏效果探究的文章就介绍到这了,更多相关js页面侧边栏内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

作者最新文章