DEV Community

Lens
Lens

Posted on • Edited on

Making a Birthday webpage that has scroll animation!

Introduction

Yesterday i made a private webpage for my freinds birthday that talks about how amazing they are. So i decided i should share how i made this! For the scroll animation i used IntersectObserver wich i will talk about in another post today so please follow me to see how it works! I'm also a begginer so if you want me to add any improvements please let me know. Make shure to scroll down to see how i made it.

Here it is on codepen:

HTML layout

For the HTML i created 5 section each having a header, text, and an image. Some of the elements in the sections had div's to seperate the p and h1 elements from the images horizontally. I gave each section a class name that matches the color i'm gonna give them while for each child element i gave them a hidden class name wich i'll use to give them a scoll animation. For the last section i gave one of the words in the heading a span element to style it differently later. Each of the images are pictures of my freind, but for this showcase we'll use different images to keep their privacy. Although for the last section i gave it a class name called Final wich will show an image saying "Thank you!" on it.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="style.css" type="text/css">
    <script defer src="app.js"></script>
</head>
<body>
    <section class="darkestPeach">
        <div class="hidden">
        <img src="https://gifimage.net/wp-content/uploads/2017/10/dancing-cat-gif.gif">
        </div>
        <div class="hidden">
        <h1>Happy Birthday Unicorn!</h1>
        <p>Even though i haven't seen your face in centuries. I hope you like this :D</p>
        </div>
    </section>
    <section class="darkPeach">
<div class="hidden">
    <h1>Yoshi!</h1>
