DEV Community

Thaísa Vieira
Thaísa Vieira

Posted on • Edited on

NFT Preview Card Component Challenge from Frontend Mentor

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.

  • Desktop design:
    Desktop design

  • Mobile design:
    Mobile design

  • Active state design:
    Active state design

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:

Design divided 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>
Enter fullscreen mode Exit fullscreen mode

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%);
}
Enter fullscreen mode Exit fullscreen mode

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%)
Enter fullscreen mode Exit fullscreen mode

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);
  }
Enter fullscreen mode Exit fullscreen mode

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>

Enter fullscreen mode Exit fullscreen mode
  • Author's name
        <p class="author">Creation of <span>Jules Wyvern</span></p>

Enter fullscreen mode Exit fullscreen mode

The hover effect:

 .title:hover, footer span:hover{
    color: var(--primary-medium);
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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;
}

Enter fullscreen mode Exit fullscreen mode
.container .image-link:hover::before{
    opacity: 0.4;
    border-radius: 1rem;
}
Enter fullscreen mode Exit fullscreen mode

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;
}
Enter fullscreen mode Exit fullscreen mode

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)

Collapse
 
swaraj_singh__ profile image
Swaraj Singh ⚛️

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")!

Collapse
 
thaisavieira profile image
Thaísa Vieira

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.

Collapse
 
thomascansino profile image
Thomas Cansino

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 :)

Collapse
 
thaisavieira profile image
Thaísa Vieira

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