Intro
The idea is to create a JS function that will check if an element is in the middle of the screen. It was required to mark elements as active as the user scrolls on the page and different sections are visible to him.
There is a more common way of making something active when the user scrolls: check if the element is in the viewport.
However, this approach was not working for us because the elements that appeared on the page as the user scrolls have different heights and multiple can be visible at the same time in the viewport.
Given this scenario, the best solution was to see if the element passed the middle of the screen when the user scrolled.
So I wanted to check if at any point parts of the element are still “touching” the virtual middle of the screen.
Final result
This is the final result and what I wanted to achieve, getting feedback once the element was in the middle of the screen. Parts of the element still being in the middle of the screen.
How to do it
First, we’re going to create various divs on the page with different heights. We’re going to give them some background color to make things more interesting.
One important thing is that you will need to iterate through those elements. In order to make this easier add a unique “id” for each element, so you can loop them easily.
<div class="dm-content-wrapper">
<div style="height: 100px;"></div>
<div class="dm-content-element" id="id1" style="height: 1200px; background-color: brown; margin-top: 100px;"></div>
<div class="dm-content-element" id="id2" style="height: 500px; background-color: burlywood;"></div>
<div class="dm-content-element" id="id3" style="height: 700px; background-color: green;"></div>
<div class="dm-content-element" id="id4" style="height: 1000px; background-color: greenyellow;"></div>
<div class="dm-content-element" id="id5" style="height: 250px; background-color: plum;"></div>
<div class="dm-content-element" id="id6" style="height: 800px; background-color: purple;"></div>
<div class="dm-content-element" id="id7" style="height: 600px; background-color: goldenrod;"></div>
<div class="dm-middle-of-screen"></div>
</div>
Next, we apply some style to the elements, and wrapper, and create a simple animation that will tilt the component if it’s active.
.dm-content-wrapper {
width: 1000px;
margin: auto;
position: relative;
}
.dm-content-element {
width: 100%;
margin-bottom: 75px;
}
.dm-content-element.active {
animation: tilt-shaking 0.25s infinite;
}
.dm-middle-of-screen {
position: absolute;
height: 1px;
width: 100%;
left: 0;
right: 0;
background-color: blue;
}
@keyframes tilt-shaking {
0% { transform: rotate(0deg); }
25% { transform: rotate(5deg); }
50% { transform: rotate(0eg); }
75% { transform: rotate(-5deg); }
100% { transform: rotate(0deg); }
}
Now we add the JS that will do the job.
It requires jQuery, so make sure you have that added before the script we’re going to create.
<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
Below you can find the JS that will do the check to see if an element is in the middle of the screen.
I left some of the comments, this way you can see in your console what is happening.
I created a function called isInViewport that will trigger on scroll. This function will determine the middle of the screen and position the .dm-middle-of-screen element so you can have a visual representation of the middle of the screen. This can be removed after that.
Once we determine the middle of the screen, we loop through the elements in the page and check if they are passed the middle of the screen. If they are passed we apply a class that will make the element tilt in order to get feedback, if not we remove that class.
<script>
"use strict";
jQuery( document ).ready(function($) {
$(window).on( 'scroll', function(){
console.log('Event Fired');
isInViewport();
});
const isInViewport = function() {
const middleOfScreen = $(window).scrollTop() + $(window).height()/2;
const numberOfElements = $('.dm-content-element').length;
$('.dm-middle-of-screen').css('top', middleOfScreen + 'px');
for (let index = 1; index <= numberOfElements; index++) {
const element = $('#id' + index);
const elementHeight = element.outerHeight();
let topOfElement = 0;
if (element.length) {
topOfElement = element.offset().top;
}
const bottomOfElement = topOfElement + elementHeight;
console.log('Middle of screen:' + middleOfScreen);
console.log('Element Height:' + elementHeight);
console.log('Top Element position:' + topOfElement);
console.log('Bottom Element position:' + bottomOfElement);
console.log('---------------------------------------------');
if ((middleOfScreen > topOfElement) && (middleOfScreen < bottomOfElement)){
console.log('visible');
element.addClass('active');
} else {
console.log('not visible');
element.removeClass('active');
}
}
}
});
</script>
The full page code is below, just paste it and save it as a simple HTML file so you can test it.
Note: line #51 and line #63 can be removed. They only create that line in the middle of the screen.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Middle of screen test</title>
<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
<style>
.dm-content-wrapper {
width: 1000px;
margin: auto;
position: relative;
}
.dm-content-element {
width: 100%;
margin-bottom: 75px;
}
.dm-content-element.active {
animation: tilt-shaking 0.25s infinite;
}
.dm-middle-of-screen {
position: absolute;
height: 1px;
width: 100%;
left: 0;
right: 0;
background-color: blue;
}
@keyframes tilt-shaking {
0% { transform: rotate(0deg); }
25% { transform: rotate(5deg); }
50% { transform: rotate(0eg); }
75% { transform: rotate(-5deg); }
100% { transform: rotate(0deg); }
}
</style>
</head>
<body>
<div class="dm-content-wrapper">
<div style="height: 100px;"></div>
<div class="dm-content-element" id="id1" style="height: 1200px; background-color: brown; margin-top: 100px;"></div>
<div class="dm-content-element" id="id2" style="height: 500px; background-color: burlywood;"></div>
<div class="dm-content-element" id="id3" style="height: 700px; background-color: green;"></div>
<div class="dm-content-element" id="id4" style="height: 1000px; background-color: greenyellow;"></div>
<div class="dm-content-element" id="id5" style="height: 250px; background-color: plum;"></div>
<div class="dm-content-element" id="id6" style="height: 800px; background-color: purple;"></div>
<div class="dm-content-element" id="id7" style="height: 600px; background-color: goldenrod;"></div>
<div class="dm-middle-of-screen"></div>
</div>
</body>
<script>
"use strict";
jQuery( document ).ready(function($) {
$(window).on( 'scroll', function(){
isInViewport();
});
const isInViewport = function() {
const middleOfScreen = $(window).scrollTop() + $(window).height()/2;
const numberOfElements = $('.dm-content-element').length;
$('.dm-middle-of-screen').css('top', middleOfScreen + 'px');
for (let index = 1; index <= numberOfElements; index++) {
const element = $('#id' + index);
const elementHeight = element.outerHeight();
let topOfElement = 0;
if (element.length) {
topOfElement = element.offset().top;
}
const bottomOfElement = topOfElement + elementHeight;
if ((middleOfScreen > topOfElement) && (middleOfScreen < bottomOfElement)){
element.addClass('active');
} else {
element.removeClass('active');
}
}
}
});
</script>
</html>