<p>You're a pretty cool person who plays on the nintendo!</p>
<br>
<h1>Mmm Chezburger</h1>
<p>You like playing roblox! Best free game on Earth! We should play a game one day :o</p>
</div>
<img class="hidden" src="https://media.discordapp.net/attachments/701125768675065917/1030316445445398538/2022-10-13_9.png?width=1246&height=701" class="awards">
    </section>
    <section class="peach">
        <div class="hidden">
        <h1>You're an amazing freind!</h1>
        <p>
           To tell the truth, i didn't think i would be able to make this on time, but i tried my best to give you a showage
           of appreciation. Even though we don't talk a lot you're still my freind and i just wanted to show you that it's 
           not just your family who cares about you. I also made this to help improve my coding skills since i made this 
           website without any apps or extensions, it's just all code! I don't know a lot about you so i just put some 
           random images and an aeshetic image at the bottom. I hope you have an amazing year and uhh I'll make something
           even better for you next year! (p.s the section above is supposed to be all the hobbies that you master at, i
           should've asked more questions to put more hobbies there) 
        </p>
        </div>
        <img class="hidden" src="https://media.tenor.com/GdJRGf60YN4AAAAC/hugs-sending-virtual-hugs.gif">
    </section>
    <section class="lightPeach">
   <div class="hidden">
    <h1>One word, <span>Fantastic</span></h1>
    <p>That's the word i would use to describe you. Even though i don't know a lot about you it makes me wonderous.
        Anways your teasy ego is amazing, even though you don't text a lot you text more that Prishaa or the others. 
        There isn't really anything you should change about you (except for your response times on discord) so keep 
        being you the that's how you met most of us :). 
    </p>
    </div>
    <img class="hidden" src="https://media.discordapp.net/attachments/701125768675065917/1030315397121052762/2022-10-13_7.png?width=1246&height=701">
    </section>
    <section class="final"><h1 class="move">Thank You!</h1></section>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Note: You can make the image to the left and the text to the right or reverse it depending on the order you put them

CSS

To layout the section i gave it a min-height of 500px. I then gave each section flex and align-items to the center while using space-around to space around each child element. I used gap and gave it the value of 5rem to always space the elements apart. Then i made shure the html and body had margin set to 0 with the height and width set to 100%. I gave the images a width of 300px with a border radius of 10px for extra styling. Finally i put a transition of 0.8s. This is so later the :hover animation lasts 0.8s. That animation causes the bottom margin to go up by 20px with a box-shadow as well.

For each section class i gave them different colors with some having differnet fonts and some having grid (for better layout). I gave the span element a font-family of lobster. For the last element i gave it a class called move wich has the property margin-right that has the value of 1000px(to make shure it doesn't block the image at the bottom).

Lastly i gave hidden class an opacity of 0 and gave their transform element translateX(-100%). This is how our scroll animation starts so i then give it a transition of 1s for all. Next is the show class, i gave it an opacity of 1 which is the same as 100%. The transform: translateX property goes back to 100% as well. This means that at the end of the animation the content can be fully seen and placed right where it should be.

For the class called Final i gave it a background-image with a font-family to have it as a thank you image.

@import url("https://fonts.googleapis.com/css2?family=Dancing+Script&family=Lobster&family=Lora:ital@0;1&family=Poppins:wght@300;400&display=swap");

html,
body {
  height: 100%;
  width: 100%;
  margin: 0;
}

body {
  margin: 0;
  background-color: #f8ad9d;
}

section {
  display: flex;
  align-items: center;
  justify-content: space-around;
  gap: 5rem;
  min-height: 500px;
}

img {
  width: 300px;
  border-radius: 10px;
  margin-top: 50px;
  transition: 0.8s ease;
}

img:hover {
  margin-bottom: 20px;
  box-shadow: 12px 12px #07072c;
}

.darkestPeach {
  background-color: #f08080;
  font-family: "Poppins", sans-serif;
  color: antiquewhite;
}

.darkPeach {
  background-color: #f4978e;
}

.Peach {
  background-color: #f8ad9d;
  display: grid;
  grid-template-columns: 40% auto;
}

.lightPeach {
  background-color: #f7dba7;
  color: White;
  font-family: "Poppins", sans-serif;
}

.awards:hover {
  margin-bottom: 20px;
  box-shadow: 12px 12px wheat;
}

.gray {
  font-family: "Poppins", sans-serif;
}

.whitePeach {
  background-color: antiquewhite;
  display: grid;
  grid-template-columns: 50% 50%;
  font-family: "Poppins", sans-serif;
  word-wrap: break-word;
  justify-content: space-between;
  align-content: center;
}

.hidden {
  opacity: 0;
  transition: all 1s;
  filter: opacity(0);
  transform: translateX(-100%);
}

.show {
  opacity: 1;
  filter: opacity(100%);
  transform: translateX(0);
}

@media (prefers-reduced-motion) {
  .hidden {
    transition: none;
  }
}

span {
  font-family: "Lobster", cursive;
}

.final {
  gap: 1rem;
  font-family: "Dancing Script", cursive;
  background-image: url("https://media.discordapp.net/attachments/701125768675065917/1030317951141818398/2022-10-13_10.png?width=1246&height=701");
}

.move {
  margin-right: 1000px;
}
Enter fullscreen mode Exit fullscreen mode

Note: I got the hex colors from coolors.co, it's a nice place to find hex colors!

Scroll Animation

For the scroll Animation i used IntersectionObserver wich is used to observe changes in a targeted element(you can learn more here). I used it so when an element of a section intersects and is now observed the animation will start. First i made a const variable that stores all the elements with the class hidden on it by using document.querySelectorAll(). I then made another const variable but this one has the IntersectionObserver(). Inside the Intersection Observer it has the property called entries wich means it can observe multiple entries. Due to this i needed to use a for loop over them so then i can run a conditonal check to find out if the entry is intersecting the viewport or not. If it's intersecting the show class will be added to that element but for anything else that new class will be removed. This is so if the element isn't intersecting the viewport anymore the animation will go back making the animation run again whenever it in the viewport again. Finally i told the observer to observe each hidden class element.

const hiddenElements = document.querySelectorAll(".hidden");

const observer = new IntersectionObserver((entries) => {
  entries.forEach((entry) => {
    console.log(entry);
    if (entry.isIntersecting) {
      entry.target.classList.add('show');
    }
    else {
      entry.target.classList.remove('show');
    }
  });
})

hiddenElements.forEach((el) => observer.observe(el));
Enter fullscreen mode Exit fullscreen mode

Top comments (0)