Introduction
During the three-day weekend, I made a fitness website that's responsive to most devices, it took me a while but, in the end, I'm happy with the outcome. So, in this blog, I'll show you how I made it by explaining each part of the website. If you have any questions, you can comment below. Below this introduction is a codepen for a preview of what the website looks like, but to see it fullscreen go here: fullcreen link.
Table of contents
- Responsive nav bar
- Intro section
- Course Grid
- Custom Graph
- Blog Section
- Review Section
- Footer Nav
- Slide In Transition
-
Conclusion
Responsive Nav
First, we make an icon (which I got from ion-icons) and a nav element where in the nav are paragraphs.
<ion-icon name="menu-outline" class="menu"></ion-icon>
<nav>
<p><ion-icon name="barbell-outline"></ion-icon>Fitco</p>
<p>Home</p>
<p>Prices</p>
<p>About</p>
<p>Courses</p>
<p>Blog</p>
</nav>
- With CSS we use flex to make the nav bar horizontal then we give it a
width
of100%
and aheight
of5%
so it doesn't cover the whole website but stretches across it. We center everything with
align-items
andjustify-content
set tocenter
, then give the nav abackground-color
ofred
.For the elements in the nav we give their after pseudo-element a transition where the
width
goes from0
to100%
when it's hovered making a smooth underline animation (to make it more noticeable I gave it a border when it's hovered).Finally, we give the nav a
position
offixed
and a high z-index so it always stays on top of the screen. For now, we'll set the menu icon'sdisplay
tonone
since we don't need it right now.
nav {
display: flex;
width: 100%;
gap: 10%;
align-items: center;
justify-content: center;
z-index: 4;
height: 5%;
border: solid;
position: fixed;
background-color: red;
font-family: "Gill Sans", "Gill Sans MT", Calibri, "Trebuchet MS", sans-serif;
}
nav > p {
cursor: pointer;
}
nav > p::after {
content: "";
width: 0px;
transition: 0.3s;
display: block;
background-color: black;
}
nav > p:hover::after {
width: 100%;
border: solid 1px black;
}
Now we need to make it responsive, we'll make a media query where the nav's display is set to none and the menu is visible when the width of the website is under 580 pixels.
@media (max-width: 580px) {
.menu {
display: block;
/*just stylizing the icon ^_^*/
position: fixed;
color: white;
font-size: 50px;
background-color: red;
border-radius: 5px;
left: 10px;
cursor: pointer;
z-index: 3;
}
nav {
display: none;
}
}
Next, we make a custom class for the mobile version of the nav. In it we use the inset property to make it cover up the right side of the page, we'll also set the flex-direction
to column
so all of the content is vertical. Finally, we set the align-items
property to flex-start
so we can see the nav content and a position
of fixed
with a width of 100% so it can always stretch vertically across the website.
.mobil_navbar {
display: flex;
flex-direction: column;
align-items: flex-start;
inset: 0 0 0 60%;
position: fixed;
height: 100%;
gap: 10%;
}
/*To center the text*/
.navbar > p {
margin-left: 70px;
}
Now we just need JavaScript so whenever we click the menu, the mobile navbar will pop up. All we need to do is give the menu an event listener where when it's clicked the nav element will toggle the mobile navbar class to itself.
var menu = document.querySelector('.menu');
var nav = document.querySelector('nav');
menu.addEventListener('click', function () {
nav.classList.toggle('mobil_navbar');
})
Results
Intro section
In the intro section there's a header, pragraph element, and button element inside a div.
<section class="Intro">
<div>
<h1>Keep your body fit any time, all the time</h1>
<p>With fitco, you can always exrcise and track your journey to reach your body goals</p>
<button>Learn More</button>
</div>
</section>
We gave the section a display of flex to align the items onto the center horizontally. We'll make the div small to squeeze all of the content in and make sure it doesn't spread out. Finally, we give the section a background image which I got from Unsplash. For the button, we give it a transition where the colors switch when it's hovered on.
.Intro {
background-image: url("https://images.unsplash.com/photo-1517836357463-d25dfeac3438?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1170&q=80");
color: white;
/* background-size's cover value is important to make the
background-image actually cover the section*/
background-size: cover;
font-family: "Poppins";
display: flex;
align-items: center;
font-size: 30px;
height: 40rem;
}
.Intro > div {
width: 30rem;
}
/*Stylizing the button*/
.Intro > div > button {
height: 40px;
cursor: pointer;
background-color: transparent;
color: white;
border: solid white;
border-radius: 5px;
transition: 0.3s;
}
.Intro > div > button:hover {
color: black;
background-color: white;
}
Course grid
Inside the lesson section, we make a div with a class called courses that contains the lesson_container. The lesson_container has six div's inside that'll be our grid.
<div class="courses">
<h2 class="hidden">Popular courses</h2>
<div class="lesson_container hidden">
<div class="lesson_card"></div>
<div class="lesson_card"></div>
<div class="lesson_card"></div>
<div class="lesson_card"></div>
<div class="lesson_card"></div>
<div class="lesson_card"></div>
</div>
</div>
With CSS make the lesson_container a 3-column grid. For the divs in the lesson_container, which we call the lesson_cards, they'll be a 200px square. We give the lesson_card's a height transition and make a psuedo-class for it where when it hovered the height grows. To give each lesson_card a title I position all of their before psuedo-elements below and give them each a specific title. Finally, I give each lesson_card a different background image to match its title.
.lesson_container {
display: grid;
grid-template-columns: repeat(3, 1fr);
column-gap: 30px;
row-gap: 60px;
}
.lesson_card {
border-radius: 10px;
display: flex;
align-items: center;
justify-content: center;
transition: height 0.5s, brightness 0.3s;
background-size: cover;
border: solid;
width: 200px;
height: 200px;
cursor: pointer;
}
.lesson_card:hover {
height: 350px;
}
/* I won't show the background image for each image to
reduce the amount of code in this, but just know there's
5 more selectors like the one below*/
.lesson_card:nth-child(1) {
background-image: url("https://images.unsplash.com/photo-1603503364272-6e28e046b37a?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=388&q=80");
}
.lesson_card:before {
content: '';
position: relative;
top: 135px;
}
.lesson_card:after {
display: none;
}
.lesson_card:hover:after {
display: block;
margin-right: 80px;
}
.lesson_card:nth-child(1):before {
content: 'Upper body warmup';
}
/*Once again I'm not going to show all of the selectors
to make this shorter, so look for the 5 other titles from the Codepen or the full screen website*/
Results
Custom graph
To make the custom graph in the tracking section we first make a div with a class name called graph and seven div's inside it. Now with CSS, we give the graph a background image that makes it looks like a graph and a display
of grid
to make the div's inside it vertical. We now separate the div's by setting the graph's gap
to 10px
. Finally, we give the div's different widths, and there! we now have our graph. The last problem we have is that it's sideways, but all we have to do is rotate the graph 90 degrees using transform: rotate(90deg);
.
.graph {
display: grid;
border: solid;
width: 400px;
height: 400px;
gap: 10px;
transform: rotate(-90deg);
background-image: url()/*Im not going to put
the actual URL here, since it's WAY too big*/;
}
.graph > div {
background-color: red;
}
Results
Blog section
I made my three examples in my blog section by putting them in a div called blog_container. It uses flex to put them in a row, but using a media query I made it so that when the width of the website is small one of them is taken away. I also gave them a hover effect where the background changes. I use grid inside each blog to make the content vertical and center the text with text-align: center
while centering everything in the blog with place-items: center
.blog_container {
display: flex;
gap: 40px;
}
.blogs {
border-radius: 10px;
display: grid;
place-items: center;
text-align: center;
width: 220px;
padding: 30px;
}
.blogs:hover {
background-color: #4a4e69;
}
Results
Review section
- A two-column grid with one being an image and the other containing a div that changes the font size every time the width gets smaller.
.reviews {
display: grid;
grid-template-columns: 40% auto;
place-items: center;
font-family: 'Poppins';
height: 30rem;
}
.reviews > div {
height: 15rem;
background-color: #1d3557;
border-radius: 10px;
}
.reviews > div > p {
font-size: 15px;
}
@media (max-width: 651px) {
.reviews > .quote > p {
font-size: 13px;
}
}
@media (max-width: 465px) {
.reviews > .quote > p {
font-size: 12px;
}
}
Results
Footer Nav
The footer nav uses flex to space out the logo and two lists evenly. Each list item in the unordered lists have a hover effect where they turn blue.
HTML
<footer class="about">
<h2 style="text-decoration: none;">
<ion-icon name="barbell-outline"></ion-icon>Fitco
</h2>
<ul class="contacts">
<li>About us</li>
<li>Twitter</li>
<li>Facebook</li>
<li>Jobs</li>
<li>Offers</li>
</ul>
<ul class="contacts">
<li>Lensco</li>
<li>Blog</li>
<li>Github rep</li>
<li>Twitter</li>
</ul>
</footer>
CSS
.about {
display: flex;
justify-content: space-around;
font-family: 'Poppins';
align-items: center;
}
.contacts {
list-style-type: none;
display: grid;
column-gap: 20px;
}
li {
cursor: pointer;
}
li:hover {
color: blue;
}
Results
Slide in transition
With CSS we make a hidden and show class. The hidden class will have an opacity of 0 and is translated on the X-axis by -100%. The show class is the opposite, with an opacity of 1 and no translation.
.hidden {
opacity: 0;
transform: translateX(-100%);
transition: 1s;
}
.show {
opacity: 1;
transform: translateX(0);
}
Next, we give the elements we want to have the transition to the hidden class. With JavaScript, we collect all those elements and put them in a variable. We then use the Intersection Observer API function so when something intersects the viewport it'll have the show class added, but if it isn't it'll be removed. We assign the function to all the hidden class elements, and there you have it! You can give it a transition to make it look better.
var hidden = document.querySelectorAll('.hidden');
const observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add("show");
} else {
entry.target.classList.remove("show");
}
});
});
hidden.forEach((el) => observer.observe(el));
Results
Conclusion
Even though this may have been the best-looking project I've made, I still need better practice when it comes to making websites responsive. Notice that for the nav part, I did it in bulletins to make it a bit shorter, if you liked it, should I continue using bulletins for my blogs? Anyways I hope this blog helped you or inspired you, and next week I'll be making an E-commerce website, so follow me for more! Have a great Day!
Top comments (1)
Hi, interesting post, thanks for sharing your experience!
I also recommend reading the article on the Gapsy studio blog, which provides practical advice on creating a design for a fitness website and explains why design is important for a website in this industry.