0

I am building a website that has section panels slide up using position: sticky on scrolling but having issues with fixed elements inside the sticky panels not hiding outside of the section with overflow: hidden.

How can I hide the Logo and Footer outside of each of their section so that they are not sitting over each other and instead on scroll the Logo and Footer appear as their intended colors?

Here is a simple snippet of the problem. As you can see, on the sticky sections, I have applied overflow: hidden but this is ineffective.

html {
  font-family: sans-serif;
  font-size: 20px;
  font-weight: 700;
  text-transform: uppercase;
}

*,
 ::after,
 ::before {
  box-sizing: border-box;
}

body {
  margin: 0;
  overflow-x: hidden;
}

.nav {
  position: fixed;
  width: 100%;
  top: 0;
  left: 0;
  padding: 24px 28px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
}

.footer {
  position: fixed;
  bottom: 0;
  right: 0;
}

.sticky {
  height: 100vh;
  width: 100vw;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  position: sticky;
  overflow: hidden; // Not working to hide and contain the logo and Footer in the section
  top: -1px;
  background-color: #ffffff;
  color: #000000;
}

.dark {
  background-color: #1e1e1e;
  color: #fff;
}

.image {
  color: #fff;
  background-image: url('https://images.unsplash.com/photo-1621864972187-063dae587c27?ixid=MnwxMjA3fDB8MHxlZGl0b3JpYWwtZmVlZHwyOHx8fGVufDB8fHx8&ixlib=rb-1.2.1&auto=format&fit=crop&w=500&q=60');
  background-size: cover;
}
<main>
  <div class="sticky">
    <div class="nav"><svg height="30" width="200">
  <text x="0" y="15" fill="black">Logo svg!</text>
</svg></div>
    <p>Section Light</p>
    <div class="footer"><svg height="30" width="200" transform="rotate(90)">
  <text x="0" y="15" fill="black">Footer!</text>
</svg></div>
  </div>
  <div class="sticky dark">
    <div class="nav"><svg height="30" width="200">
  <text x="0" y="15" fill="white">Logo svg!</text>
</svg></div>
    <p>Section Dark</p>
    <div class="footer"><svg height="30" width="200" transform="rotate(90)">
  <text x="0" y="15" fill="white">Footer!</text>
</svg></div>
  </div>
  <div class="sticky image">
    <div class="nav"><svg height="30" width="200">
  <text x="0" y="15" fill="white">Logo svg!</text>
</svg></div>
    <p>Section with Image</p>
    <div class="footer"><svg height="30" width="200" transform="rotate(90)">
  <text x="0" y="15" fill="white">Footer!</text>
</svg></div>
  </div>
  <div class="sticky dark">
    <div class="nav"><svg height="30" width="200">
  <text x="0" y="15" fill="white">Logo svg!</text>
</svg></div>
    <p>Section Dark</p>
    <div class="footer"><svg height="30" width="200" transform="rotate(90)">
  <text x="0" y="15" fill="white">Footer!</text>
</svg></div>
  </div>
  <div class="sticky">
    <div class="nav"><svg height="30" width="200">
  <text x="0" y="15" fill="black">Logo svg!</text>
</svg></div>
    <p>Section Light</p>
    <div class="footer"><svg height="30" width="200" transform="rotate(90)">
  <text x="0" y="15" fill="black">Footer!</text>
</svg></div>
  </div>
</main>

The website is built using Gatsby incase anyone has a JS solution. I was perhaps thinking of hiding each using a ref and applying a className. Although I am sure there is a simpler solution out there.

Darren
  • 2,176
  • 9
  • 42
  • 98
  • 1
    What behavior are you looking for on the fixed elements? Do you want them to stay static while the user scrolls and just change color? Or do you want each section to have it's own header and footer that moves with it fixed to the position of the section? The reason every logo and footer is overlapped right now is because position: sticky does not contain absolute or fixed position items, since there is no relative parent to those items they are fixed to the window. But how to fix it heavily depends on what you want these items to do on scroll. – JHeth May 25 '21 at 00:22
  • @JHeth. I want them to remain static but hidden outside their parent section. Thank you for your help. – Darren May 25 '21 at 01:04
  • My guess is you'll need some Javascript to accomplish that. Position fixed will always be relative to the viewport and will ignore overflow: hidden on any parent containers (because it can't have a parent other than the window). Last question, will the headers and footers contain different content per section or will it be like your example where they are identical? – JHeth May 25 '21 at 02:54

1 Answers1

2

Not sure whether you need separate content for the nav and footer per section but this answer only applies if you want the same header and footer content to appear over all sections and just change color.

It's possible using mix-blend-mode and the support is good for modern browsers. The spec says that Safari doesn't work "On SVG elements" but it seems to work fine on Safari in the demo below, maybe because it's applied to the SVG's parent.

I pulled the nav and footer out of each section and made one copy of each at the top. Then I applied mix-blend-mode: difference; to both of them and made the fill color of the SVG elements white. Then I added mix-blend-mode: screen; to the .dark class which makes it so that whenever the white SVG elements with difference on their parent container pass over it the color of the SVG elements will change to white. This will not be very useful if you're looking to support IE or if you want different headers and footers by section but in the event that you just want what you had in your code demo to work as you explained then it should be fine for modern browsers.

If you do need varying content per section then it will most likely require Javascript since a fixed element will not respect a relative positioned parent element's rules or will not act like a window fixed element on scroll when using the translateZ hack for instance, good luck!

html {
  font-family: sans-serif;
  font-size: 20px;
  font-weight: 700;
  text-transform: uppercase;
}

*,
 ::after,
 ::before {
  box-sizing: border-box;
}

body {
  margin: 0;
  overflow-x: hidden;
}

.nav {
  position: fixed;
  width: 100%;
  top: 0;
  left: 0;
  padding: 24px 28px;
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  z-index: 99;
  mix-blend-mode: difference;
}

.footer {
  position: fixed;
  bottom: 0;
  right: 0;
  z-index: 99;
  mix-blend-mode: difference;
}

.sticky {
  height: 100vh;
  width: 100vw;
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  position: relative;
  background-color: #ffffff;
  color: #000000;
}
.sticky p {
  position: sticky;
  top: 50%;
  transform: translateY(-50%)
}
.dark {
  background-color: #1e1e1e;
  color: #fff;
  mix-blend-mode: screen;
}
<div class="nav"><svg height="30" width="200">
  <text x="0" y="15" fill="#fff">Logo svg!</text>
 </svg></div>
<div class="footer"><svg height="30" width="200" transform="rotate(90)">
  <text x="0" y="15" fill="#fff">Footer!</text>
 </svg></div>
<main>
  <div class="sticky">
    <p>Section Light</p>
  </div>
  <div class="sticky dark">
    <p>Section Dark</p>
  </div>
  <div class="sticky">
    <p>Section Light</p>
  </div>
  <div class="sticky dark">
    <p>Section Dark</p>
  </div>
  <div class="sticky">
    <p>Section Light</p>
  </div>
</main>
JHeth
  • 7,067
  • 2
  • 23
  • 34
  • Thank you JHeth, but doing this requires you to make the sections `relative` not `sticky` thus loosing the desired layout. – Darren May 25 '21 at 11:28
  • True, but you can make the inner content of the sticky div position: sticky and keep the sticky div relative. I updated the code snippet above to show the result. In order to get a similar positioning on the sticky scroll it takes a larger top value and some translateY to offset the height of the element(s). – JHeth May 25 '21 at 23:05