Have you ever heard about Frontend Mentor? It's a website where you can improve your coding skills by building real-world projects professionally designed to help students of all levels practice HTML, CSS, and JavaScript. Also, since you made the challenge as close as the desired design you can use all the tools you like. Learning a new library? Testing your knowledge in fundamentals? Frontend Mentor is the right place to challenge yourself.
While in my studies I always keep something in mind:
"You can't cross the sea merely by standing and staring at the water" - Rabindranath Tagore
So, that is why Frontend Mentor is important in my weekly study schedule.
About the challenge
The NFT Preview Card Component is a challenge with HTML and CSS only, very indicated for newbies and beginners who want to test their skills with semantic HTML and flexbox CSS, also it's has a very important detail with a hover effect in the product image that will be discussed forward.
For this challenge, the goal is to build this preview card component and get it as close to the design as possible.
It's important to remember that the Sketch and Figma design file access can be unlocked with Frontend Mentor PRO (clicking on this link you can read more about it), these files contain things like the size of padding, margins, fonts, and image. Unfortunately, I don't have the PRO, so everything I have done was with the PerfectPixel extension from Chrome/Brave.
My first step, as always, was to divide the design into smaller parts:
For building this, I use simple things like Paint but the most important idea is to "see" those blocks, avoiding the anxiety of coding without thinking.
The first thing we have is a container, which will be our main section. Inside this container, we will have an image, a title, a subtitle, a price, and a "countdown" in a row, a single line, a profile image, and the name of the author with some text in a row. The hover effect is present in the "product" image, title, and in the author's name.
Note that to position the elements like the container, price, countdown, and profile image with the author's name we will use the flexbox propriety.
Here we have the HTML structure:
<body>
<main>
<div class="container">
<picture class="product">
<a href="#" class="image-link"><img src="./src/images/image-equilibrium.jpg" alt="Equilibrium ilustrated" class = "image"></a>
</picture>
<h1 class="title">Equilibrium #3429</h1>
<h2 class="description">Our Equilibrium collection promotes balance and calm.</h2>
<div class="relevant-data">
<p class="price"> <img src="src/images/icon-ethereum.svg" alt="Ethereum icon"> 0.041 ETH</p>
<p class="time-left"> <img src="src/images/icon-clock.svg" alt="Clock icon">3 days left</p>
</div>
<hr>
<footer>
<picture>
<img src="src/images/image-avatar.png" alt="Author profile picture" class="profile-picture">
</picture>
<p class="author">Creation of <span>Jules Wyvern</span></p>
</footer>
</div>
<div class="attribution">
Challenge by <a href="https://www.frontendmentor.io?ref=challenge" target="_blank">Frontend Mentor</a>.
Coded by <a href="https://github.com/thaisavieira">Thaísa Vieira</a>.
</div>
</main>
</body>
Before we go to the CSS structure let's declare some variables on a separate file called variables.css
:
:root{
--primary-soft: hsl(215, 51%, 70%);
--primary-medium:hsl(178, 100%, 50%);
--neutral-dark:hsl(217, 54%, 11%);
--neutral-dark-medium:hsl(216, 50%, 16%);
--neutral-soft:hsl(215,32%,27%);
--white: hsl(0, 0%, 100%);
}
When we download a new project/challenge on Frontend Mentor we already have some other variable names, like:
- Very dark blue (main BG): hsl(217, 54%, 11%)
- Very dark blue (card BG): hsl(216, 50%, 16%)
- Very dark blue (line): hsl(215, 32%, 27%)
- White: hsl(0, 0%, 100%)
But if Frontend Mentor gives some variables names, why create other ones? The main idea is, in case the designer/client wants to change colors it'll be easier.
And the CSS struture:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html{
font-size: 62.5%;
}
body {
font-family: "Outfit", sans-serif;
background-color: var(--neutral-dark);
}
main{
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.container{
width: 35rem;
height: 58rem;
border-radius: 1.5rem;
background-color: var(--neutral-dark-medium);
box-shadow: 0 1rem 3rem rgba(0, 0, 0, 0.5);
display: flex;
flex-direction: column;
justify-content: center;
padding: 2rem;
gap: 2rem;
}
.title{
font-size: 2.3rem;
font-weight: 400;
color: var(--white);
cursor: pointer;
}
.description{
font-size: 1.8rem;
letter-spacing: 0.15rem;
font-weight: 400;
color: var(--primary-soft);
}
.relevant-data{
display: flex;
flex-direction: row;
justify-content: space-between;
}
.price{
color: var(--primary-medium);
font-weight: 500;
font-size: 1.6rem;
display: flex;
align-self: baseline;
gap: 0.5rem;
}
.time-left{
color: var(--primary-soft);
font-size: 1.6rem;
display: flex;
align-self: baseline;
gap: 0.5rem;
}
hr{
border-color: var(primary-soft);
}
footer{
display: flex;
flex-direction: row;
align-items: center;
gap: 1.5rem;
color: var(--primary-soft);
font-size: 1.6rem;
}
footer span{
color: var(--white);
cursor: pointer;
}
.profile-picture{
height: 2.6rem;
}
.attribution {
font-size: 1.1rem;
text-align: center;
padding-top: 2rem;
color: var(--white);
}
.attribution a {
color: var(--cyan);
}
And now, it's time to focus on the active state parts.
The hover effect
The hover effect is made by the :hover
CSS selector and is used to select elements when you mouse over them and the element responds with transition effects. That's a great way to enhance the user experience. Here's a CodePen example.
First, we will look again at the title and the author's name.
- Product title
<h1 class="title">Equilibrium #3429</h1>
- Author's name
<p class="author">Creation of <span>Jules Wyvern</span></p>
The hover effect:
.title:hover, footer span:hover{
color: var(--primary-medium);
}
The :hover
pseudo-class is triggered when the user hovers over the element with the pointer and it changes the appearance of the element while it is being used. This is a pretty simple part (note that I used the word simple and not easy!).
About the Equilibrium image effect
Now, let's look at the class .image-link
. When the user hovers over the Equilibrium image it changes to image opacity, adds a background color, and shows an icon on top of the product image, so it's a little bit more complex than our last case.
To divide this task into smaller parts I asked some questions myself:
Question 1: What's the content I wanna to insert?
Answer 1: The view icon.Question 2: Is the icon the only thing I need to add?
Answer 2: No, I need to change the background color too.Question 3: How do I need to it show up in the design? What'll happen to the original image?
Answer 3: I need the original image "stay behind", to appear and disappear smoothly when the user hovers over the element.
Starting with basic styles:
(Attention to specificity!)
.container .image-link{
position: relative;
display: flex;
cursor: pointer;
}
.container .image-link .image{
width: 100%;
border-radius: 1rem;
}
Let's analyze these proprieties.
In the "first div", we have the position: relative
which allows the element to change the position, accepting values as top, bottom, left... Also, we have the display: flex
propriety to align the element. Now, when we look at the "second div" we are talking about the inner part, the image itself, so we will need the image covering all the div (.image-link) width and a border radius for rounding corners of the image.
To create the effect we want we will need:
- .container .image-link::before;
- container .image-link:hover::before;
- .container .image-link::after;
- container .image-link:hover::after.
Are you familiar with pseudo-elements? You can check a short and useful explanation on CSS-Tricks and also try to play a bit with this project on CodePen, it may help to understand what each property do.
Starting with .container .image-link::before
:
.container .image-link::before{
content: '';
background-color: var(--primary-medium);
width: 100%;
height: 100%;
position: absolute;
opacity: 0;
transition: 0.3s ease-in-out;
}
.container .image-link:hover::before{
opacity: 0.4;
border-radius: 1rem;
}
So in this part, we have our element .image-link
and we want to add the color when the user hovers and disappears slowly after it.
We start with .container .image-link::before
where we had the content property which is used with ::before
and ::after
pseudoelements to generate content in an element, in our case, we only want a new color. Properties like height
and width
are used to adjust the size of the new background color on the image.link
div. Now, it's important to understand the main idea with the opacity
, on the W3 website it's possible to see some practical examples of how opacity numbers can affect an image. For our situation, an opacity of 0 will give us an image transparent but when we see the .container .image-link:hover::before
we have an opacity: 0.4;
which means that we will be able to see the image but with a little bit of transparency. The lower the value, the more transparent.
Now, let's work on the most difficult part for me, the icon hover.
{
content: '';
background: url(../images/icon-view.svg);
background-position: center;
background-repeat: no-repeat;
position: absolute;
width: 100%;
height: 100%;
opacity: 0;
transition: 0.3s ease-in-out;
}
.container .image-link:hover::after{
opacity: 1;
}
Before we start it's important to review your folder paths, an error on the URL background can make you burn some nerves no need. If you're facing something like the icon only pops up locally but when you deploy on GitHub Pages it disappears, it's quite sure the URL is the problem.
When we work with .image-link::after
we have the content + background responsible for adding the image, also proprieties like background-position
and background-repeat
are important for letting our project with a single image well positioned, like the design. And to finish we had our opacity and transition, one for working with transparency and the other for letting things smooth.
It's my first time writing such a "long" post like this talking about my experience (with strong points, doubts, and difficulties) and I'd like to know if it is possible to make it clearer and how to make it even better.
Also, you can check the project here:
Repository: https://github.com/thaisavieira/nft-preview-card-component
Live website: https://thaisavieira.github.io/nft-preview-card-component/
Frontend Mentor profile: https://www.frontendmentor.io/profile/thaisavieira
Top comments (4)
Whoa! Bravo, @thaisavieira I find this to be really interesting! I would recommend that you also showcase this post on Twitter (now known as "X")!
Thanks, Swaraj Singh! I'll sure do that, while doing this challenge I only found a few posts about it and on Frontend Mentor Discord a lot of people are having some difficulty with this challenge.
I've been searching for this kind of website for weeks now where I get to build something and actively learn things! Thank you for the recommendation! I'll definitely try this frontend mentor :)
I'm sure you will love this website more than I do, it's great to practice and they even have a Discord community, a safe space for doubts and co-working too