CSS Form Styling — Inputs, Focus, Icons, and Form Elements
Lesson 36: CSS Form Styling — Inputs, Focus, Icons, and Form Elements
Lesson Introduction
Every website you use — whether you are logging into your email, signing up for a service, placing an order, or filling in a contact form — uses HTML forms behind the scenes. But raw, unstyled HTML forms look plain, clunky, and unprofessional. That is where CSS form styling comes in.
In this lesson, you will learn how to take a basic HTML form and transform it into a polished, professional-looking interface that feels good to use. You will style text fields, dropdowns, buttons, checkboxes, labels, textareas, and more. You will learn how to give inputs a highlight when a user clicks on them (called focus), how to add little icons inside input fields, and how to style all the different pieces of a form to work together beautifully.
By the end of this lesson, you will have built a real, styled registration form from scratch — the kind you see on real websites every day.
Prerequisite Concepts
Before we begin styling forms, let us make sure you understand the building blocks. If any of these feel unfamiliar, read each mini-explanation carefully before continuing.
What is an HTML Form?
An HTML form is a section of a webpage that collects information from a user. Think of it like a paper questionnaire — it has blank spaces for you to fill in, options to choose from, and a button to submit your answers.
<form>
<label for="name">Your Name:</label>
<input type="text" id="name" name="name">
<button type="submit">Submit</button>
</form>
Output (unstyled): A plain text box with a label and a button — no colours, no spacing, no padding.
What is <input>?
The <input> element is the most common form element. It can be many different things depending on its type attribute:
type="text"→ a text box for typingtype="password"→ a text box that hides characterstype="email"→ a text box for email addressestype="submit"→ a clickable submit buttontype="checkbox"→ a small square you can ticktype="radio"→ a small circle for selecting one option from manytype="file"→ a button for uploading a file
What is <label>?
A <label> is the text description that tells the user what to type into an input. The for attribute of a <label> must match the id of the <input> it describes — this links them together.
<label for="email">Email Address:</label>
<input type="email" id="email" name="email">
What is <select> and <option>?
A <select> element creates a dropdown menu. Each <option> inside it is one choice in that dropdown.
<select name="country">
<option value="ng">Nigeria</option>
<option value="gh">Ghana</option>
<option value="za">South Africa</option>
</select>
What is <textarea>?
A <textarea> is a bigger text area for typing multiple lines of text — like a message box or a comments section.
<textarea name="message" rows="4" cols="40"></textarea>
What CSS Properties Will We Use?
You will use many CSS properties throughout this lesson. Here is a quick preview of the most important ones:
| Property | What It Does |
|---|---|
width |
Controls how wide the input is |
padding |
Adds space inside the input box |
margin |
Adds space outside the input box |
border |
Adds a line around the input |
border-radius |
Rounds the corners of the box |
background-color |
Sets the fill colour of the input |
color |
Sets the text colour inside the input |
font-size |
Controls how big the text is |
outline |
The glow or ring that appears when focused |
box-sizing |
Controls how padding affects the total width |
position |
Allows you to place icons inside inputs |
Part 1 — Conceptual Understanding: Why Style Forms at All?
Imagine you visit a website and the signup form looks like this: plain black-and-white boxes with no spacing, text crammed right to the edge, and a tiny submit button. You would probably leave immediately.
Now imagine the same form but with soft rounded corners, pleasant colours, breathing room (padding), and a glowing highlight when you click on a field. That feels much better — and you are more likely to trust it and fill it in.
Good form design matters because:
- It builds trust with your users.
- It guides users visually through the steps.
- It reduces errors (clear labels, good sizing).
- It makes your website look professional and polished.
CSS form styling is used in:
- Login and signup pages (every social media site)
- E-commerce checkout pages
- Contact and feedback forms
- Survey and quiz tools
- Job application forms
- Medical patient intake forms
Part 2 — Styling Form Input Fields
2.1 The Key CSS Properties for Inputs
The most commonly styled CSS properties for input fields are width, padding, margin, border, border-radius, background-color, color, and font-size.
Let us start with the most basic example and build from there.
Simple Example 1: Bare input vs. styled input
Without CSS (plain HTML):
<input type="text" placeholder="Type your name">
Output: A tiny, plain grey box — barely noticeable on the page.
With basic CSS:
<style>
input[type="text"] {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 16px;
}
</style>
<input type="text" placeholder="Type your name">
Output: A wide, comfortably padded input box with a light grey border and rounded corners. Much more readable and clickable.
Line-by-Line Explanation
Let us break down every single part of the CSS above:
input[type="text"] {
This is an attribute selector. It means: “target only <input> elements that have type="text".” This is important because styling plain input would also affect buttons and checkboxes.
width: 100%;
Makes the input stretch to fill 100% of the width of its container. This means if the container is 400px wide, the input is 400px wide. Think of it like a rubber band that stretches to fit.
padding: 12px 20px;
Adds 12px of breathing room above and below the text, and 20px of breathing room on the left and right. Without padding, text would be jammed right against the edge of the box.
margin: 8px 0;
Adds 8px of space above and below the input (outside the box), so inputs don’t stack directly on top of each other.
border: 1px solid #ccc;
Draws a thin (1px), solid, light grey (#ccc) border around the input box.
border-radius: 4px;
Gently rounds the four corners of the input. The higher the value, the more rounded. 4px gives a subtle but modern look.
font-size: 16px;
Sets the text inside the input to 16px. This is important — many browsers default to a small font that can be hard to read.
💡 Tip: Always set a font-size on inputs. Browsers often display text inside inputs in a different, smaller size than your page text unless you set it explicitly.
2.2 The box-sizing Property — A Critical Detail
Here is a common beginner confusion. Look at this:
input {
width: 100%;
padding: 12px 20px;
border: 1px solid #ccc;
}
You might expect the input to be exactly 100% wide. But actually, it would overflow! Why? Because by default, CSS calculates width without including padding and border. So:
- Your
width: 100%means the inner content area is 100% wide. - Then padding (20px left + 20px right = 40px) and border (1px + 1px = 2px) are added on top.
- Total actual width = 100% + 42px. That overflows!
The fix: box-sizing: border-box
input {
box-sizing: border-box; /* Now padding and border are included INSIDE the width */
width: 100%;
padding: 12px 20px;
border: 1px solid #ccc;
}
Output: The input is now exactly 100% wide — the padding and border are absorbed into that 100%, not added on top. Think of it like packing things inside a box: border-box means the lid still fits, no overflow.
💡 Best practice: Many developers put
box-sizing: border-boxon every element at the top of their CSS to avoid this confusion:* { box-sizing: border-box; }
2.3 Styling Specific Input Types
You do not have to style all inputs the same way. You can target each type specifically.
Example: Different styles for text and password inputs
<style>
input[type="text"],
input[type="email"],
input[type="password"] {
width: 100%;
padding: 10px 15px;
margin-bottom: 12px;
border: 2px solid #ddd;
border-radius: 6px;
font-size: 15px;
background-color: #f9f9f9;
color: #333;
}
input[type="submit"] {
width: 100%;
padding: 12px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 6px;
font-size: 16px;
cursor: pointer;
}
</style>
<input type="text" placeholder="Full Name">
<input type="email" placeholder="Email Address">
<input type="password" placeholder="Password">
<input type="submit" value="Create Account">
Output:
- Text, email, and password fields: wide, padded, light grey background, dark text, rounded.
- Submit button: full-width, green background, white text — clearly a button.
What cursor: pointer does: When the user hovers over the submit button, the mouse cursor changes to a hand (pointing finger), signalling it is clickable. Without this, the cursor stays as an arrow, which feels wrong on a button.
🤔 Thinking Prompt: What would happen if you removed
background-color: #f9f9f9from the inputs? Try picturing it — the background would revert to the browser’s default (usually white or light grey). The form would still work, but it would feel less custom.
2.4 Styling <select> Dropdowns
Select elements are often tricky because they look very different across browsers by default. You can bring them under control with CSS.
<style>
select {
width: 100%;
padding: 10px 15px;
border: 2px solid #ddd;
border-radius: 6px;
font-size: 15px;
background-color: #f9f9f9;
color: #333;
appearance: none; /* Removes default browser arrow styling */
}
</style>
<select name="country">
<option>Nigeria</option>
<option>Ghana</option>
<option>South Africa</option>
</select>
Output: A clean dropdown that matches your other input fields, with consistent padding, border, and colours.
What appearance: none does: By default, every browser adds its own style to <select> elements — custom arrows, backgrounds, colours. appearance: none strips all of that away, giving you a clean slate to style from scratch.
2.5 Styling <textarea> (Multi-line Input)
A textarea is like a bigger version of a text input. It should be styled consistently with your other inputs.
<style>
textarea {
width: 100%;
padding: 12px 15px;
border: 2px solid #ddd;
border-radius: 6px;
font-size: 15px;
resize: vertical; /* Only allows resizing up and down, not sideways */
font-family: inherit; /* Matches the font of the rest of the page */
}
</style>
<textarea rows="5" placeholder="Write your message here..."></textarea>
Output: A multi-line input box that matches your other fields and can only be resized vertically.
What resize: vertical does: By default, textareas can be resized by the user in any direction — up, down, left, right. This can break your layout. resize: vertical restricts resizing to up and down only, which is almost always what you want.
What font-family: inherit does: Inputs and textareas have their own default font (often a system monospace font). inherit means “use the same font as the rest of the page.” This makes everything look consistent.
Part 3 — Styling Labels
Labels are just as important as inputs! If labels look bad, the whole form suffers.
<style>
label {
display: block; /* Makes label take its own line */
margin-bottom: 5px; /* Space between label and input */
font-weight: bold; /* Makes the label text bold */
font-size: 14px;
color: #333;
}
</style>
<label for="name">Full Name</label>
<input type="text" id="name" name="name" placeholder="e.g. Amara Okafor">
Output: A bold, dark label sits on its own line above the input.
Why display: block? By default, <label> is an inline element — it sits on the same line as the input. display: block forces it onto its own line, stacking the label above the input. This is the most common form layout.
💡 Tip: Always pair a label’s
forattribute with the input’sid. This is not just good practice — it makes the label clickable! Clicking the label automatically focuses (activates) the input. This greatly improves accessibility.
Part 4 — The :focus Pseudo-Class: Highlighting Active Inputs
What is Focus?
When you click on an input field to start typing, that field is said to have focus. It is the active element. By default, browsers show a basic blue ring around focused elements.
The :focus pseudo-class lets you completely control what happens when a user clicks on (focuses) an input.
Why does focus styling matter?
- It tells the user: “this is the field you are currently typing in”
- It improves accessibility for keyboard navigation
- It makes forms feel polished and interactive
Think of it like a spotlight: when an actor steps into the spotlight on stage, the audience knows exactly where to look. Focus styling is your spotlight.
Simple Example: Blue glow on focus
<style>
input[type="text"] {
width: 100%;
padding: 10px 15px;
border: 2px solid #ccc;
border-radius: 6px;
font-size: 15px;
transition: border-color 0.3s ease; /* Smooth colour change */
}
input[type="text"]:focus {
border-color: #4a90e2;
outline: none;
}
</style>
<input type="text" placeholder="Click me to see focus styling">
Output (before clicking): A plain input with a light grey border. Output (after clicking): The border turns blue — the input glows visually to show it is active.
Line-by-Line Explanation
input[type="text"]:focus {
The :focus pseudo-class. This CSS only applies when the input is currently active (clicked or tabbed into). At all other times, it is ignored.
border-color: #4a90e2;
Changes the border colour from light grey to a pleasant blue. This is the “glow” effect — the border colour switches when focused.
outline: none;
This removes the default browser focus ring (the blue ring that browsers add automatically). We remove it because we are replacing it with our own, better-looking border colour change.
⚠️ Important Warning: Never use
outline: nonewithout providing your own visible focus indicator! If you remove the default focus ring and add nothing back, users who navigate by keyboard (including people with disabilities) will have no idea which element is active. Always replace the outline with something visible — a changed border colour, a box shadow, or a different background.
Example: Using box-shadow for a glowing ring
<style>
input[type="text"]:focus {
border-color: #4a90e2;
outline: none;
box-shadow: 0 0 8px rgba(74, 144, 226, 0.6);
}
</style>
Output: When clicked, the input gets a soft blue glowing ring around it, like a soft halo. This is a very popular modern design technique.
Breaking down box-shadow: 0 0 8px rgba(74, 144, 226, 0.6):
0→ no horizontal shadow offset0→ no vertical shadow offset8px→ how spread/blurry the shadow isrgba(74, 144, 226, 0.6)→ blue colour at 60% opacity (the glow colour)
The transition Property for Smooth Animations
Notice the transition: border-color 0.3s ease in the base style. This is what makes the colour change feel smooth instead of instant.
transition: border-color 0.3s ease;
border-color→ which property to animate (the border colour)0.3s→ how long the animation takes (0.3 seconds — fast but visible)ease→ starts slowly, speeds up in the middle, slows at the end (natural feeling)
Without transition, the border would snap instantly from grey to blue. With it, it smoothly fades. Always add transitions to focus effects for a polished feel.
🤔 Thinking Prompt: What do you think would happen if you changed
0.3sto2s? The colour change would take 2 full seconds — very slow and annoying. Transitions should be quick. 0.2s–0.4s is the sweet spot for form interactions.
Part 5 — Adding Icons Inside Input Fields
A very popular modern UI pattern is adding small icons inside input fields — like a magnifying glass icon inside a search box, an envelope icon in an email field, or a lock icon in a password field. These make forms immediately recognisable and professional-looking.
How Do Icons Inside Inputs Work?
HTML inputs cannot directly contain other elements like icons. Instead, the technique uses:
- A wrapping
<div>that is styled asposition: relative - An icon element placed inside that
<div>withposition: absolute - The input is padded on the left to make room for the icon
Think of it like this: the wrapper is a picture frame. The input fills the frame. The icon is a sticker placed precisely on top of the frame corner using position: absolute.
Example: Input with an icon using Font Awesome
First, you need a free icon library. Font Awesome is one of the most popular. To use it, include this line in your HTML <head>:
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css">
Now here is the full example:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css">
<style>
.input-wrapper {
position: relative; /* Makes this the reference point for the icon */
margin-bottom: 15px;
}
.input-wrapper i {
position: absolute; /* Positions icon relative to the wrapper */
left: 12px; /* 12px from the left edge */
top: 50%; /* Vertically centre */
transform: translateY(-50%); /* Fine-tune the vertical centring */
color: #888; /* Light grey icon colour */
}
.input-wrapper input {
width: 100%;
padding: 10px 10px 10px 40px; /* Extra left padding = space for icon */
border: 2px solid #ddd;
border-radius: 6px;
font-size: 15px;
box-sizing: border-box;
}
</style>
</head>
<body>
<div class="input-wrapper">
<i class="fa fa-envelope"></i>
<input type="email" placeholder="Enter your email">
</div>
<div class="input-wrapper">
<i class="fa fa-lock"></i>
<input type="password" placeholder="Enter your password">
</div>
</body>
</html>
Output: An email field with a small grey envelope icon inside the left side, and a password field with a grey lock icon. The text starts after the icon, keeping everything neat.
Step-by-Step Breakdown
Step 1 — The wrapper <div>:
<div class="input-wrapper">
This container holds both the icon and the input. It has position: relative, which is essential. Without it, position: absolute on the icon would not work correctly.
Step 2 — The icon:
<i class="fa fa-envelope"></i>
Font Awesome uses <i> tags with class names like fa fa-envelope to display icons. The fa prefix tells Font Awesome to render the icon.
Step 3 — Positioning the icon:
.input-wrapper i {
position: absolute;
left: 12px;
top: 50%;
transform: translateY(-50%);
}
position: absolute→ takes the icon out of normal flow, allows precise placementleft: 12px→ places icon 12px from the left edge of the wrappertop: 50%→ moves icon 50% down from the top of the wrappertransform: translateY(-50%)→ shifts it back up by half its own height, perfectly centring it vertically
Step 4 — Making room for the icon:
padding: 10px 10px 10px 40px; /* Top Right Bottom Left */
The left padding is 40px — much larger than the other sides. This pushes the typed text to the right, starting after the icon. Without this, text would overlap the icon.
💡 Tip: Always make the left padding at least as wide as the icon plus a little gap. If your icon is 20px wide and you want 10px of space, use
40pxof left padding.
Part 6 — Styling Other Form Elements
6.1 Styling <button> and Submit Inputs
Buttons are a critical part of any form. A well-styled button clearly signals “click here to complete the action.”
<style>
button,
input[type="submit"] {
background-color: #4CAF50; /* Green */
color: white;
padding: 14px 20px;
border: none;
border-radius: 6px;
cursor: pointer;
font-size: 16px;
width: 100%;
transition: background-color 0.3s ease;
}
button:hover,
input[type="submit"]:hover {
background-color: #45a049; /* Slightly darker green on hover */
}
</style>
<button type="submit">Submit Form</button>
Output: A wide green button. When you hover over it, it darkens slightly — giving visual feedback that it’s interactive.
What :hover does: This pseudo-class activates when the mouse hovers over the element. The background colour changes, giving the user a clear signal the button is clickable.
Why border: none? Buttons have a default browser border. Removing it gives you a clean, flat modern look.
6.2 Styling Checkboxes and Radio Buttons
Native checkboxes and radio buttons are very difficult to style with CSS alone because browsers control most of their appearance. However, you can make small adjustments, and for full custom styling, we often use a label trick.
Basic sizing and cursor:
input[type="checkbox"],
input[type="radio"] {
width: 16px;
height: 16px;
cursor: pointer;
accent-color: #4CAF50; /* Changes the tick/fill colour in modern browsers */
}
Output: Slightly larger checkboxes and radio buttons with a green tick/dot when checked.
What accent-color does: This modern CSS property (supported in all major browsers since 2022) lets you change the colour of form control accents — the tick in a checkbox, the dot in a radio button, the fill of a range slider. It is the easiest way to colour checkboxes without complex custom code.
6.3 Styling the Form Container
The form itself should be contained in a styled box to look polished.
<style>
.form-container {
background-color: white;
padding: 30px;
border-radius: 10px;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); /* Soft drop shadow */
max-width: 500px;
margin: 40px auto; /* Centres the form on the page */
}
</style>
<div class="form-container">
<!-- Your form goes here -->
</div>
Output: A white card with rounded corners, a soft shadow, centred on the page with margins. This is the standard “card” form style used on most modern websites.
Breaking down box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1):
0→ no horizontal shadow4px→ shadow is 4px lower than the element (like light coming from above)15px→ how blurry/spread the shadow isrgba(0, 0, 0, 0.1)→ black at 10% opacity — very subtle shadow
6.4 Full Styled Form Container Example
Putting it all together:
<!DOCTYPE html>
<html>
<head>
<style>
body {
background-color: #f0f2f5;
font-family: Arial, sans-serif;
}
.form-container {
background-color: white;
padding: 30px;
border-radius: 10px;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
max-width: 450px;
margin: 40px auto;
}
h2 {
text-align: center;
margin-bottom: 20px;
color: #333;
}
label {
display: block;
margin-bottom: 5px;
font-weight: bold;
font-size: 14px;
color: #555;
}
input[type="text"],
input[type="email"],
input[type="password"],
select,
textarea {
width: 100%;
padding: 10px 15px;
margin-bottom: 15px;
border: 2px solid #ddd;
border-radius: 6px;
font-size: 15px;
box-sizing: border-box;
transition: border-color 0.3s ease;
}
input:focus,
select:focus,
textarea:focus {
border-color: #4a90e2;
outline: none;
}
input[type="submit"] {
width: 100%;
padding: 12px;
background-color: #4a90e2;
color: white;
border: none;
border-radius: 6px;
font-size: 16px;
cursor: pointer;
transition: background-color 0.3s ease;
}
input[type="submit"]:hover {
background-color: #357abd;
}
</style>
</head>
<body>
<div class="form-container">
<h2>Create Account</h2>
<label for="fullname">Full Name</label>
<input type="text" id="fullname" placeholder="e.g. Amara Okafor">
<label for="email">Email Address</label>
<input type="email" id="email" placeholder="e.g. amara@email.com">
<label for="password">Password</label>
<input type="password" id="password" placeholder="At least 8 characters">
<label for="country">Country</label>
<select id="country">
<option>Nigeria</option>
<option>Ghana</option>
<option>Kenya</option>
<option>South Africa</option>
</select>
<input type="submit" value="Create Account">
</div>
</body>
</html>
Expected Output:
- A white card form, centred on a soft grey page background
- All inputs are wide, padded, with rounded corners and a soft grey border
- Clicking any input turns its border blue
- The submit button is blue and darkens when hovered
Part 7 — Guided Practice Exercises
Exercise 1: Style a Login Form
Objective: Create a fully styled login form with email, password, and submit button.
Scenario: You are building the login page for a student portal at a university.
Steps:
- Create an HTML file called
login.html - Add a
<div>container with a.form-boxclass - Style
.form-boxwith white background, padding, shadow, and max-width - Add a heading: “Student Portal Login”
- Add
label+input[type="email"]pair for email - Add
label+input[type="password"]pair for password - Add
input[type="submit"]styled as a button - Add
:focusstyling to inputs
Hints:
- Use
box-shadow: 0 4px 15px rgba(0,0,0,0.1)for the card shadow - Use
border-colorchange on:focus - Use
cursor: pointeron the submit button
Expected Output: A clean, centred login card with polished inputs and a visible focus effect.
Self-check Questions:
- Does clicking the email field change the border colour?
- Is the submit button wide enough to feel clickable?
- Does the form sit in the centre of the page?
Optional Challenge: Add a “Forgot Password?” text link below the submit button styled in a lighter colour.
Exercise 2: Style a Contact Form
Objective: Style a contact form with name, email, subject (dropdown), and message (textarea).
Scenario: You are styling the contact page for a small business website.
Steps:
- Create a form with four fields: name (text), email (email), subject (select), message (textarea)
- Style all fields consistently with the same border, padding, and font-size
- Make the textarea have 5 rows and be
resize: vertical - Add a green submit button
- Add
:hoverand:focusstates
Expected Output: A consistent four-field form where all elements look visually identical in style, only differing in shape (textarea is taller).
Self-check Questions:
- Does the select dropdown match the styling of the text inputs?
- Can the textarea only be resized vertically?
- Does the button change colour on hover?
Part 8 — Mini Project: Professional Registration Form
In this project, you will build a complete registration form from scratch — the kind used on actual websites for account creation.
Project Overview
Goal: Build a styled registration form for a fictional learning platform called “LearnPath”.
Fields needed:
- First Name and Last Name (side by side)
- Email Address (with envelope icon)
- Password (with lock icon)
- Confirm Password
- Country (dropdown)
- Course of Interest (dropdown)
- Short Bio (textarea)
- Terms of Service checkbox
- Submit button
Stage 1 — Setup
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>LearnPath Registration</title>
<link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css">
<style>
/* Reset and base */
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
background-color: #eef2f7;
font-family: 'Segoe UI', Arial, sans-serif;
color: #333;
}
</style>
</head>
<body>
<!-- Stage 2 content goes here -->
</body>
</html>
Milestone Output: A clean page with a grey background and no content yet.
Stage 2 — Form Container
Add this CSS to your <style> block, and the container HTML to <body>:
/* Form card container */
.register-card {
max-width: 580px;
margin: 40px auto;
background-color: white;
padding: 40px;
border-radius: 12px;
box-shadow: 0 6px 25px rgba(0, 0, 0, 0.1);
}
.register-card h1 {
text-align: center;
margin-bottom: 8px;
color: #2c3e50;
font-size: 26px;
}
.register-card p.subtitle {
text-align: center;
color: #777;
margin-bottom: 28px;
font-size: 14px;
}
<div class="register-card">
<h1>Join LearnPath</h1>
<p class="subtitle">Create your free account and start learning today</p>
<!-- Form goes here in Stage 3 -->
</div>
Milestone Output: A white card appears centred on the grey page with the heading and subtitle.
Stage 3 — Form Fields
Add all labels, inputs, select, and textarea:
/* Labels */
label {
display: block;
font-size: 13px;
font-weight: 600;
color: #555;
margin-bottom: 5px;
}
/* All standard inputs, select, and textarea */
input[type="text"],
input[type="email"],
input[type="password"],
select,
textarea {
width: 100%;
padding: 11px 14px;
border: 2px solid #ddd;
border-radius: 8px;
font-size: 15px;
color: #333;
background-color: #fafafa;
transition: border-color 0.25s ease, box-shadow 0.25s ease;
margin-bottom: 18px;
}
/* Focus state */
input[type="text"]:focus,
input[type="email"]:focus,
input[type="password"]:focus,
select:focus,
textarea:focus {
outline: none;
border-color: #5b8dee;
box-shadow: 0 0 0 3px rgba(91, 141, 238, 0.2);
background-color: white;
}
/* Side-by-side name fields */
.name-row {
display: flex;
gap: 15px;
}
.name-row > div {
flex: 1;
}
/* Input with icon wrapper */
.input-icon-wrapper {
position: relative;
margin-bottom: 18px;
}
.input-icon-wrapper i {
position: absolute;
left: 13px;
top: 50%;
transform: translateY(-50%);
color: #aaa;
font-size: 14px;
}
.input-icon-wrapper input {
padding-left: 38px;
margin-bottom: 0;
}
/* Textarea */
textarea {
resize: vertical;
min-height: 100px;
font-family: inherit;
}
/* Checkbox row */
.checkbox-row {
display: flex;
align-items: center;
gap: 10px;
margin-bottom: 20px;
}
.checkbox-row input[type="checkbox"] {
width: 18px;
height: 18px;
accent-color: #5b8dee;
cursor: pointer;
}
.checkbox-row label {
margin: 0;
font-weight: normal;
font-size: 14px;
}
/* Submit button */
input[type="submit"] {
width: 100%;
padding: 14px;
background-color: #5b8dee;
color: white;
border: none;
border-radius: 8px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: background-color 0.3s ease, transform 0.1s ease;
}
input[type="submit"]:hover {
background-color: #4a7de0;
}
input[type="submit"]:active {
transform: scale(0.98); /* Slight shrink when clicked */
}
<form>
<!-- First and Last Name side by side -->
<div class="name-row">
<div>
<label for="firstname">First Name</label>
<input type="text" id="firstname" placeholder="e.g. Amara">
</div>
<div>
<label for="lastname">Last Name</label>
<input type="text" id="lastname" placeholder="e.g. Okafor">
</div>
</div>
<!-- Email with icon -->
<label for="email">Email Address</label>
<div class="input-icon-wrapper">
<i class="fa fa-envelope"></i>
<input type="email" id="email" placeholder="amara@example.com">
</div>
<!-- Password with icon -->
<label for="password">Password</label>
<div class="input-icon-wrapper">
<i class="fa fa-lock"></i>
<input type="password" id="password" placeholder="Min. 8 characters">
</div>
<!-- Confirm Password -->
<label for="confirm">Confirm Password</label>
<div class="input-icon-wrapper">
<i class="fa fa-check-circle"></i>
<input type="password" id="confirm" placeholder="Repeat your password">
</div>
<!-- Country dropdown -->
<label for="country">Country</label>
<select id="country">
<option value="">-- Select your country --</option>
<option>Nigeria</option>
<option>Ghana</option>
<option>Kenya</option>
<option>South Africa</option>
<option>Senegal</option>
<option>Ethiopia</option>
</select>
<!-- Course dropdown -->
<label for="course">Course of Interest</label>
<select id="course">
<option value="">-- Select a course --</option>
<option>Web Development</option>
<option>Data Science</option>
<option>UI/UX Design</option>
<option>Mobile App Development</option>
<option>Cybersecurity</option>
</select>
<!-- Bio textarea -->
<label for="bio">Short Bio (Optional)</label>
<textarea id="bio" rows="4"
placeholder="Tell us a little about yourself and your learning goals..."></textarea>
<!-- Terms checkbox -->
<div class="checkbox-row">
<input type="checkbox" id="terms">
<label for="terms">I agree to the Terms of Service and Privacy Policy</label>
</div>
<!-- Submit button -->
<input type="submit" value="Create My Account">
</form>
Final Expected Output: A polished, professional registration form that includes:
- Two name fields side by side
- Email with envelope icon, passwords with lock icons
- Consistent dropdown styling
- A resizable textarea
- A styled checkbox with terms text
- A blue button that darkens on hover and slightly shrinks when clicked
Stage 4 — Reflection Questions
- Why did we use
position: relativeon.input-icon-wrapperandposition: absoluteon the icon? - What does
flex: 1on.name-row > divdo? (Hint: it makes both halves share space equally.) - What would happen if you removed
box-sizing: border-boxfrom the*selector? - Why do we use
transitionon the focus styles? - Why is it important that our
:focusstyle still shows something even after removingoutline: none?
Optional Advanced Extensions
- Add a “Show/Hide Password” toggle button next to the password field using JavaScript
- Make the form responsive — on mobile screens, the name fields should stack vertically (use
@mediaquery) - Add a colour-coded strength indicator below the password field
- Add a profile picture upload with
input[type="file"]
Common Beginner Mistakes
Mistake 1: Forgetting box-sizing: border-box
Wrong:
input {
width: 100%;
padding: 15px;
border: 2px solid #ccc;
}
Problem: The input overflows its container because padding and border add to the total width.
Correct:
* { box-sizing: border-box; }
input {
width: 100%;
padding: 15px;
border: 2px solid #ccc;
}
Mistake 2: Removing outline Without a Replacement
Wrong:
input:focus {
outline: none;
}
Problem: Users who navigate by keyboard cannot see which field is active. This breaks accessibility.
Correct:
input:focus {
outline: none;
border-color: #4a90e2; /* Visible replacement focus indicator */
box-shadow: 0 0 0 3px rgba(74, 144, 226, 0.3);
}
Mistake 3: Not Using font-family: inherit on Inputs
Wrong:
textarea {
width: 100%;
padding: 10px;
}
Problem: Textarea might use a monospace or system font that doesn’t match your page.
Correct:
textarea {
width: 100%;
padding: 10px;
font-family: inherit; /* Use same font as the rest of the page */
}
Mistake 4: Using input Instead of input[type="text"]
Wrong:
input {
border-radius: 8px;
padding: 10px;
}
Problem: This styles ALL inputs — including checkboxes and submit buttons. Checkboxes with border-radius and padding look very strange.
Correct:
input[type="text"],
input[type="email"],
input[type="password"] {
border-radius: 8px;
padding: 10px;
}
Mistake 5: Forgetting cursor: pointer on Buttons
Wrong:
input[type="submit"] {
background-color: green;
color: white;
}
Problem: When hovering, the cursor remains an arrow — it doesn’t feel like a clickable button.
Correct:
input[type="submit"] {
background-color: green;
color: white;
cursor: pointer;
}
Mistake 6: Not Linking Labels to Inputs
Wrong:
<label>Email</label>
<input type="email">
Problem: The label is not linked to the input. Clicking the label won’t focus the input. Screen readers cannot associate them.
Correct:
<label for="email">Email</label>
<input type="email" id="email">
Reflection Questions
- What is the difference between
paddingandmarginwhen applied to an input field? - Why would you use
input[type="text"]:focusinstead of justinput:focus? - You want to add a search icon to the right side of an input instead of the left. What CSS changes would you need to make to the icon and input padding?
- What problem does
appearance: nonesolve on<select>elements? - Why is
transitionimportant for good UX on form focus effects? - When would you use a
<textarea>instead of<input type="text">? - What is the purpose of the
forattribute on a<label>element? - If you set
resize: noneon a textarea, what does that do?
Completion Checklist
Before moving to the next lesson, confirm you can do all of the following:
- Style
<input>fields withwidth,padding,border,border-radius, andfont-size - Use
box-sizing: border-boxto prevent overflow - Style specific input types using
input[type="text"],input[type="email"], etc. - Apply
:focusstyling with a visible focus indicator (border colour or box-shadow) - Remove the default
outlinesafely (only when replacing with something visible) - Use
transitionto animate focus changes smoothly - Add icons inside inputs using
position: relative/absolutetechnique - Style
<select>dropdowns and<textarea>consistently with inputs - Style
<button>andinput[type="submit"]with:hovereffects - Use
accent-colorfor basic checkbox/radio button styling - Build a complete styled form card with container, labels, inputs, and submit button
- Link labels to inputs using
forandid - Identify and fix the six common beginner mistakes listed above
Lesson Summary
In this lesson, you went from raw, unstyled HTML form elements to a professionally designed, interactive form. Here is a recap of everything you learned:
Styling inputs: Use width, padding, margin, border, border-radius, background-color, color, and font-size to control the appearance of input fields. Target specific input types with input[type="text"] to avoid accidentally styling checkboxes and buttons.
box-sizing: border-box: Always apply this to prevent inputs from overflowing their container when padding and borders are added.
Focus styling (:focus): The :focus pseudo-class lets you change how an input looks when the user clicks on it. Always provide a visible focus indicator — change the border colour, add a box-shadow glow, or both. Never just remove outline without a replacement.
Smooth transitions: Add transition: border-color 0.3s ease (or similar) to make focus effects animate smoothly instead of snapping instantly.
Icons inside inputs: Use a wrapper <div> with position: relative, an icon with position: absolute, and extra padding-left on the input to make room. This technique is used on nearly every modern web form.
Other elements: Style <select> dropdowns with appearance: none and your own CSS. Style <textarea> with resize: vertical and font-family: inherit. Style buttons with :hover and :active states. Style checkboxes easily with accent-color.
Form container: Wrap your form in a styled card with background-color, padding, border-radius, box-shadow, and max-width to create the clean “card form” look used on professional websites worldwide.
With all of these tools, you can now build and style beautiful, functional forms that look great, work correctly for all users, and create a great first impression on any website.
Sources: W3Schools CSS Forms, CSS Form Inputs, CSS Form Focus, CSS Form Elements, and CSS Form Challenges — rewritten as a comprehensive beginner lesson.