NFT Preview Card Component Challenge from Frontend Mentor
Tags: webdev, beginners, tutorial, frontend
Published: 2024-05-01 23:00:45

Have you ever heard about [Frontend Mentor](https://www.frontendmentor.io/)? 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](https://www.frontendmentor.io/challenges/nft-preview-card-component-SbdUL_w0U) 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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bcb2hmkbzibit5jy3hyt.png)

- Mobile design:
![Mobile design](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/efhn3jqc7q4snp4lk9bn.png)

- Active state design:
![Active state design](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1a2jv59wwxc9m5qqq5ib.png)


It's important to remember that the Sketch and Figma design file access can be unlocked with Frontend Mentor PRO (clicking on [this link](https://www.frontendmentor.io/pro) 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](https://chromewebstore.google.com/detail/perfectpixel-by-welldonec/dkaagdgjmgdmbnecmcefdhjekcoceebi?hl=en) extension from Chrome/Brave.

My first step, as always, was to divide the design into smaller parts:


![Design divided into smaller parts](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/adz5swtshw37gu2fkixx.png)

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](https://codepen.io/argyleink/pen/poEjvpd) 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](https://css-tricks.com/almanac/selectors/a/after-and-before/) and also try to play a bit with [this project on CodePen](https://codepen.io/tigercodes/pen/ExNdbgv), 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](https://developer.mozilla.org/pt-BR/docs/Web/CSS/content) 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](https://www.w3schools.com/css/css_image_transparency.asp) 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