JS 30 是由加拿大的全端工程师 Wes Bos 免费提供的 JavaScript 简单应用课程,课程主打 No Frameworks
、No Compilers
、No Libraries
、No Boilerplate
在30天的30部教学影片里,建立30个JavaScript的有趣小东西。
另外,Wes Bos 也很无私地在 Github 上公开了所有 JS 30 课程的程序码,有兴趣的话可以去 fork 或下载。
今天我们要做的是置顶导览列,当使用者拉下卷轴而视窗顶部碰到导览列顶部时,若往後继续下拉卷轴则将导览列始终固定在最上方。
header
是网页上方的标题。
#main
是网页的导览列,包含.logo
(初始隐藏)还有其他五个项目。
.site-wrap
放的是一大堆假文还有图片。
<header>
<h1>A story about getting lost.</h1>
</header>
<nav id="main">
<ul>
<li class="logo"><a href="#">LOST.</a></li>
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Images</a></li>
<li><a href="#">Locations</a></li>
<li><a href="#">Maps</a></li>
</ul>
</nav>
<div class="site-wrap">
<!--以下是假文还有图片,为不占空间所以省略-->
</div>
宣告常数nav
取得网页导览列。
宣告常数topOfNav
取得导览列顶部离视窗最上方的距离。
const nav = document.querySelector('#main');
const topOfNav = nav.offsetTop;
我们置顶导览列的机制主要是透过观测卷轴的"卷动量"来决定是否置顶卷轴。为此首先要在window
注册scroll event listener
在卷轴卷动时不断触发,然後用fixNav()
进行事件处理。
在fixedNav()
里面,我们可以判断现在视窗的 y 方向卷动量(window.scrollY
)是否超过导览列的顶部(topOfNav
),如果超过的话就在body
上添加fixed-nav
这个 class,反之若没有超过则移除fixed-nav
。
那为什麽我们还要特别设定body
的padding-top
呢? 因为在导览列(#main
)的 CSS 设定中,我们使用了position: fixed;
,这样就会造成导览列(#main
)原本占的空间突然空出来,之後下方的.site-wrap
看上面还有空间就会挤上来,但挤上来的速度过快,因此在视觉上就会出现诡异的弹跳。
为避免这种状况发生,我们可以在置顶导览列的同时,指定body
的padding-top: nav.ofsetHeight;
,让原本导览列占有的空间,被padding-top
补上。不置顶导览列的同时,理所当然我们就要将body
的padding-top
改回 0。
function fixNav(){
console.log(topOfNav,window.scrollY);
if(window.scrollY >= topOfNav){
document.body.style.paddingTop = nav.offsetHeight + 'px';
document.body.classList.add('fixed-nav');
}else{
document.body.style.paddingTop = 0;
document.body.classList.remove('fixed-nav');
}
}
window.addEventListener('scroll',fixNav);
下面是在body
上有.fixed-nav
这个 class 时的特殊设定。
设定导览列position: fixed
,在预设上是固定在left: 0;
、top: 0;
的位置(视窗左上角),然後加上一点阴影。
.fixed-nav nav{
position: fixed;
box-shadow: 0 5px rgba(0,0,0,0.1);
}
把原本在导览列隐藏的logo
显示出来,设定max-width
(最大宽度)为500px,这里原本也可以用width: 500px;
就好,但是设定width
会让transition
产生的动画效果失效。
.fixed-nav li.logo{
max-width: 500px; /*use width can't show animation effect*/
}
在置顶导览列的同时,把下方的文章区块略为放大。
.fixed-nav .site-wrap{
transform: scale(1);
}
HTMLElement.offsetTop
HTMLElement.offsetHeight
Element.classList
CSS Transform
Element: scroll event
Window.scrollY
>>: 第 08 天 再接再厉坚持不懈( leetcode 300 347 )
支线任务:共笔部落格切版 礼拜一的时候终於把留言版做完了,接着是弄共笔部落格的文章列表样板,花了一两...
以物件做props的传递 我们先来看看一个例子! 在这里我们先用props把外层元件的data里的i...
安装passport套件 安装套件cmd执行以下 composer require laravel/...
在程序语言中万物皆物件, 就如同真实世界中, 所有物质接由元素组成一般 物件基本原理 C#通过new...
更多会员限定文章可以到patreon观看 WSL2, VM, Dual Boot, Proxmox怎...