简体   繁体   中英

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

I have a question relating to the Intersection Observer .

As you can see in my code , when you scroll down to the <footer> the .product-photo (T-Shirt) stays fixed and I'm not sure how to properly add the .absolute class to make it positioned bottom to it's container.

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


My Goal: Make the T-Shirt image...

static when the header is in view
fixed when the header is not in view
absolute when the footer is in view

I have everything working except the 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>

Add the footer to the observer and add/remove fixed and absolute classes by testing isIntersecting of the header/footer which you can get in your case by using 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);

Live example:

 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>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM