交集观察者:根元素的填充更改 'boundaries'?
Intersection Observer: padding changes 'boundaries' of root element?
当我 运行 Chrome (98)(或 Safari 15.3)中的示例(全页视图)时,第一个元素在滚动一点点时直接消失,所以有点 'when leaving the non-padding or entering the padding-area'
这些选项定义了一个 rootMargin: '0px 0px 0px 0px'
,我认为它指的是根元素边框。这就是它在 Firefox(97) 中的行为方式。内部元素仅在到达顶部时隐藏。
有没有办法将包装器边框定义为边界而不是 'inner padding-border'?
const wrapper = document.querySelector('#wrapper')
const firstElem = document.querySelector('#first-elem')
const options = {
root: wrapper,
rootMargin: '0px 0px 0px 0px',
threshold: 1
}
const observer = new IntersectionObserver(handleFade, options);
observer.observe(firstElem)
function handleFade(entries) {
entries.forEach(entry => {
let target = entry.target
if (entry.isIntersecting) {
target.classList.remove('fade-out')
} else {
target.classList.add('fade-out')
}
})
}
body {
padding: 0;
overflow: hidden;
}
#wrapper {
height: 100vh;
padding-top: 10rem;
overflow: auto;
border: 1px solid darkmagenta;
box-sizing: border-box;
}
.elem {
border: 3px solid teal;
padding: 0 2rem;
height: 20rem;
}
.fade-out {
visibility: hidden;
}
<div id="wrapper">
<div class="elem" id="first-elem">first watched element</div>
<div class="elem">element</div>
<div class="elem">element</div>
<div class="elem">element</div>
</div>
没错。这可能有点令人困惑,但根据 specs.
这似乎是预期的行为
当您为 IntersectionObserver
实例设置 root
时,根元素的 so-called intersection rectangle — the area that the intersection is checked against — will be the content area。
内容区域是指元素最里面的区域,不包括所有的paddings:
至于这个问题的解决方案,您可以简单地使用一个额外的包装器元素来设置填充,然后从 root
元素中删除所有填充:
const wrapper = document.querySelector('#wrapper');
const firstElem = document.querySelector('#first-elem');
const observer = new IntersectionObserver(entries => {
entries[0].target.classList.toggle('fade-out', !entries[0].isIntersecting)
}, {
root: wrapper,
threshold: 1,
});
observer.observe(firstElem)
body {
padding: 0;
margin: 0;
overflow: hidden;
}
#wrapper {
height: 100vh;
overflow: auto;
box-sizing: border-box;
}
#content {
border: 1px solid darkmagenta;
padding: 20px;
padding-top: 10rem;
}
.elem {
background-color: #eee;
border: 2px solid blue;
padding: 20px 30px;
height: 100px;
margin-bottom: 20px;
}
.fade-out {
visibility: hidden;
}
<div id="wrapper">
<div id="content">
<div class="elem" id="first-elem">first watched element</div>
<div class="elem">element</div>
<div class="elem">element</div>
<div class="elem">element</div>
<div class="elem">element</div>
<div class="elem">element</div>
<div class="elem">element</div>
<div class="elem">element</div>
</div>
</div>
虽然你的例子有点奇怪,但我不确定你想做什么,但无论如何,任何时候你想抵消填充对 root
的影响但是您的内容周围仍然有填充,解决方案是在额外的包装元素上声明填充。
鉴于滚动的 wrapper
元素占据了页面的整个高度,一个不同的解决方案是简单地从选项中删除 root: wrapper
,这样元素的位置就会相对于视口
const wrapper = document.querySelector('#wrapper')
const firstElem = document.querySelector('#first-elem')
const options = {
rootMargin: '0px 0px 0px 0px',
threshold: 1
}
const observer = new IntersectionObserver(handleFade, options);
observer.observe(firstElem)
function handleFade(entries) {
entries.forEach(entry => {
let target = entry.target
if (entry.isIntersecting) {
target.classList.remove('fade-out')
} else {
target.classList.add('fade-out')
}
})
}
body {
padding: 0;
overflow: hidden;
}
#wrapper {
height: 100vh;
padding-top: 10rem;
overflow: auto;
border: 1px solid darkmagenta;
box-sizing: border-box;
}
.elem {
border: 3px solid teal;
padding: 0 2rem;
height: 20rem;
}
.fade-out {
visibility: hidden;
}
<div id="wrapper">
<div class="elem" id="first-elem">first watched element</div>
<div class="elem">element</div>
<div class="elem">element</div>
<div class="elem">element</div>
</div>
当我 运行 Chrome (98)(或 Safari 15.3)中的示例(全页视图)时,第一个元素在滚动一点点时直接消失,所以有点 'when leaving the non-padding or entering the padding-area'
这些选项定义了一个 rootMargin: '0px 0px 0px 0px'
,我认为它指的是根元素边框。这就是它在 Firefox(97) 中的行为方式。内部元素仅在到达顶部时隐藏。
有没有办法将包装器边框定义为边界而不是 'inner padding-border'?
const wrapper = document.querySelector('#wrapper')
const firstElem = document.querySelector('#first-elem')
const options = {
root: wrapper,
rootMargin: '0px 0px 0px 0px',
threshold: 1
}
const observer = new IntersectionObserver(handleFade, options);
observer.observe(firstElem)
function handleFade(entries) {
entries.forEach(entry => {
let target = entry.target
if (entry.isIntersecting) {
target.classList.remove('fade-out')
} else {
target.classList.add('fade-out')
}
})
}
body {
padding: 0;
overflow: hidden;
}
#wrapper {
height: 100vh;
padding-top: 10rem;
overflow: auto;
border: 1px solid darkmagenta;
box-sizing: border-box;
}
.elem {
border: 3px solid teal;
padding: 0 2rem;
height: 20rem;
}
.fade-out {
visibility: hidden;
}
<div id="wrapper">
<div class="elem" id="first-elem">first watched element</div>
<div class="elem">element</div>
<div class="elem">element</div>
<div class="elem">element</div>
</div>
没错。这可能有点令人困惑,但根据 specs.
这似乎是预期的行为当您为 IntersectionObserver
实例设置 root
时,根元素的 so-called intersection rectangle — the area that the intersection is checked against — will be the content area。
内容区域是指元素最里面的区域,不包括所有的paddings:
至于这个问题的解决方案,您可以简单地使用一个额外的包装器元素来设置填充,然后从 root
元素中删除所有填充:
const wrapper = document.querySelector('#wrapper');
const firstElem = document.querySelector('#first-elem');
const observer = new IntersectionObserver(entries => {
entries[0].target.classList.toggle('fade-out', !entries[0].isIntersecting)
}, {
root: wrapper,
threshold: 1,
});
observer.observe(firstElem)
body {
padding: 0;
margin: 0;
overflow: hidden;
}
#wrapper {
height: 100vh;
overflow: auto;
box-sizing: border-box;
}
#content {
border: 1px solid darkmagenta;
padding: 20px;
padding-top: 10rem;
}
.elem {
background-color: #eee;
border: 2px solid blue;
padding: 20px 30px;
height: 100px;
margin-bottom: 20px;
}
.fade-out {
visibility: hidden;
}
<div id="wrapper">
<div id="content">
<div class="elem" id="first-elem">first watched element</div>
<div class="elem">element</div>
<div class="elem">element</div>
<div class="elem">element</div>
<div class="elem">element</div>
<div class="elem">element</div>
<div class="elem">element</div>
<div class="elem">element</div>
</div>
</div>
虽然你的例子有点奇怪,但我不确定你想做什么,但无论如何,任何时候你想抵消填充对 root
的影响但是您的内容周围仍然有填充,解决方案是在额外的包装元素上声明填充。
鉴于滚动的 wrapper
元素占据了页面的整个高度,一个不同的解决方案是简单地从选项中删除 root: wrapper
,这样元素的位置就会相对于视口
const wrapper = document.querySelector('#wrapper')
const firstElem = document.querySelector('#first-elem')
const options = {
rootMargin: '0px 0px 0px 0px',
threshold: 1
}
const observer = new IntersectionObserver(handleFade, options);
observer.observe(firstElem)
function handleFade(entries) {
entries.forEach(entry => {
let target = entry.target
if (entry.isIntersecting) {
target.classList.remove('fade-out')
} else {
target.classList.add('fade-out')
}
})
}
body {
padding: 0;
overflow: hidden;
}
#wrapper {
height: 100vh;
padding-top: 10rem;
overflow: auto;
border: 1px solid darkmagenta;
box-sizing: border-box;
}
.elem {
border: 3px solid teal;
padding: 0 2rem;
height: 20rem;
}
.fade-out {
visibility: hidden;
}
<div id="wrapper">
<div class="elem" id="first-elem">first watched element</div>
<div class="elem">element</div>
<div class="elem">element</div>
<div class="elem">element</div>
</div>