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
Links
- Solution URL: solution-link
- Live Site URL: site-link
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 anh2
element, not anh3
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 theh1
toh6
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
, andfooter
. 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 { }
Useful resources
- 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 - 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 & CSS Flexbox Tutorial - The Net Ninja is my go to channel for almost any web development related stuff.
- CSS Variables - Web Dev Simplified is another great channel. He simplifies every concept and learning is so beginner level.
- BEM: Block-Element-Modifier - I was unaware of this convention. Tried for the first time!
- CSS Animations - Wanna start of with CSS animations? Check this out. If you have time follow this playlist
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 */
}
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.
-
- The url of both the circles is comma-separated and put in the value of
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);
.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;
.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.
.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.
.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.
.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.
.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.
@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 thebody
element.- I want the total duration of the animation to be
2s
. - My
animation-name
iscircles
. - The
animation-timing-function
is set toease-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
toforwards
the circle will retain the computed values set by the last keyframe (100%
) encountered during execution.
- I want the total duration of the animation to be
Here I have used the animation shorthand notation .
body{
animation: 2s circles ease-out forwards;
...
}
Top comments (6)
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!
Hi Romeo, thank you for sharing with us!!
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!
Ayee!! I'm so glad that it helped :D
I didn't know about this site at all. I'll definitely check out some of the challenges.
Yes! That would be fun!!