Intersection Observer:根据 <header> 和 <footer> 视口位置删除/添加 类

Intersection Observer: Remove/ Add classes based on <header> and <footer> viewport position

我有一个关于 Intersection Observer 的问题。

正如您在 my code 中看到的那样,当您向下滚动到 <footer> 时,.product-photo (T-Shirt)保持固定,我不确定如何正确添加 .absolute class 以使其位于容器底部。

Note: I'm aware of css's position: sticky but it won't work for this particular case


我的目标:制作T-Shirt图像...

static 当 header 在视图中时
fixed 当 header 不在视图中时
absolute 当页脚在视图中时

absolute class

外,我的一切正常

const photo = document.querySelector(".product-photo");
const header = document.querySelector("header");

const sectionOptions = {
 root: null
};

const sectionObserver = new IntersectionObserver(function(entries, sectionObserver) {
  entries.forEach(entry => {
    if (!entry.isIntersecting) {
      photo.classList.add("fixed");
    } 
  else {
      photo.classList.remove("fixed");
    }
  });
}, sectionOptions);


sectionObserver.observe(header);
* { margin: 0; padding: 0; box-sizing: border-box; font-family: roboto; }

header, footer { background: black; color: white; padding: 2rem; }
footer { height: 100vh; }
main { background: white; padding: 1rem; }
section { margin: 2rem 0; }
h1, h2 { margin: 0 0 1rem; font-size: 2rem; }
p { margin: 0 0 2rem; font-size: 1.2rem; line-height: 1.4; }
img { max-width: 100%; }

/* styles
****************************************/
.announcement { background: #f2f2f2; font-size: 2rem; padding: 2rem; text-align: center; border: 3px dashed rgba(0,0,0,.2); margin-top: 0; }
.product { height: 100%; display: flex; justify-items: space-between; position: relative; }
.product-photo { width: 50%; }
.product-description { width: 50%; }
.recommended-products { display: flex; }

/* Sticky Classes */
.product-photo.fixed img { position: fixed; top: 0; left: 0; width: 50%; }
.product-photo.absolute img { position: absolute; left: 0; bottom: 0; width: 50%; }

/* .fixed { position: fixed; top: 0; left: 0; right: 0; } */




/* Mobile */
@media (min-width: 0) and (max-width: 768px) { 
 .product { display: flex; flex-direction: column; }
 .product-photo { width: 100%; }
 .product-description { width: 100%; }
}
  
/* Tablet */
@media (min-width: 769px) and (max-width: 1024px) { 
 
    
}
  
/* Desktop */
@media (min-width: 1025px) { 
 
    
}
<header>Header</header>
<main>
 
 <!-- Product -->
 <section class="product">
  <figure class="product-photo">
   <img src="https://cdn.shopify.com/s/files/1/0078/6825/2273/products/SSCrew_TrueBlack_Front_1950x.png" alt="Black T-Shirt">
  </figure>
  <article class="product-description">
   <h1>Black T-Shirt</h1>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
  </article>
 </section>
</main>
<footer>Footer</footer>

通过测试 header/footer 的 isIntersectingfooter 添加到观察者和 add/remove fixedabsolute 类 ] 你可以通过使用 entry.target.tagName:

const header = document.querySelector("header");
const footer = document.querySelector("footer");

const sectionOptions = {
    root: null
};

const sectionObserver = new IntersectionObserver(function(entries, sectionObserver) {
  const headerEntry = entries.find(entry => entry.target.tagName === 'HEADER');
  const footerEntry = entries.find(entry => entry.target.tagName === 'FOOTER');
  if (headerEntry && headerEntry.isIntersecting) {
    photo.classList.remove("fixed");
  } else if(footerEntry && footerEntry.isIntersecting) {
    photo.classList.remove("fixed");
    photo.classList.add("absolute");
  } else {
    photo.classList.add("fixed");
    photo.classList.remove("absolute");
  }
}, sectionOptions);


sectionObserver.observe(header);
sectionObserver.observe(footer);

实例:

const photo = document.querySelector(".product-photo");
const header = document.querySelector("header");
const footer = document.querySelector("footer");

const sectionOptions = {
 root: null
};

const sectionObserver = new IntersectionObserver(function(entries, sectionObserver) {
  const headerEntry = entries.find(entry => entry.target.tagName === 'HEADER');
  const footerEntry = entries.find(entry => entry.target.tagName === 'FOOTER');
  if (headerEntry && headerEntry.isIntersecting) {
    photo.classList.remove("fixed");
  } else if(footerEntry && footerEntry.isIntersecting) {
    photo.classList.remove("fixed");
    photo.classList.add("absolute");
  } else {
    photo.classList.add("fixed");
    photo.classList.remove("absolute");
  }
}, sectionOptions);


sectionObserver.observe(header);
sectionObserver.observe(footer);
* { margin: 0; padding: 0; box-sizing: border-box; font-family: roboto; }

header, footer { background: black; color: white; padding: 2rem; }
footer { height: 100vh; }
main { background: white; padding: 1rem; }
section { margin: 2rem 0; }
h1, h2 { margin: 0 0 1rem; font-size: 2rem; }
p { margin: 0 0 2rem; font-size: 1.2rem; line-height: 1.4; }
img { max-width: 100%; }

/* styles
****************************************/
.announcement { background: #f2f2f2; font-size: 2rem; padding: 2rem; text-align: center; border: 3px dashed rgba(0,0,0,.2); margin-top: 0; }
.product { height: 100%; display: flex; justify-items: space-between; position: relative; }
.product-photo { width: 50%; }
.product-description { width: 50%; }
.recommended-products { display: flex; }

/* Sticky Classes */
.product-photo.fixed img { position: fixed; top: 0; left: 0; width: 50%; }
.product-photo.absolute img { position: absolute; left: 0; bottom: 0; width: 50%; }

/* .fixed { position: fixed; top: 0; left: 0; right: 0; } */




/* Mobile */
@media (min-width: 0) and (max-width: 768px) { 
 .product { display: flex; flex-direction: column; }
 .product-photo { width: 100%; }
 .product-description { width: 100%; }
}
  
/* Tablet */
@media (min-width: 769px) and (max-width: 1024px) { 
 
    
}
  
/* Desktop */
@media (min-width: 1025px) { 
 
    
}
<header>Header</header>
<main>
 
 <!-- Product -->
 <section class="product">
  <figure class="product-photo">
   <img src="https://cdn.shopify.com/s/files/1/0078/6825/2273/products/SSCrew_TrueBlack_Front_1950x.png" alt="Black T-Shirt">
  </figure>
  <article class="product-description">
   <h1>Black T-Shirt</h1>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
   <p>This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. This is some content. </p>
  </article>
 </section>
</main>
<footer>Footer</footer>