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>