以正确方式到达 window 边缘的事件(onscroll)
Event of reaching the edge of window in correct way (onscroll)
以防万一,这是我的第一个问题。
我有:
具有透明背景的导航菜单,并在到达 window.
的顶部边缘时尝试更改背景
window.addEventListener("scroll", navSticky);
function navSticky(){
let nav = document.getElementById('navbar');
let bounding = nav.getBoundingClientRect();
if(bounding.top <= 0 ){
nav.classList.add("sticky");
}else{
nav.classList.remove("sticky");
}
}
*{
margin: 0;
text-align: center;
}
body{
background: lightgrey;
}
header h1{
padding: 40px;
}
nav{
position: sticky;
top: 0;
padding: 12px;
background: linear-gradient(to right,
rgba(0,0,0,0),
rgba(0,255,0, 0.5),
rgba(255,0,0, 0.5),
rgba(0,0,0,0));
color: black;
}
nav:before{
content: "now bg transparent";
}
.container{
min-height: 1000px;
padding: 20px;
}
nav.sticky{
background: linear-gradient(to right,
rgb(0,255,0),
rgb(255,0,0));
color: white;
}
nav.sticky:before{
content: "now bg isn't transparent";
}
<body>
<header>
<h1>Header, that ask u to scroll page</h1>
</header>
<nav id="navbar">
</nav>
<div class ="container">
When we scroll page, and nav reached top of screen, .sticky add to classList<br>
</div>
</body>
它的工作,但我有几个问题:
- 没有js也能做到吗?
- 是否可以优化此脚本,因为滚动事件调用如此频繁..
谢谢!
- 很遗憾没有。
- 是的,IntersectionObserver API 是针对此特定问题的非常好的高效解决方案。
API 允许您在元素进入或离开视口时观察 元素。它在远离主线程的地方执行此操作,因此您不会获得任何渲染阻塞代码。
在您的具体情况下,请观察 <header>
元素。每当元素离开视图时,navbar
就会变得粘滞。在回调中检查 isIntersecting
属性 是 true
还是 false
。 属性 表示观察到的元素是否(部分)在视图中。
const header = document.querySelector('#header');
const nav = document.querySelector('#navbar');
const callback = ([entry]) => {
const { isIntersecting } = entry;
nav.classList.toggle('sticky', !isIntersecting);
};
const options = {
root: null,
rootMargin: '0px',
threshold: 0
};
const observer = new IntersectionObserver(callback, options);
observer.observe(header);
* {
margin: 0;
text-align: center;
}
body {
background: lightgrey;
}
header h1 {
padding: 40px;
}
nav {
position: sticky;
top: 0;
padding: 12px;
background: linear-gradient(to right, rgba(0, 0, 0, 0), rgba(0, 255, 0, 0.5), rgba(255, 0, 0, 0.5), rgba(0, 0, 0, 0));
color: black;
}
nav:before {
content: "now bg transparent";
}
.container {
min-height: 1000px;
padding: 20px;
}
nav.sticky {
background: linear-gradient(to right, rgb(0, 255, 0), rgb(255, 0, 0));
color: white;
}
nav.sticky:before {
content: "now bg isn't transparent";
}
<body>
<header id="header">
<h1>Header, that ask u to scroll page</h1>
</header>
<nav id="navbar"></nav>
<div class="container">
When we scroll page, and nav reached top of screen, .sticky add to classList<br>
</div>
</body>
以防万一,这是我的第一个问题。
我有: 具有透明背景的导航菜单,并在到达 window.
的顶部边缘时尝试更改背景window.addEventListener("scroll", navSticky);
function navSticky(){
let nav = document.getElementById('navbar');
let bounding = nav.getBoundingClientRect();
if(bounding.top <= 0 ){
nav.classList.add("sticky");
}else{
nav.classList.remove("sticky");
}
}
*{
margin: 0;
text-align: center;
}
body{
background: lightgrey;
}
header h1{
padding: 40px;
}
nav{
position: sticky;
top: 0;
padding: 12px;
background: linear-gradient(to right,
rgba(0,0,0,0),
rgba(0,255,0, 0.5),
rgba(255,0,0, 0.5),
rgba(0,0,0,0));
color: black;
}
nav:before{
content: "now bg transparent";
}
.container{
min-height: 1000px;
padding: 20px;
}
nav.sticky{
background: linear-gradient(to right,
rgb(0,255,0),
rgb(255,0,0));
color: white;
}
nav.sticky:before{
content: "now bg isn't transparent";
}
<body>
<header>
<h1>Header, that ask u to scroll page</h1>
</header>
<nav id="navbar">
</nav>
<div class ="container">
When we scroll page, and nav reached top of screen, .sticky add to classList<br>
</div>
</body>
它的工作,但我有几个问题:
- 没有js也能做到吗?
- 是否可以优化此脚本,因为滚动事件调用如此频繁..
谢谢!
- 很遗憾没有。
- 是的,IntersectionObserver API 是针对此特定问题的非常好的高效解决方案。
API 允许您在元素进入或离开视口时观察 元素。它在远离主线程的地方执行此操作,因此您不会获得任何渲染阻塞代码。
在您的具体情况下,请观察 <header>
元素。每当元素离开视图时,navbar
就会变得粘滞。在回调中检查 isIntersecting
属性 是 true
还是 false
。 属性 表示观察到的元素是否(部分)在视图中。
const header = document.querySelector('#header');
const nav = document.querySelector('#navbar');
const callback = ([entry]) => {
const { isIntersecting } = entry;
nav.classList.toggle('sticky', !isIntersecting);
};
const options = {
root: null,
rootMargin: '0px',
threshold: 0
};
const observer = new IntersectionObserver(callback, options);
observer.observe(header);
* {
margin: 0;
text-align: center;
}
body {
background: lightgrey;
}
header h1 {
padding: 40px;
}
nav {
position: sticky;
top: 0;
padding: 12px;
background: linear-gradient(to right, rgba(0, 0, 0, 0), rgba(0, 255, 0, 0.5), rgba(255, 0, 0, 0.5), rgba(0, 0, 0, 0));
color: black;
}
nav:before {
content: "now bg transparent";
}
.container {
min-height: 1000px;
padding: 20px;
}
nav.sticky {
background: linear-gradient(to right, rgb(0, 255, 0), rgb(255, 0, 0));
color: white;
}
nav.sticky:before {
content: "now bg isn't transparent";
}
<body>
<header id="header">
<h1>Header, that ask u to scroll page</h1>
</header>
<nav id="navbar"></nav>
<div class="container">
When we scroll page, and nav reached top of screen, .sticky add to classList<br>
</div>
</body>