Build a Developer Profile Page
Build a styled developer profile page from scratch with HTML and CSS.
Introduction
30 Second Summary
Every website you visit is built on two languages: HTML and CSS. They are the foundation that every modern web framework compiles down to.
In this project, you will build a Developer Profile Page from scratch using only HTML and CSS. You'll create a page with a styled header, an about section with an image, a skills list, an experience timeline, and a footer.
What You'll Build
A personal Developer Profile Page that showcases your information as a full-stack developer, built entirely with raw HTML and CSS files.
By the end of this project, you'll have:
- A complete HTML document using semantic elements to structure your profile page with headings, paragraphs, links, images, and lists.
- A CSS stylesheet demonstrating selectors, the box model, typography, colors, and interactive pseudo-classes.
- A live-reloading development environment in Cursor so changes appear instantly in the browser.
- Secret Mission: Add a styled contact form that introduces form elements, focus states, and accessibility basics.
Are there any prerequisites?
No prior web development experience is needed. This guide includes setup instructions for all required tools. You just need a computer with Cursor installed.
Before We Start
Every web page starts with two files: an HTML file for content and a CSS file for styling. Before you write any code, you need a workspace where you can see changes instantly in the browser.
In this step, you will create a project folder, install a browser preview extension, and confirm that edits appear live.
In this step, get ready to:
- Create a dev-profile project folder with an HTML file and a CSS file.
- Install the Live Server (Five Server) extension for instant browser preview.
- Verify that saving a file automatically updates the browser.
Create the project folder and files
You need a dedicated folder on your Desktop to hold the two project files. Creating it on the Desktop makes it easy to find later.
- Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type Cursor and press Enter to open it.
- Open a terminal inside Cursor by clicking Terminal in the top menu bar, then clicking New Terminal.
A panel appears at the bottom of the Cursor window with a blinking cursor ready for commands.
- Move to your Desktop by running this command:
cd ~/Desktop
- Create your project folder and move into it by running these commands:
mkdir dev-profile
cd dev-profile
- Create the two project files by running this command:
macOS
touch index.html styles.css
Windows
New-Item -ItemType File -Path .\index.html
New-Item -ItemType File -Path .\styles.css
- Confirm the files exist by running:
ls
You should see index.html and styles.css in the output.
- Open this folder as your workspace by clicking File in the top menu bar.
- Click Open Folder.
- Navigate to your Desktop, select the dev-profile folder, and click Open.
The Explorer sidebar on the left now shows index.html and styles.css under the dev-profile heading.
Don't see both files in the sidebar?
Make sure you selected the dev-profile folder itself, not its parent (Desktop). If you opened the Desktop instead, click File then Open Folder again and select dev-profile.
help me find my project files in Cursor
Install the Live Server extension
Live Server launches a local web server and automatically refreshes the browser whenever you save a file. This gives you instant visual feedback as you build your page.
- Open the Extensions panel by pressing Cmd+Shift+X (macOS) or Ctrl+Shift+X (Windows).
- Type Five Server in the search bar at the top of the panel.
- Find the result titled Live Server (Five Server) by yandeu.
- Click Install.
After a few seconds, the Install button changes to a gear icon, confirming the extension is ready.
Why Live Server instead of opening the file directly?
You could double-click an HTML file to open it in a browser, but you would have to manually refresh every time you make a change. Live Server watches your files and pushes updates to the browser automatically, so you see results the instant you save.
Can't find the extension?
Make sure you are searching for Five Server (two words), not "Live Server" which returns multiple results. Look for the author name yandeu to confirm you have the right one.
help me install the Five Server extension in Cursor
Verify live-reload works
Now you will add a test heading to your HTML file and launch the server to confirm everything connects.
- Click on index.html in the Explorer sidebar to open it in the editor.
- Type the following code into the file:
<h1>Hello</h1>
What does this code do?
The <h1> tag creates the largest heading on a page. The browser reads everything between <h1> and </h1> as a top-level heading and displays it in large, bold text.
- Save the file by pressing Cmd+S (macOS) or Ctrl+S (Windows).
- In the Explorer sidebar, right-click on index.html.
- Select Open with Five Server from the context menu.
Your default browser opens and displays the word "Hello" in large text.
- Back in Cursor, change the text inside the <h1> tag to anything else (for example, Hello World) and save the file.
The browser updates automatically without you refreshing the page. This confirms live-reload is working.
- Change the text back to Hello and save index.html so it matches the code above.
Browser didn't open or shows a blank page?
Make sure you right-clicked index.html in the Explorer sidebar (not the editor tab). If you do not see Open with Five Server in the menu, the extension may not have finished installing. Close and reopen Cursor, then try again.
help me launch Five Server in Cursor
✔️ Awesome, I've got everything!
Great. Double check you have saved index.html and that the browser shows "Hello" in large text.
ⓧ I'd like to double check the full code
Here is what each file should contain at this point:
index.html:
<h1>Hello</h1>
styles.css:
This file should be completely empty. You will add styles in a later step.
Your development environment is ready. Next up, you will build the full HTML structure of your Developer Profile Page using semantic elements.
Build the HTML Structure
Your development environment is ready and the browser is live-reloading changes. Now it's time to replace that test heading with a proper HTML document.
Every web page needs a specific structure that tells the browser how to interpret its content. In this step, you'll write the document skeleton and organize it using semantic elements that describe what each section of the page is for.
In this step, get ready to:
- Write the HTML boilerplate that every web page needs.
- Add semantic elements to define the page's major sections.
- Confirm the structure appears correctly in browser DevTools.
Write the HTML boilerplate
Every HTML page starts with a specific structure that the browser expects. This includes a declaration of the document type, a head section for metadata, and a body for visible content.
- Switch back to index.html in Cursor.
- Select all the existing content (Cmd+A on macOS or Ctrl+A on Windows) and delete it.
- Replace it with the following HTML boilerplate:
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Tells the browser which character set to use -->
<meta charset="UTF-8">
<!-- Makes the page scale correctly on mobile devices -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- The text shown in the browser tab -->
<title>Developer Profile</title>
<!-- Connects your CSS stylesheet to this HTML file -->
<link rel="stylesheet" href="styles.css">
</head>
<body>
</body>
</html>
What does this code do?
- <!DOCTYPE html> tells the browser this is an HTML5 document. Without it, browsers may render the page in a quirky compatibility mode.
- <html lang="en"> wraps everything and declares the page language as English for screen readers and search engines.
- <head> contains metadata the browser needs but does not display on the page. This is where you set the character encoding, viewport size, page title, and link to external files like stylesheets.
- <body> contains everything visible on the page. All your headings, text, images, and links go here.
- Save index.html (Cmd+S on macOS or Ctrl+S on Windows).
- Check your browser. The page should now be completely blank (no more "Hello" text) because the <body> is empty.
Still seeing "Hello" in the browser?
- Make sure you deleted the old <h1>Hello</h1> content before pasting the new boilerplate.
- Confirm you saved the file. An unsaved file shows a dot on its tab in Cursor.
- Check that Five Server is still running. You should see a port number (like 5500) in the Cursor status bar at the bottom.
Why is my page still showing old content after saving?
Add semantic structure elements
With the boilerplate in place, you need to define the major sections of your profile page. HTML provides semantic elements that describe the purpose of content, not just its appearance.
Semantic elements like <header> and <main> help screen readers, search engines, and other developers understand what each part of the page is for. A generic <div> has no meaning at all.
- In index.html, place your cursor on the empty line between <body> and </body>.
- Add the following semantic structure inside the body:
<header>
</header>
<main>
<!-- About section -->
<section id="about">
</section>
<!-- Skills section -->
<section id="skills">
</section>
<!-- Experience section -->
<section id="experience">
</section>
</main>
<footer>
</footer>
What does this code do?
- <header> defines the page banner area. It will hold your name and title.
- <main> wraps the primary content of the page. There should be only one <main> per page.
- <section> groups related content together. Each section has an id attribute so you can target it individually with CSS later.
- <footer> defines the bottom information area. It will hold your contact details.
These elements work identically to a <div> in terms of layout. The difference is purely semantic. A <div> says "this is a box," while <header> says "this is the page banner."
- Save index.html.
- Check your browser. The page still looks blank because semantic elements have no visible styling by default.
Seeing broken text or tags on the page?
- Make sure all your opening tags have matching closing tags. For example, <section id="about"> needs a corresponding </section>.
- Check that the semantic elements are placed between <body> and </body>, not inside the <head> section.
Why does my HTML look broken in the browser?
Inspect the element tree in DevTools
The page looks empty, but the structure is there. Browser DevTools let you see the full element tree that the browser built from your HTML.
- In your browser, right-click anywhere on the blank page and select Inspect.
- The Elements panel opens, showing the DOM tree. You can also use the keyboard shortcut Cmd+Option+I (macOS) or F12 (Windows).
- Click the arrow next to <body> to expand it.
- You should see <header>, <main>, and <footer> listed as children. Expand <main> to see the three <section> elements nested inside it.
Why use DevTools?
DevTools shows you exactly what the browser sees. Even when a page looks empty, DevTools reveals the underlying structure. This is essential for debugging throughout this project.
✔️ Awesome, I've got everything!
Great. Double check you've saved index.html and you can see the element tree in DevTools.
ⓧ I'd like to double check the full code
Here is the complete index.html at this point:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Developer Profile</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header>
</header>
<main>
<section id="about">
</section>
<section id="skills">
</section>
<section id="experience">
</section>
</main>
<footer>
</footer>
</body>
</html>
Your HTML skeleton is in place. Next up, you'll fill these empty elements with real content like headings, text, images, and links.
Add HTML Content Elements
Your page has a solid semantic skeleton, but it looks completely blank in the browser because every element is empty.
In this step, you will fill each section with real content. By the end, your page will display headings, paragraphs, images, links, lists, and grouped entries using only HTML elements.
In this step, get ready to:
- Add headings, an image, paragraphs, and a link to the header and about section.
- Add a skills list and experience entries with grouped inline elements.
- Add footer content and preview the full page in the browser.
Add header and about content
Every section needs content elements inside it to display anything in the browser. You will start with the header and about section, which introduce headings, images, paragraphs, and links.
- In index.html, find the empty <header> element and add the following code between the opening and closing tags:
<h1>Your Name</h1>
<p>Full-Stack Developer</p>
- Next, find the <section id="about"> element and add this content inside it:
<h2>About Me</h2>
<img src="https://placehold.co/150x150" alt="Profile photo of Your Name">
<p>I am a full-stack developer with experience building backend services with Node.js. Currently expanding into frontend development to build complete web applications from end to end.</p>
<p>Check out my work on <a href="https://github.com">GitHub</a>.</p>
What does this code do?
These two sections introduce the most common HTML content elements:
- <h1> through <h6> define heading hierarchy. <h1> is the page title, <h2> is a section heading, and so on.
- <p> creates a paragraph. It is a block-level element, meaning it takes the full width of its container and stacks vertically.
- <img> embeds an image. It is self-closing (no closing tag needed) and requires src (the image URL) and alt (a text description for accessibility).
- <a> creates a hyperlink. It is an inline element, meaning it flows within surrounding text rather than starting a new line.
Block elements (like <p> and <h1>) stack vertically and take full width. Inline elements (like <a>) flow horizontally within text.
- Save index.html.
- Refresh your browser. You should see "Your Name" as a large bold heading, "Full-Stack Developer" below it, a small placeholder image, two paragraphs of text, and a blue underlined "GitHub" link.
Don't see any content in the browser?
- Make sure your code is between the opening <header> and closing </header> tags (or the matching section tags). Code placed outside these elements will not appear in the expected location.
- Check that Five Server is still running. Look for "Go Live" in the bottom status bar. If it says "Go Live" instead of showing a port number, right-click index.html in the Explorer panel and select Open with Five Server.
- help me debug why my HTML content isn't showing in the browser
Add skills and experience content
The skills section uses a list, and the experience section uses grouped inline elements to style individual words differently later with CSS.
- In index.html, find the <section id="skills"> element and add this content inside it:
<h2>Skills</h2>
<ul>
<li>JavaScript</li>
<li>Node.js</li>
<li>TypeScript</li>
<li>Express</li>
<li>HTML & CSS</li>
</ul>
What are lists in HTML?
- <ul> creates an unordered (bulleted) list. <ol> creates an ordered (numbered) list.
- <li> represents each list item inside a <ul> or <ol>.
- & is an HTML entity that displays the & symbol. Special characters like &, <, and > have entity codes because they have special meaning in HTML.
- Save index.html and refresh your browser.
- You should see a bulleted list with five skills displayed below an "Skills" heading.
- Now find the <section id="experience"> element and add this content inside it:
<h2>Experience</h2>
<article>
<h3>Backend Developer</h3>
<p><span class="company">Tech Company</span> - <span class="duration">2024 - Present</span></p>
<p>Built RESTful APIs and microservices using Node.js and Express. Designed database schemas and implemented authentication systems.</p>
</article>
<article>
<h3>Junior Developer</h3>
<p><span class="company">Startup Inc</span> - <span class="duration">2023 - 2024</span></p>
<p>Developed internal tools and automated deployment pipelines. Collaborated with frontend team on API design.</p>
</article>
What are article, span, and class?
- <article> represents a self-contained piece of content (like a blog post or job entry). It is a semantic element that tells the browser this content could stand alone.
- <span> is an inline container with no visual meaning on its own. You use it to wrap specific words so you can target them with CSS later. Compare this to <div>, which is a block-level container.
- class="company" is a class attribute. Classes can be reused on multiple elements and let you style groups of elements the same way.
- id="about" is an id attribute. IDs must be unique per page and target a single specific element.
- Save index.html and refresh your browser.
- You should see two job entries, each with a bold heading, company and duration text, and a description paragraph.
Seeing jumbled or missing text?
- Double check that every opening tag has a matching closing tag. For example, each <span class="company"> must have a </span> after the text inside it.
- Make sure the two <article> elements are siblings (next to each other), not nested inside one another.
- help me fix my experience section HTML
Add footer content and preview the page
- Find the empty <footer> element and add this content inside it:
<p>Built by Your Name | <a href="mailto:you@email.com">you@email.com</a></p>
What is a mailto link?
The href="mailto:you@email.com" attribute tells the browser to open the user's email app with a pre-filled recipient address when clicked. This is a special URL scheme, similar to how https:// opens a web page.
- Save index.html and refresh your browser.
- Your page should now display all content from top to bottom: a name heading, job title, placeholder image, about paragraphs with a GitHub link, a bulleted skills list, two experience entries, and a footer with an email link.
- Everything appears in plain browser defaults. You will see a serif font (like Times New Roman), blue underlined links, and bullet points.
Page still looks blank or partially empty?
- Open DevTools by pressing F12 and check the Elements tab. You should see your full element tree. If elements are missing or misplaced, compare your nesting against the full code below.
- help me figure out why my HTML page isn't displaying all content correctly
✔️ Awesome, I've got everything!
Great. Double check you have saved index.html and your browser shows all sections with content.
ⓧ I'd like to double check the full code
Here is the complete index.html file at this point. Compare yours against it:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Developer Profile</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<header>
<h1>Your Name</h1>
<p>Full-Stack Developer</p>
</header>
<main>
<section id="about">
<h2>About Me</h2>
<img src="https://placehold.co/150x150" alt="Profile photo of Your Name">
<p>I am a full-stack developer with experience building backend services with Node.js. Currently expanding into frontend development to build complete web applications from end to end.</p>
<p>Check out my work on <a href="https://github.com">GitHub</a>.</p>
</section>
<section id="skills">
<h2>Skills</h2>
<ul>
<li>JavaScript</li>
<li>Node.js</li>
<li>TypeScript</li>
<li>Express</li>
<li>HTML & CSS</li>
</ul>
</section>
<section id="experience">
<h2>Experience</h2>
<article>
<h3>Backend Developer</h3>
<p><span class="company">Tech Company</span> - <span class="duration">2024 - Present</span></p>
<p>Built RESTful APIs and microservices using Node.js and Express. Designed database schemas and implemented authentication systems.</p>
</article>
<article>
<h3>Junior Developer</h3>
<p><span class="company">Startup Inc</span> - <span class="duration">2023 - 2024</span></p>
<p>Developed internal tools and automated deployment pipelines. Collaborated with frontend team on API design.</p>
</article>
</section>
</main>
<footer>
<p>Built by Your Name | <a href="mailto:you@email.com">you@email.com</a></p>
</footer>
</body>
</html>
Your page now has every piece of content in place. Next up, you will open styles.css and start transforming this plain content into a styled profile with CSS selectors and typography.
Style with CSS Selectors and Typography
Your HTML content is complete with headings, paragraphs, links, images, and lists all in place. Right now, though, the browser renders everything in its unstyled defaults.
CSS is the language that controls how HTML elements look on screen. In this step, you will write your first CSS rules to reset browser defaults, define your typography, and style the header.
In this step, get ready to:
- Reset browser default styles for consistent spacing.
- Set up base typography for the entire page.
- Style the header and section headings with CSS selectors.
Add a universal reset
Every browser applies its own default margins, padding, and sizing to HTML elements. This causes inconsistent spacing that makes styling unpredictable.
- Open styles.css in Cursor and add a universal reset by pasting this code:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
What does this code do?
- The * selector targets every element on the page. It is the universal selector.
- margin: 0 and padding: 0 remove all the default spacing browsers add to elements like headings, paragraphs, and lists.
- box-sizing: border-box makes an element's width and height include its padding and border, not just its content. Without this, adding padding makes elements wider than you set them to be.
- Save styles.css and check your browser.
- You should see all the content shift slightly. The gaps between headings, paragraphs, and list items disappear because the browser defaults have been removed.
Page looks the same as before?
- Make sure you saved styles.css. Unsaved changes will not appear in the browser.
- Confirm your index.html has <link rel="stylesheet" href="styles.css"> in the <head> section. This line connects your HTML to your stylesheet.
- Check that both files are in the same folder (dev-profile). If the stylesheet is in a subfolder, the browser will not find it.
Why isn't my CSS reset showing any changes in the browser?
Style the body with typography
With defaults cleared, you can set your own base styles on the body element. These styles cascade down to every element inside the body, giving your whole page a consistent look.
- Add the body styles below your reset in styles.css:
body {
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
font-size: 16px;
line-height: 1.6;
color: #333333;
background-color: #f5f5f5;
}
What does this code do?
- font-family sets the typeface. The browser tries each font in the list from left to right and uses the first one installed on the user's computer.
- font-size: 16px sets the base text size. px means pixels, a fixed unit that does not change with user settings.
- line-height: 1.6 controls the space between lines of text. A value of 1.6 means each line is 1.6 times the font size, which makes paragraphs comfortable to read.
- color sets the text color. #333333 is a hex code for dark gray.
- background-color sets the page background. #f5f5f5 is a very light gray that is easier on the eyes than pure white.
What are rem and em units?
You will see three types of CSS units in this project. px is a fixed pixel value that never changes. rem is relative to the root font-size (the 16px you just set), so 2.5rem equals 40px.
em is relative to the parent element's font-size, which can sometimes cause unexpected sizing when elements are nested. For headings and spacing, rem is the more predictable choice.
- Save styles.css and check your browser.
- The page background should now be light gray, and all text should appear in a clean sans-serif font instead of the browser's default Times New Roman.
Still seeing Times New Roman?
- Check that the body rule is outside the * { } block, not nested inside it. Each CSS rule needs its own opening and closing curly braces.
- Make sure you have a closing } for the reset block before the body rule starts.
Why is my body font-family not being applied?
Style the header and section headings
So far you have used only the element selector (targeting elements by their tag name, like body). CSS has several selector types that let you target elements with increasing precision.
- Add the header styles below your body rule in styles.css:
header {
background-color: #2c3e50;
color: #ffffff;
padding: 40px 20px;
text-align: center;
}
header h1 {
font-size: 2.5rem;
margin-bottom: 8px;
}
header p {
font-size: 1.2rem;
color: #bdc3c7;
}
What's happening here?
This code uses two selector types. header is an element selector that targets the <header> tag directly. header h1 is a descendant selector. The space between the two names means "target any h1 that is nested inside a header."
This lets you style the h1 inside the header differently from an h1 anywhere else on the page. More specific selectors override less specific ones.
- Save styles.css and check your browser.
- You should see a dark blue banner across the top of the page with your name in large white text and your title in a muted gray below it.
Header not turning dark blue?
- Check that header in your CSS matches the <header> tag in your HTML exactly. CSS selectors are case-sensitive.
- Make sure the previous body { } rule has a closing } before the header rule. A missing brace breaks every rule after it.
Why is my header background-color not showing?
- Now add the section heading styles below your header rules in styles.css:
section h2 {
font-size: 1.8rem;
color: #2c3e50;
margin-bottom: 16px;
border-bottom: 2px solid #3498db;
padding-bottom: 8px;
}
What are the four CSS selector types?
You have now used three of the four main selector types in this project:
- Element selector (body, header) targets all elements of that tag type.
- Descendant selector (header h1, section h2) targets elements nested inside another element.
- Class selector (.company) targets elements with a specific class attribute. You will use these in the next step.
- ID selector (#about) targets the single element with that unique ID.
When multiple rules target the same element, the more specific selector wins. This is called specificity.
- Save styles.css and check your browser.
- Each section heading (About Me, Skills, Experience) should now be larger, dark colored, and have a blue underline beneath it.
Section headings not styled?
- The selector section h2 only targets h2 elements inside a <section>. Make sure your HTML headings use <h2> (not <h3> or another heading level).
- Check for a missing } on the rule above. A single missing brace causes the browser to ignore everything after it.
My section h2 styles are not being applied. What could be wrong?
✔️ Awesome, I've got everything!
Great. Double check you have saved styles.css before moving on.
ⓧ I'd like to double check the full code
Here is the complete styles.css file so far. Compare yours against it:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
font-size: 16px;
line-height: 1.6;
color: #333333;
background-color: #f5f5f5;
}
header {
background-color: #2c3e50;
color: #ffffff;
padding: 40px 20px;
text-align: center;
}
header h1 {
font-size: 2.5rem;
margin-bottom: 8px;
}
header p {
font-size: 1.2rem;
color: #bdc3c7;
}
section h2 {
font-size: 1.8rem;
color: #2c3e50;
margin-bottom: 16px;
border-bottom: 2px solid #3498db;
padding-bottom: 8px;
}
Your page already looks dramatically different from the unstyled version. Next up, you will use the CSS box model to control spacing and layout across the rest of the page.
Apply the Box Model and Visual Styling
Your header is styled and your section headings stand out with color and a blue underline. The page has a clear visual hierarchy, but the sections still blend into the background with no separation between them.
Every HTML element is a rectangular box made of four layers: content, padding, border, and margin. In this step, you will use this box model to give each section its own card-like appearance, style the profile image and skills list, and add interactive hover effects to links.
In this step, get ready to:
- Style the page layout and section cards using the CSS box model.
- Style the about image, skills list, and experience entries.
- Add link colors and interactive hover effects using pseudo-classes.
Style the page layout and section cards
The box model has four layers: content at the center, padding around the content, border around the padding, and margin outside the border. You will use these layers to center the page content and turn each section into a distinct white card.
- In styles.css, find the section h2 rule.
- Add the following code directly above it:
/* Center the content and limit width */
main {
max-width: 800px;
margin: 0 auto;
padding: 40px 20px;
}
/* Give each section a card-like appearance */
section {
background-color: #ffffff;
padding: 30px;
margin-bottom: 30px;
border-radius: 8px;
border: 1px solid #e0e0e0;
}
What does this code do?
- max-width: 800px prevents the content from stretching across wide screens. It sets a maximum width but allows the content to shrink on smaller screens.
- margin: 0 auto centers the main element horizontally. The auto value distributes remaining space equally on the left and right.
- padding: 30px adds space inside each section (between the content and the border).
- margin-bottom: 30px adds space outside each section (between one section's border and the next).
- border-radius: 8px rounds the corners of the border to create the card effect.
What is the CSS box model?
Every HTML element is a box with four layers. Content is at the center (your text or image). Padding wraps around the content, creating space inside the element. Border wraps around the padding. Margin wraps around the border, creating space outside the element.
The key difference: padding adds space inside the element (background color fills it), while margin adds space outside (it is always transparent).
- Save styles.css.
- Your browser auto-refreshes. You should see the sections now appear as white cards with rounded corners, centered on the grey background with clear spacing between them.
Sections still look flat?
- Make sure your new code is above the section h2 rule, not below it. The section rule must come before section h2 in the file.
- Check that you have the opening { and closing } braces for both the main and section rules.
Still having trouble? Help me fix my section card styling
Style the about image, skills list, and experience entries
Now you will use the box model to style individual content elements within each section. Each group of styles targets a specific section using ID selectors and class selectors.
- In styles.css, scroll to the bottom of the file (below the section h2 rule).
- Add the about section image and paragraph styles:
/* Make the profile image circular */
#about img {
width: 150px;
height: 150px;
border-radius: 50%;
border: 3px solid #3498db;
margin-bottom: 16px;
}
/* Add spacing between about paragraphs */
#about p {
margin-bottom: 12px;
}
What does this code do?
- #about img is a descendant selector. It targets only img elements inside the element with id="about".
- border-radius: 50% turns a square image into a perfect circle. Equal width and height plus 50% radius creates the circular crop.
- margin-bottom: 12px on paragraphs adds vertical breathing room between each paragraph.
- Save styles.css.
- You should see your placeholder image is now circular with a blue border around it.
Image still square?
- Confirm the width and height are equal (both 150px). A circle requires a square element.
- Check the selector is #about img with a space between them. Without the space, CSS looks for an element with both the ID and the tag name on the same element.
Need help? Why is my profile image not circular?
- Below #about p, add the skills list styles:
/* Remove default bullet points */
#skills ul {
list-style: none;
}
/* Style each skill as a card with a left accent */
#skills li {
background-color: #ecf0f1;
padding: 10px 16px;
margin-bottom: 8px;
border-radius: 4px;
border-left: 4px solid #3498db;
}
What does this code do?
- list-style: none removes the default bullet markers from the unordered list.
- border-left: 4px solid #3498db adds a thick blue accent on the left edge of each skill item. This creates a visual indicator without using bullet points.
- Save styles.css.
- Your skills list should now show as grey cards with a blue left accent instead of plain bullet points.
Skills still showing default bullets?
- Make sure you have both #skills ul and #skills li as separate rules. The list-style: none goes on the ul, not the li.
- Check your HTML has id="skills" on the section element. The CSS #skills selector targets that specific ID.
Still stuck? Help me debug my skills list styling
- Below #skills li, add the experience section styles:
/* Separate experience entries with a bottom border */
article {
margin-bottom: 20px;
padding-bottom: 20px;
border-bottom: 1px solid #e0e0e0;
}
/* Remove border from the last entry */
article:last-child {
border-bottom: none;
margin-bottom: 0;
padding-bottom: 0;
}
/* Style job titles */
article h3 {
font-size: 1.3rem;
color: #2c3e50;
margin-bottom: 4px;
}
/* Highlight company names */
.company {
font-weight: bold;
color: #3498db;
}
/* Subtle styling for date ranges */
.duration {
color: #7f8c8d;
font-style: italic;
}
What does this code do?
- article:last-child is a pseudo-class that targets only the final article element inside its parent. It removes the bottom border so the last entry doesn't have an unnecessary divider.
- .company and .duration are class selectors. They target the <span> elements you gave those class names to in your HTML.
- font-style: italic on the duration creates a visual distinction between the company name (bold, blue) and the time period (italic, grey).
- Save styles.css.
- In the Experience section, you should see job entries separated by thin grey lines. Company names appear in bold blue and durations appear in italic grey.
Company and duration text not styled?
- Verify your HTML has class="company" and class="duration" on the <span> elements. Class names are case-sensitive.
- Make sure you used a dot before the class name in CSS (.company not company). The dot tells CSS this is a class selector.
Need help? Why aren't my class selectors working?
Style links and the footer with pseudo-classes
Pseudo-classes target elements in a specific state. The :hover pseudo-class applies styles only when the mouse is over an element. This lets you create interactive visual feedback without JavaScript.
- In styles.css, find the #about p rule.
- Add the link styles directly below it (above #skills ul):
/* Style all links with brand color */
a {
color: #3498db;
text-decoration: none;
}
/* Change appearance when mouse hovers over a link */
a:hover {
color: #2980b9;
text-decoration: underline;
}
What does this code do?
- text-decoration: none removes the default blue underline that browsers put on links.
- a:hover applies only when the cursor is over the link. The color darkens and the underline reappears, signaling to the user that the element is clickable.
- Other useful pseudo-classes include :focus (when an element is selected via keyboard) and :first-child (targets the first element in a group).
- Save styles.css.
- Hover your mouse over the GitHub link in the About section. You should see it change color and gain an underline.
Link not changing on hover?
- Make sure a:hover has no space between a and :hover. A space would make it a descendant selector instead of a pseudo-class.
- Confirm the a:hover rule comes after the a rule. If reversed, the base styles would override the hover styles.
Need help? Why isn't my hover effect working on links?
- Scroll to the very bottom of styles.css (below the .duration rule).
- Add the footer styles:
/* Match footer style to header */
footer {
background-color: #2c3e50;
color: #ffffff;
text-align: center;
padding: 20px;
}
/* Style footer link */
footer a {
color: #3498db;
}
/* Lighter hover color for footer link */
footer a:hover {
color: #5dade2;
}
What does this code do?
- The footer uses the same dark background as the header, creating a visual "bookend" effect that frames the page.
- footer a overrides the general a color because it is a more specific selector (descendant selector beats element selector). This is CSS specificity in action.
- footer a:hover uses a lighter blue (#5dade2) because the footer's dark background needs a different contrast than the white sections.
- Save styles.css.
- Scroll to the bottom of your page. You should see a dark footer matching the header, with a blue email link that lightens on hover.
Footer link color not changing?
- Make sure you have three separate rules: footer, footer a, and footer a:hover. Each needs its own set of curly braces.
- Verify the footer link in your HTML uses the <a> tag with an href attribute. Without a valid href, some browsers won't apply link pseudo-classes.
Still stuck? Help me debug my footer link styles
Your Developer Profile Page is now fully styled. Every section is a clean white card, the image is circular, skills have accent borders, and links respond to hover. Take a moment to scroll through the page and appreciate how much CSS transformed the raw HTML.
✔️ Awesome, I've got everything!
Great. Double check you have saved your file.
ⓧ I'd like to double check the full code
Here is the complete styles.css file at this point:
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
font-size: 16px;
line-height: 1.6;
color: #333333;
background-color: #f5f5f5;
}
header {
background-color: #2c3e50;
color: #ffffff;
padding: 40px 20px;
text-align: center;
}
header h1 {
font-size: 2.5rem;
margin-bottom: 8px;
}
header p {
font-size: 1.2rem;
color: #bdc3c7;
}
main {
max-width: 800px;
margin: 0 auto;
padding: 40px 20px;
}
section {
background-color: #ffffff;
padding: 30px;
margin-bottom: 30px;
border-radius: 8px;
border: 1px solid #e0e0e0;
}
section h2 {
font-size: 1.8rem;
color: #2c3e50;
margin-bottom: 16px;
border-bottom: 2px solid #3498db;
padding-bottom: 8px;
}
#about img {
width: 150px;
height: 150px;
border-radius: 50%;
border: 3px solid #3498db;
margin-bottom: 16px;
}
#about p {
margin-bottom: 12px;
}
a {
color: #3498db;
text-decoration: none;
}
a:hover {
color: #2980b9;
text-decoration: underline;
}
#skills ul {
list-style: none;
}
#skills li {
background-color: #ecf0f1;
padding: 10px 16px;
margin-bottom: 8px;
border-radius: 4px;
border-left: 4px solid #3498db;
}
article {
margin-bottom: 20px;
padding-bottom: 20px;
border-bottom: 1px solid #e0e0e0;
}
article:last-child {
border-bottom: none;
margin-bottom: 0;
padding-bottom: 0;
}
article h3 {
font-size: 1.3rem;
color: #2c3e50;
margin-bottom: 4px;
}
.company {
font-weight: bold;
color: #3498db;
}
.duration {
color: #7f8c8d;
font-style: italic;
}
footer {
background-color: #2c3e50;
color: #ffffff;
text-align: center;
padding: 20px;
}
footer a {
color: #3498db;
}
footer a:hover {
color: #5dade2;
}
Secret mission
Add a Styled Contact Form
Your profile page looks polished, but there's no way for visitors to reach out to you. In this secret mission, you'll add an accessible contact form that introduces HTML form elements, the :focus pseudo-class, and accessibility best practices you'll use again when building React forms.
Clean Up Your Resources
Clean Up Your Resources
This project runs entirely locally, so there are no ongoing costs. Decide whether to keep your files for reference, or delete them entirely.
Resources you used:
- dev-profile folder on your Desktop (contains index.html and styles.css).
- Five Server extension installed in Cursor.
Keep everything running
No action needed. Choose this if you plan to continue to Project 2 (CSS Layout and Responsive Design), where you will add Flexbox, Grid, and media queries to this same page.
- Your dev-profile folder stays on your Desktop, ready for the next project.
- The Five Server extension remains installed in Cursor for live-reloading in future projects.
Pause - I'll come back to this later
Stop the Five Server to free up the port it uses. Your files stay on disk so you can pick up where you left off.
- In Cursor, click the port number shown in the bottom status bar to stop Five Server.
- Close the browser tab showing your profile page.
- Your dev-profile folder remains on your Desktop for when you return.
Delete - I don't want to use this again
Remove all project files and the extension to start completely fresh.
- Stop Five Server by clicking the port number in the bottom status bar.
- Close the browser tab showing your profile page.
- Delete the project folder by running this command on macOS/Linux:
rm -rf ~/Desktop/dev-profile
On Windows, run this instead:
rmdir /s /q "$HOME\Desktop\dev-profile"
- To uninstall the Five Server extension, open the Extensions panel in Cursor with Ctrl+Shift+X.
- Search for Five Server, click on it, then click Uninstall.
Nice Work!
Nice Work!
You just built a complete Developer Profile Page from scratch using only HTML and CSS. Every element on the page and every style rule exists because you wrote it and understand what it does.
You've learned how to:
- Build a complete HTML document using semantic elements (header, main, section, article, footer) and content elements (headings, paragraphs, links, images, lists) that communicate page structure to browsers and screen readers.
- Create a CSS stylesheet using element, class, ID, and descendant selectors and apply the box model (margin, padding, border, content) to control spacing and layout.
- Style typography with font properties, color values, and relative units, then add interactive feedback with :hover and :focus pseudo-classes.
- Secret Mission: Built an accessible contact form with styled form elements and focus states.
Ready to quiz yourself?