DEV Community

Cover image for Profile Card challenge - frontendmentor.io
lismaria
lismaria

Posted on

Profile Card challenge - frontendmentor.io

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

This is a solution to the Profile card component challenge on Frontend Mentor. 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

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 InterfaceMobile Interface

Links

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

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

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

/* 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 { }
Enter fullscreen mode Exit fullscreen mode

Useful resources

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.
: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 */
}
Enter fullscreen mode Exit fullscreen mode

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.

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

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

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

The blue background design extends from row 1 to row 3. grid-row: 1/3;

.card__bg{
    grid-row: 1/3;    
    background: url(images/bg-pattern-card.svg);
    border-radius:15px 15px 0 0;
}
Enter fullscreen mode Exit fullscreen mode

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.

.card__img{
    grid-row: 3/4;
    margin-top: -5rem;
    text-align: center;
}

.card__img img{
    border: 0.5rem solid white;
    border-radius: 50%;
}
Enter fullscreen mode Exit fullscreen mode

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.

.card__pri{
    grid-row: 4/5;
    text-align: center;
    position: relative;    
}

.card__pri section *{
    line-height: 3rem;
}
Enter fullscreen mode Exit fullscreen mode

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

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.

.card__sec section *{
    line-height: 2rem;
}
Enter fullscreen mode Exit fullscreen mode

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

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 .

body{
    animation: 2s circles ease-out forwards;
    ...
}
Enter fullscreen mode Exit fullscreen mode

Author 🦸🏻‍♀️

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

Top comments (6)

Collapse
 
romeoks profile image
Romeo • Edited

It's worth mentioning that Pro membership on FrondEndmentor.io will give members access to design files, which make writing code much easier and this files contain the design system which IMHO every frontend dev should understand and use.
Also the Pro membership gives access to Premium challenges.
I started using Frontendmentor.io about a year ago and it helped me a lot to apply what I've learned.
I also want to mention that peeking at other members solutions it will help us if we get stuck and also that Frontendmentor.io has a good Slack channel where members can ask for help or get their solutions reviewed.

PS. I'm not affiliated with Frontendmentor.io

Happy coding!

Collapse
 
lismaria profile image
lismaria

Hi Romeo, thank you for sharing with us!!

Collapse
 
robertrynard profile image
Robert-Rynard

Thank you SO much!! I could not for the life of me figure out how to get those background to work. I don't have much experience using the vw and vh units but was trying to use them after some searching and seeing it might help. I got close to what you have but was using negative values and I'm not sure why but that seem to have a different end result. Appreciate the write up!

Collapse
 
lismaria profile image
lismaria

Ayee!! I'm so glad that it helped :D

Collapse
 
leonblade profile image
James Stine

I didn't know about this site at all. I'll definitely check out some of the challenges.

Collapse
 
lismaria profile image
lismaria

Yes! That would be fun!!