Profile Card challenge - frontendmentor.io
Tags: css, codenewbie, html, webdev
Published: 2021-09-21 11:03:58

Hello my Beautiful Friends on the Internet!🙋🏻‍♀️

This is a solution to the [Profile card component challenge on Frontend Mentor](https://www.frontendmentor.io/challenges/profile-card-component-cfArpWshJ). Frontend Mentor challenges help you improve your coding skills by building realistic projects. 

This is a perfect challenge to test your layout skills. The card layout doesn't shift, so it's also great for those that haven't dived into responsive websites yet!

## Table of contents

- [Overview](#overview)
  - [The challenge](#the-challenge)
  - [Screenshot](#screenshot)
  - [Links](#links)

- [My process](#my-process)
  - [Built with](#built-with)
  - [What I learned](#what-i-learned)
  - [Useful resources](#useful-resources)

- [CSS explanation](#css-explanation)
  - [Variables](#variables)
  - [Background](#background)
  - [Card](#card)
  - [Animation](#animation)

- [Author](#author)


## Overview

### The challenge

The challenge is to build out this profile card component and get it looking as close to the design as possible. I am free to use any tools I like to complete the challenge. 


### Screenshot
![Desktop Interface](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qcz52jp8rp1oqodpkxia.jpg)![Mobile Interface](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hq7e1zync9rvo7c3lm8m.jpg)

### Links

- Solution URL: [solution-link](https://github.com/lismaria/FM1-ProfileCardComponent)
- Live Site URL: [site-link](https://lismaria.github.io/FM1-ProfileCardComponent/)


## My process

### Built with

- Semantic HTML5 markup
- CSS custom properties
- CSS Flexbox
- CSS Grid
- CSS Animations

### What I learned

#### It's always a good idea to sketch 🥇
> Before starting off with the CSS, I sketched the design pretty roughly using pen and paper. Then I drew lines so as to get a better understanding of which layout algorithm might suit the best. I came up with 2 approaches. There came a point where I literally got stuck with my first approach so I knew which part of the second approach is gonna help me now. There are endless ways in which sketching the design will come handy. You should definitely give it a go!

#### Heading levels should only increase by one

> A heading level following an `h1` element should be an `h2` element, not an `h3` element. Why this matters? Well for sighted users, the different font sizes distinguish the hierarchy for us. The same is not helpful for screen readers. The screen reader identifies a  properly marked-up header hence applying the `h1` to `h6` hierarchically makes it easier to navigate.[click here to know more](https://dequeuniversity.com/rules/axe/4.2/heading-order)

#### Document should have one main landmark

>  In HTML5, you should use elements like `header`, `nav`, `main`, and `footer`. Once added, screen reader users can navigate to a section based on its ARIA landmark or HTML element. [click here to know more](https://dequeuniversity.com/rules/axe/4.2/region)

#### CSS naming convention exists!

>BEM which stands for Block, Element, and Modifier is a CSS naming convention for writing cleaner and more readable CSS classes. Though I might not have literally used this, it's okay for the first time. [click here to know more](https://codeburst.io/understanding-css-bem-naming-convention-a8cca116d252)

```css
/* Blocks are named as standard CSS classes */
.block { }

/* Elements declared with 2 underscores, after block */
.block__element { }

/* Modifiers declared with 2 dashes, after block or element */
.block--modifier { }

/* Block, element and modifier together */
.block__element--modifier { }
```

### Useful resources

- [Background-Position](https://css-tricks.com/almanac/properties/b/background-position/) - One of the most challenging part was to place the circles in the background. This post was life saver! Couldn't recommend enough.
- [Pixel vs rem](https://www.youtube.com/watch?v=dHbYcAncAgQ) - This is an amazing YouTube video from _Coder Coder_ which helped me finally understand rem unit. I'd recommend it to anyone still learning this concept.
- [CSS Grid Tutorial](https://www.youtube.com/watch?v=x7tLPhnA06w&list=PL4cUxeGkcC9itC4TxYMzFCfveyutyPOCY) & [CSS Flexbox Tutorial](https://www.youtube.com/watch?v=Y8zMYaD1bz0&list=PL4cUxeGkcC9i3FXJSUfmsNOx8E7u6UuhG) - _The Net Ninja_ is my go to channel for almost any web development related stuff. 
- [CSS Variables](https://www.youtube.com/watch?v=oZPR_78wCnY) - _Web Dev Simplified_ is another great channel. He simplifies every concept and learning is so beginner level. 
- [BEM: Block-Element-Modifier](https://codeburst.io/understanding-css-bem-naming-convention-a8cca116d252) - I was unaware of this convention. Tried for the first time!
- [CSS Animations](https://www.youtube.com/watch?v=YszONjKpgg4) - Wanna start of with CSS animations? Check this out. [If you have time follow this playlist](https://www.youtube.com/watch?v=jgw82b5Y2MU&list=PL4cUxeGkcC9iGYgmEd2dm3zAKzyCGDtM5)

## CSS explanation
### Variables

Also known as _CSS Custom Properties_ or _cascading variables_ contain specific values that are to be reused throughout the document.
  - Property name is begins with double hyphen `--` and the property value can be any css valid value. Eg: `--main-bg: #c4c4c4;`
  - We use the custom property by specifying the name inside `var()` function instead of regular property value. Eg: `background-color: var(--main-bg)`
  - It's a common best practice to define custom properties on the `:root` _pseudo-class_. This enables us to apply it globally across the HTML doc.

```css
:root{
    /* Primary */
    --cyanD: hsl(185, 75%, 39%);
    --Dblue: hsl(229, 23%, 23%);
    --Gblue: hsl(227, 10%, 46%);

    /* Neutral */
    --Dgray: hsl(0, 0%, 59%);

    font-size: 62.5%; /* 1 rem = 10px */
}
```
You must have notice I have set the font-size to 62.5%. Well what this exactly means is, 62.5% of the default font-size of the browser which is usually 16px. This gives me 10px which makes it easier to convert pixel into rems. Before 1rem = 16px and now 1rem = 10px.

### Background
- I have set the body dimensions to 100% viewport width and height and overflow to hidden so that it hides of the stuff that don't fit in (else a scrollbar might appear).
- I have applied _CSS grid_ on this element so as to center the card as this is its parent.
- I have commented out the background image and position of the circles as I want them to animate in so substituted the values there.
    - The url of both the circles is comma-separated and put in the value of `background-image` property. This will place both the circle as the background image.
    - Similarly for the `background-position` I have put the two values which will respectively position the circles.
      - `top -65vh right 50vw` will place the top circle 35% of viewport height from the bottom and place it 50% of viewport width from the right.
      - `top 50vh left 50vw;` will place the bottom circle 50% from the top and 50% from the left.
```css

body{
    animation: 2s circles ease-out forwards;
    background: var(--cyanD);
    /* background-image: url(/images/bg-pattern-top.svg), url(/images/bg-pattern-bottom.svg); */
    /* background-position: top -65vh right 50vw, top 50vh left 50vw; */
    background-repeat: no-repeat, no-repeat;
    overflow: hidden;
    height: 100vh;
    display: grid;
    place-items: center;
    position: relative;
}
```

### Card
The card has a background-color white and a border radius of around 15px. The dimension of the card is roughly 350 x 390 px. It also has a box-shadow.
I decided to use **CSS Grid layout** to position the child elements. To start of I created 5 rows of equal height. `grid-template-rows: repeat(5,1fr);`
```css
.card {
    background-color:  #fff; 
    width: 100%;
    max-width: 35rem;
    height: 100%;
    max-height: 39rem;
    border-radius: 15px;
    display: grid;
    grid-template-rows: repeat(5,1fr);
    box-shadow: 0px 50px 100px -20px rgba(8, 70, 94, 0.5);
}
```
The blue background design extends from row 1 to row 3. `grid-row: 1/3;`
```css
.card__bg{
    grid-row: 1/3;    
    background: url(images/bg-pattern-card.svg);
    border-radius:15px 15px 0 0;
}
```
To position the profile picture, I initially placed it at row 3 `grid-row: 3/4;`. Then I did a margin top of -5rem which eventually aligned the picture vertically as I wanted. Since `img` is an inline element, I used `text-align: center;` to align the picture horizontally centered.
To make the square picture circled, I gave it a `border-radius:` of `50%` and colored the border white.
```css
.card__img{
    grid-row: 3/4;
    margin-top: -5rem;
    text-align: center;
}

.card__img img{
    border: 0.5rem solid white;
    border-radius: 50%;
}
```
The remaining rows are divided into 2 parts: primary(pri) and secondary(sec).
The first section consists of the name, age and place. This is placed in row 5 `grid-row: 4/5;` and styled according to the design.
```css
.card__pri{
    grid-row: 4/5;
    text-align: center;
    position: relative;    
}

.card__pri section *{
    line-height: 3rem;
}
```
The second part consist of the rest of the details. This is placed in row 5 `grid-row: 5;`. 
  - Now I am using **CSS Flexbox** to position the contents in this row. There are 3 sections and I wanted them spaced out evenly, hence i used `justify-content: space-evenly;`
  - Now within each section, I am again using flexbox to align items to the center vertically and horizontally.
```css
.card__sec{
    grid-row: 5;
    display: flex;
    justify-content: space-evenly;
    border-top: 1px solid var(--Dgray); 
}

.card__sec section{
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
}
```
This part of the code was new to me. In this code we are selecting every element that is child to `.card__sec section` and styling it.
```css
.card__sec section *{
    line-height: 2rem;
}
```


### Animation

Coming to the animation part, I wanted the circles to float into the page on load. 
- So at the start i.e., at `0%` the opacity will be 0 which means that the circles wont be visible. I have set the position of circles in such a way that they are out of the main screen.
- At the end i.e., at `100%` the opacity will be 1 and the circles will be clearly visible. This time the circles are positioned at the desired location. 

```css
@keyframes circles {
    0% { 
        opacity: 0;
        background-position: top -100vh right 100vw, top 100vh left 100vw;
    }
    100% { 
            opacity: 1;
            background-image: url(images/bg-pattern-top.svg), url(./images/bg-pattern-bottom.svg);
            background-position: top -65vh right 50vw, top 50vh left 50vw;
    }     
}
```
Each animation needs to be defined with the `@keyframes` at-rule which is then called with the `animation` property.

- I have set the `animation` property on the `body` element. 
    - I want the total duration of the animation to be `2s`.
    - My `animation-name` is `circles`. 
    - The `animation-timing-function` is set to `ease-out`. This is used to set how you want the animation to progress. Ease-out will make the circles load quickly and then slows down the animation as it continues.
    - On setting the `animation-fill-mode` to `forwards` the circle will retain the computed values set by the last keyframe ( `100%` ) encountered during execution.

Here I have used the **animation shorthand notation** .
```css
body{
    animation: 2s circles ease-out forwards;
    ...
}
```

## Author 🦸🏻‍♀️

- GitHub - [@lismaria](https://github.com/lismaria)
- Frontend Mentor - [@lismaria](https://www.frontendmentor.io/profile/lismaria)
- Reach me out on [LinkedIn](https://www.linkedin.com/in/lismariasaju/)


## _`H A P P Y   C O D I N G👩🏻‍💻👨🏻‍💻`_