文章主要用于记录遇到固定定位导航栏时,锚点定位元素应如何避免被导航栏遮挡。
零、锚点定位的实现方法
1、利用url上的hash
利用hash进行锚点定位是一种传统的锚点定位方法。如url为www.xxx.com/#target,那么页面就会使id为target的元素滚动至可视范围内。
使用这种方法,目的就是改变浏览器窗口url的hash,一般而言有两种方法:
方法一:利用a标签的href属性进行跳转
<a href="#target1">滚动至target1</a>
<a href="#target2">滚动至target2</a>
<div id="target1">
这是target1盒子
</div>
<div id="target2">
这是target2盒子
</div>
方法二:使用js更改hash
window.location.hash="target1"
上述两种方法都能更改url的hash,从而实现锚点定位。但是,利用hash进行定位有一个比较致命的弊端,就是会更改url,刷新页面。
2、利用srollIntoView方法
scrollIntoView是存放在Element.prototype中的方法,也就是说,所有元素节点
都能调用此方法。
我们可以将希望展示的元素节点选取出来,然后调用其scrollIntoView方法来实现锚点定位。
function scrollToTarget(id){
// 选取元素节点
var target = document.getElementById(id)
// 平滑滚动,其他参数可参考MDN文档
target.scrollIntoView({ behavior: "smooth" })
}
scrollToTarget('target1')
scrollToTarget('target2')
使用这种方法的好处就是不需要刷新页面,url美观,而且使用简单。
一、当锚点定位遇上固定定位导航栏
上述篇幅我们简述了两种实现锚点定位的方法,一般情况下,他们都会将需要定位的元素滚动至页面的可视区域中,即元素的上边界与可视区域的上边界重合。
那么这就引出了一个问题:如果在这个页面中,存在一个使用固定定位(fixed)的导航栏,它始终固定在可视区域的顶部。那么当我们使用锚点定位时,元素的一部分将会被导航栏所覆盖。
针对这个需求,我们尝试使用scrollIntoView及配合css布局来解决。
<style>
*{
padding: 0;
margin: 0;
}
.nav{
height: 50px;
width: 100%;
border: 1px solid black;
position: fixed;
top: 0;
left: 0;
background-color: #fff;
}
.other-content1{
height: 500px;
border: 1px solid orange;
margin-top: 50px;
}
.other-content2{
height: 2000px
}
.target{
height: 100px;
background: pink;
}
</style>
<div class="nav">
我是固定定位导航栏
</div>
<div class="other-content1">
我是其他占位内容1
</div>
<div class="target">
我是锚点定位目标元素
</div>
<div class="other-content2">
我是其他占位内容2
</div>
function scrollToTarget(className){
var target = document.getElementsByClassName(className)[0]
target.scrollIntoView({ behavior: "smooth" })
}
scrollToTarget('target')
上述方法就是未经处理的情况,虽然target元素的确实现了定位的目标,但是它的一部分是被处于顶部的导航栏所遮盖。
为了避免上述被遮盖的情况出现,这里提供一种利用padding和margin来进行特殊布局的方法:
对target盒子设置padding-top: 导航栏高度; margin-top: -导航栏高度;
具体对target选择器的改写如下所示
.target{
height: 100px;
background: pink;
padding-top: 50px; //撑高盒子
margin-top: -50px; //将盒子向上移动
}
.other-content1{
height: 500px;
border: 1px solid blue;
margin-top: 50px;
position: relative; //使用定位,提高层级,盖住target的padding部分
}
如上设置之后,就可以使target盒子撑高,并向上移动,然后使用上面的盒子将其padding-top覆盖。那么在进行定位时,target的padding边界就会与可视区域边界重合,content区域则不会被遮挡。
二、总结
文章中使用到的padding-top: 导航栏高度; margin-top: -导航栏高度;
方法,可能会导致页面布局变得复杂。如果大家对此问题有其他见解,欢迎留言讨论。