<p class="note">Please see this in a bigger screen.</p>
<div class="block first">
<div class="box">Go on, start scrolling...</div>
<div class="sticky">
<div class="sticky-content">I'm sticky</div>
<div class="sticky-floating"></div>
<div class="sticky-exclude" id="js-sticky-exclude">
I'll be covered by the white box bellow
</div>
</div>
</div>
<div class="block" id="js-sticky-next">
<div class="box full">
I'll be above the <span class="highlight">red</span> box...
</div>
</div>
<div class="block">
<div class="box full last">
That's all. Have a nice day!
</div>
</div>
<svg width="0" height="0">
<defs>
<clipPath id="clipPath">
<rect class="clipPathRect"></rect>
</clipPath>
</defs>
</svg>
<footer class="footer">
<p>Made without coffee by <a href="https://twitter.com/a_sandrina_p" class="link">Sandrina Pereira</a>. Would you <a href="https://www.buymeacoffee.com/sandrinap" target="_blank" class="link">buy me one</a>?</p>
</footer>
$highlight: #cc6060;
:root {
// Clip Path to "mask" the element on scrolling.
--js-sticky-exclude-path-height: 100%;
}
// Styles to make sticky work are at ".sticky-exclude"
body {
background: #b3ced6;
color: #394c53;
font-family: "Trebuchet MS", Helvetica, sans-serif;
line-height: 1.4;
padding: 2rem 0;
box-sizing: border-box;
* {
box-sizing: inherit;
}
}
.block {
position: relative;
display: flex;
box-sizing: border-box;
align-items: flex-start;
max-width: 35rem;
margin: 0 auto;
margin-top: 1rem;
&.first {
// optional: so .sticky-floating can be above of the next white box
z-index: 1;
}
}
.sticky {
position: -webkit-sticky;
position: sticky;
top: 10px;
width: 33%;
min-width: 11rem;
margin: 0 1%;
top: 10px;
}
.sticky-content {
height: 150px;
background: #fdfefe;
box-shadow: 0px 1px 2px #4761757a;
padding: 1rem;
}
.sticky-floating {
position: absolute;
top: 65px;
left: 20px;
width: 50px;
height: 120px;
background: #394c53;
box-shadow: 0px 3px 3px #4761757a;
z-index: 1;
}
.sticky-exclude {
$height: 5.5rem; // It's hardcoded, but can be dynamic too
$marginTop: 1rem; // Optional
position: relative;
height: $height;
margin-top: $marginTop;
margin-bottom: calc(#{-$height} + #{-$marginTop}); // Exclude it from ".sticky" height
clip-path: polygon(
0% 0%, // top left corner
100% 0%, // top right corner
100% var(--js-sticky-exclude-path-height), // bottom right corner
0% var(--js-sticky-exclude-path-height) // bottom left corner
);
background: $highlight;
border-bottom: 1px solid #476175;
padding: 2rem 1rem 1rem;
color: #fdfefe;
font-size: 0.9rem;
}
// Layout styling...
.box {
width: 63%;
margin: 0 1%;
height: 70vh;
padding: 1rem;
background: #fdfefe;
box-shadow: 0px 1px 2px #4761757a;
&.full {
width: 100%;
}
&.last {
height: 50vh;
}
}
.highlight {
color: $highlight;
}
.note {
text-align: center;
font-size: 0.8rem;
color: $highlight;
margin-top: -1rem;
@media screen and (min-height: 22rem) {
display: none;
}
}
.link {
display: inline-block;
color: inherit;
text-decoration-color: #9b78de;
padding: 0.1rem 0;
transform: translateX(-0.1em);
margin-right: -0.1em;
&:hover {
color: #8c00ff;
}
&:focus {
outline: none;
background-color: #e9e1f8;
}
}
.footer {
position: relative;
width: 100%;
margin-top: 60px;
padding: 24px 16px;
text-align: center;
font-size: 1rem;
background: white;
border-top: 1px solid gray;
@media screen and (min-height: 26em) {
position: fixed;
left: 0;
bottom: 0;
}
}
View Compiled
let root = document.documentElement;
let hasClipPathSupport = false;
if ('CSS' in window) {
hasClipPathSupport =
CSS.supports('clip-path: polygon(0% 0%, 100% 0%, 100% 0px, 0% 0px)') ||
CSS.supports('-webkit-clip-path: polygon(0% 0%, 100% 0%, 100% 0px, 0% 0px)');
}
const elStickyExclude = document.getElementById('js-sticky-exclude');
const elStickyNext = document.getElementById('js-sticky-next');
const stickyExcludeHeight = elStickyExclude.offsetHeight;
function lookForStickyExclude() {
const extraTop = elStickyExclude.getBoundingClientRect().top + stickyExcludeHeight;
const nextTop = elStickyNext.getBoundingClientRect().top;
const diff = nextTop - extraTop;
const pathHeight = stickyExcludeHeight + diff;
const value = `${pathHeight}px`;
if(hasClipPathSupport) {
root.style.setProperty('--js-sticky-exclude-path-height', value);
} else {
// IE or Edge: ¯\_(ツ)_/¯
elStickyExclude.style.maxHeight = value;
elStickyExclude.style.overflow = 'hidden';
// WIP: Working on another solution with SVG clip-path
// elStickyExclude.style.clipPath = "url(#clipPath)";
}
}
window.addEventListener('scroll', lookForStickyExclude)
View Compiled
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.