Reputation: 405
I bumped into this problem while watching the Intersection Observer
tutorial. Mine is a div instead of an image so I did not have to specify an attribute like the one in the video and I believe I almost did everything right as I get 10 console logs because I have 10 divs with a class "box", which were used as a variable in JS file. I used opacity and transformation for the animation as indicated in CSS. I appreciate what I am doing wrong that I cannot see the scroll animation happening.
const targets = document.querySelectorAll('.box');
const lazyLoad = target => {
const io = new IntersectionObserver((entries,observer) => {
entries.forEach(entry => {
console.log('hello World');
if(entry.isIntersecting) {
const div = entry.target;
div.classList.add('fade');
observer.disconnect();
}
});
});
io.observe(target);
};
targets.forEach(lazyLoad);
:root {
--primary-color:#425b84;
--secondary-color:#5b7bb4;
--max-width:1100px;
}
* {
margin:0;
padding:0;
box-sizing:border-box;
}
body {
font:normal 1rem/1.5 'Arial', sans-serif;
background:var(--primary-color);
color:#fff;
overflow-x:hidden;
padding-bottom:50px;
}
#main-header {
background:var(--secondary-color);
padding:4rem 0;
}
.container {
max-width:var(--max-width);
margin:0 auto;
text-align:center;
}
h1 {
font-size:2.3rem;
}
#timeline ul {
background:var(--primary-color);
padding:50px 0;
}
/* Create Line */
#timeline ul li {
list-style:none;
position: relative;
width:6px;
margin:0 auto;
padding-top:50px;
background:#fff;
}
/* Boxes */
#timeline ul li div {
position: relative;
bottom:0;
width:400px;
padding:1rem;
background:var(--secondary-color);
transition:all 0.5s ease-in-out;
opacity:0;
}
.fade {
opacity:1;
transition:all 0.5s ease-in-out;
transform:translateX(0);
}
/* Right Side */
#timeline ul li:nth-child(odd) div {
left:40px;
transform:translateX(1100px);
}
/* Left Side */
#timeline ul li:nth-child(even) div {
left:-434px;
transform:translateX(-1100px);
}
/* Dots */
#timeline ul li:after {
content:'';
position: absolute;
left:50%;
bottom:0;
width:25px;
height:25px;
background:var(--secondary-color);
transform:translateX(-50%);
border-radius:50%;
transition:background 0.5s ease-in-out;
}
/* Arrows Base */
#timeline div:before {
content:'';
position: absolute;
bottom:5px;
width:0;
height:0;
border-style:solid;
}
/* Right Side Arrows */
#timeline ul li:nth-child(odd) div:before {
left:-15px;
border-width:8px 16px 8px 0;
border-color:transparent var(--secondary-color) transparent transparent;
}
/* Left Side Arrows */
#timeline ul li:nth-child(even) div:before {
right:-15px;
border-width:8px 0 8px 16px;
border-color:transparent transparent transparent var(--secondary-color);
}
@media(max-width:900px){
#timeline ul li div {
width:250px;
}
#timeline ul li:nth-child(even) div {
left:-284px;
}
}
@media(max-width:600px) {
#timeline ul li {
margin-left:20px;
}
#timeline ul li div {
width:calc(100vw - 90px);
}
#timeline ul li:nth-child(even) div {
left:40px;
}
/* Right Side Arrows */
#timeline ul li:nth-child(even) div:before {
left:-15px;
border-width:8px 16px 8px 0;
border-color:transparent var(--secondary-color) transparent transparent;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://kit.fontawesome.com/bbb16afe05.js" crossorigin="anonymous"></script>
<link rel="stylesheet" href="./css/aos.css">
<link rel="stylesheet" href="./css/style.css">
<title>Knowledge Timeline</title>
</head>
<body>
<header id="main-header">
<div class="container">
<h1><i class="fas fa-brain"></i> Knowledge Resume</h1>
<h3><div class="fas fa-user"></div> Jun Jung</h3>
</div>
</header>
<section id="timeline">
<ul>
<li>
<div class="box">
<h3><i class="fas fa-chevron-right"></i> 2007: HTML & CSS</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque animi at, dolorum tempora labore exercitationem sapiente voluptate possimus necessitatibus quos cum, voluptatibus maiores voluptates quam illum consequatur nemo est dolores.</p>
</div>
</li>
<li>
<div class="box">
<h3><i class="fas fa-chevron-right"></i> 2009: JavaScript & jQuery</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque animi at, dolorum tempora labore exercitationem sapiente voluptate possimus necessitatibus quos cum, voluptatibus maiores voluptates quam illum consequatur nemo est dolores.</p>
</div>
</li>
<li>
<div class="box">
<h3><i class="fas fa-chevron-right"></i> 2010: PHP & Wordpress</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque animi at, dolorum tempora labore exercitationem sapiente voluptate possimus necessitatibus quos cum, voluptatibus maiores voluptates quam illum consequatur nemo est dolores.</p>
</div>
</li>
<li>
<div class="box">
<h3><i class="fas fa-chevron-right"></i> 2011: Ruby on Rails</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque animi at, dolorum tempora labore exercitationem sapiente voluptate possimus necessitatibus quos cum, voluptatibus maiores voluptates quam illum consequatur nemo est dolores.</p>
</div>
</li>
<li>
<div class="box">
<h3><i class="fas fa-chevron-right"></i> 2012: Python</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque animi at, dolorum tempora labore exercitationem sapiente voluptate possimus necessitatibus quos cum, voluptatibus maiores voluptates quam illum consequatur nemo est dolores.</p>
</div>
</li>
<li>
<div class="box"
>
<h3><i class="fas fa-chevron-right"></i> 2013: Node.js & React</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque animi at, dolorum tempora labore exercitationem sapiente voluptate possimus necessitatibus quos cum, voluptatibus maiores voluptates quam illum consequatur nemo est dolores.</p>
</div>
</li>
<li>
<div class="box">
<h3><i class="fas fa-chevron-right"></i> 2014: Angular & React Native</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque animi at, dolorum tempora labore exercitationem sapiente voluptate possimus necessitatibus quos cum, voluptatibus maiores voluptates quam illum consequatur nemo est dolores.</p>
</div>
</li>
<li>
<div class="box">
<h3><i class="fas fa-chevron-right"></i> 2015: Vue.js </h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque animi at, dolorum tempora labore exercitationem sapiente voluptate possimus necessitatibus quos cum, voluptatibus maiores voluptates quam illum consequatur nemo est dolores.</p>
</div>
</li>
<li>
<div class="box">
<h3><i class="fas fa-chevron-right"></i> 2016:GraphQL & Apollo</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque animi at, dolorum tempora labore exercitationem sapiente voluptate possimus necessitatibus quos cum, voluptatibus maiores voluptates quam illum consequatur nemo est dolores.</p>
</div>
</li>
<li>
<div class="box">
<h3><i class="fas fa-chevron-right"></i> 2017: Machine Learning</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque animi at, dolorum tempora labore exercitationem sapiente voluptate possimus necessitatibus quos cum, voluptatibus maiores voluptates quam illum consequatur nemo est dolores.</p>
</div>
</li>
</ul>
</section>
<script src="./js/main.js"></script>
</body>
</html>
Upvotes: 1
Views: 562
Reputation: 16311
Your intersection observer is currently targeting the .box
elements which trigger the initial 10 console logs because they exist on the DOM but wont trigger on scroll because they're not on the screen (out of viewport).
Also, as mentioned in the other answer, you should use a common observer for all your instances.
However, if you want to use a separate observer for each instance, you can target the .box
element's parent i.e. the <li>
element and when the <li>
element is scrolled into view, you can just add the class to it's child element which is the .box
element you were targeting earlier using the ParentNode.children property like this:
const targets = document.querySelectorAll('#timeline li');
const lazyLoad = target => {
const io = new IntersectionObserver((entries,observer) => {
entries.forEach(entry => {
console.log('hello World');
if(entry.isIntersecting) {
const div = entry.target.children[0];
div.classList.add('fade');
observer.disconnect();
}
});
});
io.observe(target);
};
targets.forEach(lazyLoad);
Also, your css #timeline ul li:nth-child(odd) div
style properties is overriding your new .fade
properties because it targetting is more precise. You will need the new .fade
properties to target the .box
element as precise as you did with the initial styles like this:
#timeline ul li:nth-child(odd) div.fade {
opacity:1;
transition:all 0.5s ease-in-out;
transform:translateX(0) !important;
}
#timeline ul li:nth-child(even) div.fade {
opacity:1;
transition:all 0.5s ease-in-out;
transform:translateX(0) !important;
}
Or you can combined the above css like this:
#timeline ul li:nth-child(odd) div.fade, #timeline ul li:nth-child(even) div.fade {
opacity:1;
transition:all 0.5s ease-in-out;
transform:translateX(0) !important;
}
Check and run the following Code Snippet or open this JSFiddle link for a practical example of the above:
const targets = document.querySelectorAll('#timeline li');
const lazyLoad = target => {
const io = new IntersectionObserver((entries,observer) => {
entries.forEach(entry => {
console.log('hello World');
if(entry.isIntersecting) {
const div = entry.target.children[0];
div.classList.add('fade');
observer.disconnect();
}
});
});
io.observe(target);
};
targets.forEach(lazyLoad);
:root {
--primary-color:#425b84;
--secondary-color:#5b7bb4;
--max-width:1100px;
}
* {
margin:0;
padding:0;
box-sizing:border-box;
}
body {
font:normal 1rem/1.5 'Arial', sans-serif;
background:var(--primary-color);
color:#fff;
overflow-x:hidden;
padding-bottom:50px;
}
#main-header {
background:var(--secondary-color);
padding:4rem 0;
}
.container {
max-width:var(--max-width);
margin:0 auto;
text-align:center;
}
h1 {
font-size:2.3rem;
}
#timeline ul {
background:var(--primary-color);
padding:50px 0;
}
/* Create Line */
#timeline ul li {
list-style:none;
position: relative;
width:6px;
margin:0 auto;
padding-top:50px;
background:#fff;
}
/* Boxes */
#timeline ul li div {
position: relative;
bottom:0;
width:400px;
padding:1rem;
background:var(--secondary-color);
transition:all 0.5s ease-in-out;
opacity:0;
}
#timeline ul li:nth-child(odd) div.fade, #timeline ul li:nth-child(even) div.fade {
opacity:1;
transition:all 0.5s ease-in-out;
transform:translateX(0) !important;
}
/* Right Side */
#timeline ul li:nth-child(odd) div {
left:40px;
transform:translateX(1100px);
}
/* Left Side */
#timeline ul li:nth-child(even) div {
left:-434px;
transform:translateX(-1100px);
}
/* Dots */
#timeline ul li:after {
content:'';
position: absolute;
left:50%;
bottom:0;
width:25px;
height:25px;
background:var(--secondary-color);
transform:translateX(-50%);
border-radius:50%;
transition:background 0.5s ease-in-out;
}
/* Arrows Base */
#timeline div:before {
content:'';
position: absolute;
bottom:5px;
width:0;
height:0;
border-style:solid;
}
/* Right Side Arrows */
#timeline ul li:nth-child(odd) div:before {
left:-15px;
border-width:8px 16px 8px 0;
border-color:transparent var(--secondary-color) transparent transparent;
}
/* Left Side Arrows */
#timeline ul li:nth-child(even) div:before {
<header id="main-header">
<div class="container">
<h1><i class="fas fa-brain"></i> Knowledge Resume</h1>
<h3><div class="fas fa-user"></div> Jun Jung</h3>
</div>
</header>
<section id="timeline">
<ul>
<li>
<div class="box">
<h3><i class="fas fa-chevron-right"></i> 2007: HTML & CSS</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque animi at, dolorum tempora labore exercitationem sapiente voluptate possimus necessitatibus quos cum, voluptatibus maiores voluptates quam illum consequatur nemo est dolores.</p>
</div>
</li>
<li>
<div class="box">
<h3><i class="fas fa-chevron-right"></i> 2009: JavaScript & jQuery</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque animi at, dolorum tempora labore exercitationem sapiente voluptate possimus necessitatibus quos cum, voluptatibus maiores voluptates quam illum consequatur nemo est dolores.</p>
</div>
</li>
<li>
<div class="box">
<h3><i class="fas fa-chevron-right"></i> 2010: PHP & Wordpress</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque animi at, dolorum tempora labore exercitationem sapiente voluptate possimus necessitatibus quos cum, voluptatibus maiores voluptates quam illum consequatur nemo est dolores.</p>
</div>
</li>
<li>
<div class="box">
<h3><i class="fas fa-chevron-right"></i> 2011: Ruby on Rails</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque animi at, dolorum tempora labore exercitationem sapiente voluptate possimus necessitatibus quos cum, voluptatibus maiores voluptates quam illum consequatur nemo est dolores.</p>
</div>
</li>
<li>
<div class="box">
<h3><i class="fas fa-chevron-right"></i> 2012: Python</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque animi at, dolorum tempora labore exercitationem sapiente voluptate possimus necessitatibus quos cum, voluptatibus maiores voluptates quam illum consequatur nemo est dolores.</p>
</div>
</li>
<li>
<div class="box"
>
<h3><i class="fas fa-chevron-right"></i> 2013: Node.js & React</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque animi at, dolorum tempora labore exercitationem sapiente voluptate possimus necessitatibus quos cum, voluptatibus maiores voluptates quam illum consequatur nemo est dolores.</p>
</div>
</li>
<li>
<div class="box">
<h3><i class="fas fa-chevron-right"></i> 2014: Angular & React Native</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque animi at, dolorum tempora labore exercitationem sapiente voluptate possimus necessitatibus quos cum, voluptatibus maiores voluptates quam illum consequatur nemo est dolores.</p>
</div>
</li>
<li>
<div class="box">
<h3><i class="fas fa-chevron-right"></i> 2015: Vue.js </h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque animi at, dolorum tempora labore exercitationem sapiente voluptate possimus necessitatibus quos cum, voluptatibus maiores voluptates quam illum consequatur nemo est dolores.</p>
</div>
</li>
<li>
<div class="box">
<h3><i class="fas fa-chevron-right"></i> 2016:GraphQL & Apollo</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque animi at, dolorum tempora labore exercitationem sapiente voluptate possimus necessitatibus quos cum, voluptatibus maiores voluptates quam illum consequatur nemo est dolores.</p>
</div>
</li>
<li>
<div class="box">
<h3><i class="fas fa-chevron-right"></i> 2017: Machine Learning</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque animi at, dolorum tempora labore exercitationem sapiente voluptate possimus necessitatibus quos cum, voluptatibus maiores voluptates quam illum consequatur nemo est dolores.</p>
</div>
</li>
</ul>
</section>
Upvotes: 2
Reputation: 20944
In the example you gave the .box
elements would not be intersecting because they are out of the viewport. This is due to the transform
property on these elements which places them outside of the view. Removing the transform
properties would fix it. You can tackle this by adding another div inside the .box
element which is transformed outside of the view. This way the parent (.box
) is observed and in the view and the child of .box
is transform outside and can be animated back whenever .box
is intersecting.
The .fade
class is not working because of the specificity on the the .box
divs. #timeline ul li div
is far more specific than .fade
and thus .fade
will always be overwritten by the id selector of #timeline ul li div
. To tackle this either make your selectors less specific by using .box { ... }
and .box.fade { ... }
or add the .fade
to the specific selector like so: #timeline ul li div.fade
.
Also, avoid creating an instance of an IntersectionObserver
for each element. A single observer can observe multiple elements. Multiple instances should only be created if the callback
argument varies.
In your case, all .box
elements have to be handled the same.
const targets = document.querySelectorAll('.box');
const onObserve = (entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const div = entry.target;
div.classList.add('fade');
observer.unobserve(div);
}
});
}
const io = new IntersectionObserver(onObserve);
const observeTargets = targets => targets.forEach(target => {
io.observe(target);
});
observeTargets(targets);
:root {
--primary-color: #425b84;
--secondary-color: #5b7bb4;
--max-width: 1100px;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font: normal 1rem/1.5 'Arial', sans-serif;
background: var(--primary-color);
color: #fff;
overflow-x: hidden;
padding-bottom: 50px;
}
#main-header {
background: var(--secondary-color);
padding: 4rem 0;
}
.container {
max-width: var(--max-width);
margin: 0 auto;
text-align: center;
}
h1 {
font-size: 2.3rem;
}
#timeline ul {
background: var(--primary-color);
padding: 50px 0;
}
/* Create Line */
#timeline ul li {
list-style: none;
position: relative;
width: 6px;
margin: 0 auto;
padding-top: 50px;
background: #fff;
}
/* Boxes */
#timeline ul li div {
position: relative;
bottom: 0;
width: 400px;
padding: 1rem;
background: var(--secondary-color);
transition: all 0.5s ease-in-out;
opacity: 0;
}
#timeline ul li div.fade {
opacity: 1;
transition: all 0.5s ease-in-out;
transform: translateX(0);
}
/* Right Side */
#timeline ul li:nth-child(odd) div {
left: 40px;
/* transform: translateX(1100px); */
}
/* Left Side */
#timeline ul li:nth-child(even) div {
left: -434px;
/* transform: translateX(-1100px); */
}
/* Dots */
#timeline ul li:after {
content: '';
position: absolute;
left: 50%;
bottom: 0;
width: 25px;
height: 25px;
background: var(--secondary-color);
transform: translateX(-50%);
border-radius: 50%;
transition: background 0.5s ease-in-out;
}
/* Arrows Base */
#timeline div:before {
content: '';
position: absolute;
bottom: 5px;
width: 0;
height: 0;
border-style: solid;
}
/* Right Side Arrows */
#timeline ul li:nth-child(odd) div:before {
left: -15px;
border-width: 8px 16px 8px 0;
border-color: transparent var(--secondary-color) transparent transparent;
}
/* Left Side Arrows */
#timeline ul li:nth-child(even) div:before {
right: -15px;
border-width: 8px 0 8px 16px;
border-color: transparent transparent transparent var(--secondary-color);
}
@media(max-width:900px) {
#timeline ul li div {
width: 250px;
}
#timeline ul li:nth-child(even) div {
left: -284px;
}
}
@media(max-width:600px) {
#timeline ul li {
margin-left: 20px;
}
#timeline ul li div {
width: calc(100vw - 90px);
}
#timeline ul li:nth-child(even) div {
left: 40px;
}
/* Right Side Arrows */
#timeline ul li:nth-child(even) div:before {
left: -15px;
border-width: 8px 16px 8px 0;
border-color: transparent var(--secondary-color) transparent transparent;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://kit.fontawesome.com/bbb16afe05.js" crossorigin="anonymous"></script>
<link rel="stylesheet" href="./css/aos.css">
<link rel="stylesheet" href="./css/style.css">
<title>Knowledge Timeline</title>
</head>
<body>
<header id="main-header">
<div class="container">
<h1><i class="fas fa-brain"></i> Knowledge Resume</h1>
<h3>
<div class="fas fa-user"></div> Jun Jung</h3>
</div>
</header>
<section id="timeline">
<ul>
<li>
<div class="box">
<h3><i class="fas fa-chevron-right"></i> 2007: HTML & CSS</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque animi at, dolorum tempora labore exercitationem sapiente voluptate possimus necessitatibus quos cum, voluptatibus maiores voluptates quam illum consequatur nemo est dolores.</p>
</div>
</li>
<li>
<div class="box">
<h3><i class="fas fa-chevron-right"></i> 2009: JavaScript & jQuery</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque animi at, dolorum tempora labore exercitationem sapiente voluptate possimus necessitatibus quos cum, voluptatibus maiores voluptates quam illum consequatur nemo est dolores.</p>
</div>
</li>
<li>
<div class="box">
<h3><i class="fas fa-chevron-right"></i> 2010: PHP & Wordpress</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque animi at, dolorum tempora labore exercitationem sapiente voluptate possimus necessitatibus quos cum, voluptatibus maiores voluptates quam illum consequatur nemo est dolores.</p>
</div>
</li>
<li>
<div class="box">
<h3><i class="fas fa-chevron-right"></i> 2011: Ruby on Rails</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque animi at, dolorum tempora labore exercitationem sapiente voluptate possimus necessitatibus quos cum, voluptatibus maiores voluptates quam illum consequatur nemo est dolores.</p>
</div>
</li>
<li>
<div class="box">
<h3><i class="fas fa-chevron-right"></i> 2012: Python</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque animi at, dolorum tempora labore exercitationem sapiente voluptate possimus necessitatibus quos cum, voluptatibus maiores voluptates quam illum consequatur nemo est dolores.</p>
</div>
</li>
<li>
<div class="box">
<h3><i class="fas fa-chevron-right"></i> 2013: Node.js & React</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque animi at, dolorum tempora labore exercitationem sapiente voluptate possimus necessitatibus quos cum, voluptatibus maiores voluptates quam illum consequatur nemo est dolores.</p>
</div>
</li>
<li>
<div class="box">
<h3><i class="fas fa-chevron-right"></i> 2014: Angular & React Native</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque animi at, dolorum tempora labore exercitationem sapiente voluptate possimus necessitatibus quos cum, voluptatibus maiores voluptates quam illum consequatur nemo est dolores.</p>
</div>
</li>
<li>
<div class="box">
<h3><i class="fas fa-chevron-right"></i> 2015: Vue.js </h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque animi at, dolorum tempora labore exercitationem sapiente voluptate possimus necessitatibus quos cum, voluptatibus maiores voluptates quam illum consequatur nemo est dolores.</p>
</div>
</li>
<li>
<div class="box">
<h3><i class="fas fa-chevron-right"></i> 2016:GraphQL & Apollo</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque animi at, dolorum tempora labore exercitationem sapiente voluptate possimus necessitatibus quos cum, voluptatibus maiores voluptates quam illum consequatur nemo est dolores.</p>
</div>
</li>
<li>
<div class="box">
<h3><i class="fas fa-chevron-right"></i> 2017: Machine Learning</h3>
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Cumque animi at, dolorum tempora labore exercitationem sapiente voluptate possimus necessitatibus quos cum, voluptatibus maiores voluptates quam illum consequatur nemo est dolores.</p>
</div>
</li>
</ul>
</section>
<script src="./js/main.js"></script>
</body>
</html>
Upvotes: 1