Problem: I have a title container element that starts off as 100vh to act as a landing page. When the user scrolls it should reduce the title container element to 15vh and stick it to the top of the window. I've essentially done that but the transition isn't very smooth and jumps around when the user doesn't scroll heaps.
Intended outcome: When the user scrolls at all, it should trigger the title element to reduce in size to 15vh and stick to the top of the window with a smooth transition.
Things tried:
I have tried to give an example below with the minimum amount of code.
window.addEventListener(
'scroll',
function() {
let scrollTop =
window.pageYOffset ||
(document.documentElement || document.body.parentNode || document.body)
.scrollTop;
getPosition();
console.log(getPosition());
if (getPosition() <= 0) {
this.document.getElementById('title').classList.add('header');
} else {
this.document.getElementById('title').classList.remove('header');
}
},
false
);
function getPosition() {
element = document.getElementById('topTitleMarker');
var clientRect = element.getBoundingClientRect();
return clientRect.top;
}
.title {
padding: 0;
margin: 0;
height: 100vh;
font-weight: bold;
font-family: 'Titillium Web', sans-serif;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
background-color: black;
-webkit-transition: all 1s linear;
-moz-transition: all 1s linear;
-o-transition: all 1s linear;
transition: all 1s linear;
color: white;
}
.header {
top: 0px;
height: 15vh;
position: sticky;
}
body {
background-color: white;
height: 500vh;
-ms-overflow-style: none;
scrollbar-width: none;
border-bottom: 5px solid white;
/* overflow: hidden; */
}
.topTitleMarker {
top: 1px;
position: absolute;
}
.test {
margin-top: 15vh;
}
<div id='title' class="title">TITLE</div>
<div id='topTitleMarker' class="topTitleMarker"></div>
<div class="test">TEST</div>
Codepen
I think the jerkiness in the scrolling was because of the .topTitleMarker was referenced as the top of scrolling element with .getBoundingClientRect().top and the transition was based on the height of .title when it increases at 100vh but there isn't a transition for when .title shrinks. Moreover, transition is a process heavy animation, but your animation is a simple one so no worries there.
JavaScript
scrollTop -- it wasn't being usedgetPosition() over to the event handler.getBoundingClientRect().top from
.topTitleMarker to <h1> (in OP it's .title)CSS
transition from <h1>animation: grow 1s forwards ease-out; to <h1>animation: shrink 1s forwards ease-out; to .headeranimation and @keyframes are used for shrinking and growing of <h1>HTML
<h1>window.addEventListener('scroll', headerHeight);
function headerHeight(event) {
const title = document.querySelector('h1');
if (title.getBoundingClientRect().top <= 0) {
title.classList.add('header');
} else {
title.classList.remove('header');
}
};
@import url('https://fonts.googleapis.com/css2?family=Titillium+Web:wght@300;700&display=swap');
html {
font: 300 2ch/1.25 'Titillium Web';
}
body {
height: 500vh;
}
h1 {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100vh;
margin: 0;
padding: 0;
font-weight: 700;
color: white;
background-color: black;
animation: grow 1s forwards ease-out;
}
.header {
position: sticky;
top: 0px;
height: 15vh;
animation: shrink 1s forwards ease-out;
}
@keyframes grow {
0% {
height: 15vh
}
100% {
height: 100vh
}
}
@keyframes shrink {
0% {
height: 100vh
}
100% {
height: 15vh
}
}
<h1>TITLE</h1>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With