Sections
Progress Scroll Section
19 Sep 2022
Animated progress scroll section with informational blocks
HTML
SCSS
PostCSS
JS
<section class="progress-section">
<div class="cont">
<h2>Progress Section</h2>
<div class="progress-chain">
<div class="progress-line">
<div class="fill"></div>
</div>
<div class="progress-items">
<div class="progress-item" data-aos="progress-anim">
<h4 class="progress_title">Inclusive</h4>
<h6>Lorem ipsum dolor</h6>
<p class="progress_desc">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Faucibus
nisl tincidunt eget nullam non nisi.
</p>
</div>
<div class="progress-item" data-aos="progress-anim">
<h4 class="progress_title">Sustainable</h4>
<h6>Lorem ipsum dolor</h6>
<p class="progress_desc">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Faucibus
nisl tincidunt eget nullam non nisi.
</p>
</div>
<div class="progress-item" data-aos="progress-anim">
<h4 class="progress_title">Attentive</h4>
<h6>Lorem ipsum dolor</h6>
<p class="progress_desc">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Faucibus
nisl tincidunt eget nullam non nisi.
</p>
</div>
<div class="progress-item" data-aos="progress-anim">
<h4 class="progress_title">Authentic</h4>
<h6>Lorem ipsum dolor</h6>
<p class="progress_desc">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Faucibus
nisl tincidunt eget nullam non nisi.
</p>
</div>
<div class="progress-item" data-aos="progress-anim">
<h4 class="progress_title">Considerate</h4>
<h6>Lorem ipsum dolor</h6>
<p class="progress_desc">
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Faucibus
nisl tincidunt eget nullam non nisi.
</p>
</div>
</div>
</div>
</div>
</section>
.progress {
&-section {
padding: 80px 0;
h2 {
text-align: center;
margin-bottom: 64px;
}
}
&-chain {
position: relative;
max-width: 964px;
margin: 0 auto;
}
&-item {
max-width: ac(376px, 290px, 768, 1440);
h4 {
margin: 0;
}
p {
padding: 0;
}
&:not(:last-of-type) {
margin-bottom: ac(12px, 60px);
}
&:nth-child(odd) {
text-align: right;
transform: translateX(-100%);
}
&:nth-child(even) {
margin-left: auto;
transform: translateX(100%);
}
@include media(769) {
max-width: 100%;
&:nth-child(odd),
&:nth-child(even) {
margin-left: ac(75px, 30px, 375, 769);
text-align: left;
transform: translateX(50%);
}
}
}
&-line {
width: 4px;
height: 100%;
position: absolute;
background: #c2c2c2;
top: 0;
left: 50%;
transform: translateX(-25%);
overflow: hidden;
.fill {
width: 100%;
height: 10%;
background: var(--primary);
}
@include media(769) {
left: 0;
transform: none;
}
}
}
/* Container */
.cont {
margin: 0 auto;
max-width: 1280px;
width: perc(1280);
@include media(901) {
width: 89%;
}
}
/* AOS */
[data-aos="progress-anim"] {
opacity: 0;
transition: transform 0.3s ease-in-out, opacity 0.5s ease;
&.aos-animate {
opacity: 1;
transform: translateX(0);
}
}
/* Mixin */
@define-mixin media $width {
@media only screen and (max-width: $(width)px) {
@mixin-content;
}
}
.progress {
&-section {
padding: 80px 0;
h2 {
text-align: center;
margin-bottom: 64px;
}
}
&-chain {
position: relative;
max-width: 964px;
margin: 0 auto;
}
&-item {
max-width: ac(376px, 290px, 768, 1440);
h4 {
margin: 0;
}
p {
padding: 0;
}
&:not(:last-of-type) {
margin-bottom: ac(12px, 60px);
}
&:nth-child(odd) {
text-align: right;
transform: translateX(-100%);
}
&:nth-child(even) {
margin-left: auto;
transform: translateX(100%);
}
@mixin media 769 {
max-width: 100%;
&:nth-child(odd),
&:nth-child(even) {
margin-left: ac(75px, 30px, 375, 769);
text-align: left;
transform: translateX(50%);
}
}
}
&-line {
width: 4px;
height: 100%;
position: absolute;
background: #c2c2c2;
top: 0;
left: 50%;
transform: translateX(-25%);
overflow: hidden;
.fill {
width: 100%;
height: 10%;
background: var(--primary);
}
@mixin media 769 {
left: 0;
transform: none;
}
}
}
/* Container */
.cont {
margin: 0 auto;
max-width: 1280px;
width: perc(1280);
@mixin media 901 {
width: 89%;
}
}
/* AOS */
[data-aos="progress-anim"] {
opacity: 0;
transition: transform 0.3s ease-in-out, opacity 0.5s ease;
&.aos-animate {
opacity: 1;
transform: translateX(0);
}
}
const progressSection = document.querySelector(".progress-section");
if (progressSection) {
const scrollFillElement = progressSection.querySelector(".progress-line .fill");
// Scroll progress function
function scrollProgress(section, fillElement, startIndex = 0.25) {
let sectionTopPosition = section.offsetTop - window.innerHeight + window.innerHeight * startIndex;
const windowScroll = document.body.scrollTop || document.documentElement.scrollTop;
const sectionHeight = section.scrollHeight;
const scrolled = ((windowScroll - sectionTopPosition) / sectionHeight) * 100;
let windowWidth = window.innerWidth;
window.addEventListener("resize", function (e) {
if (windowWidth === window.innerWidth) return;
windowWidth = window.innerWidth;
sectionTopPosition =
section.offsetTop -
window.innerHeight +
window.innerHeight * startIndex;
});
scrollFillElement.style.height = scrolled + "%";
window.onscroll = function () {
scrollProgress(section, fillElement);
};
}
scrollProgress(progressSection, scrollFillElement);
}
// AOS init
AOS.init({
startEvent: "load",
disableMutationObserver: false,
});
AOS.refresh(true);
// Functions for pcss
const maxWidth = 1440;
const minWidth = 768;
export function ac( startSize, endSize, minBreakpoint = minWidth, maxBreakpoint = maxWidth) {
const startSizeFormatted = startSize.replace("px", "");
const endSizeFormatted = endSize.replace("px", "");
const difference = startSizeFormatted - endSizeFormatted;
if (difference > 0) {
return `min(max(calc(${endSize} + ${difference} * ((100vw - ${minBreakpoint}px) / ${maxBreakpoint - minBreakpoint})),${endSize}),${startSize})`;
} else {
return `min(max(calc(${endSize} + ${difference} * ((100vw - ${minBreakpoint}px) / ${maxBreakpoint - minBreakpoint})),${startSize}),${endSize})`;
}
}
export const perc = (number1, number2 = maxWidth) =>`${(number1 * 100) / number2}%`;
This progress section was made with Vanilla JS.
There is a function that takes 3 parameters:
section - DOM-element that defines the section where the content is located;
fillElement - DOM-element that fills up with scroll;
startIndex - visibility percentage
For animation we use popular AOS library