Styling forms and buttons
Forms let people interact with a website.
They can type a message, join a newsletter, choose an option, or submit contact details. Plain HTML forms work, but browser defaults often look different across devices and browsers.
CSS helps you make forms clearer, easier to scan, and more comfortable to use.
Quick reminder: form elements
Before styling forms, remember the common HTML tags:
<form>wraps the whole form.<label>explains what a field is for.<input>creates a field for typing, choosing, or checking something.<textarea>creates a larger multi-line text field.<button>creates a clickable action.
Labels are especially important. A label's for attribute should match the input's id.
<label for="email">Email</label> <input id="email" type="email" />This connection helps screen readers, and it lets users click the label to focus the input.
You can also connect a label by wrapping the input inside the label. You will see that pattern later with a checkbox.
Styling labels
Labels should be easy to read and close to the field they describe.
By default, labels are inline. For simple forms, it is often cleaner to place each label above its field with display: block.
<label for="name">Name</label>
<input id="name" type="text" placeholder="Enter your name" />
<style>
label {
display: block;
margin-bottom: 6px;
font-family: Arial, sans-serif;
font-weight: bold;
}
input {
padding: 10px;
}
</style>Use margin on the label or input to create space between form rows.
Styling text inputs
Text inputs usually need width, padding, border, and font styles.
Padding makes the typed text feel less cramped. Borders show the shape of the field. box-sizing: border-box keeps padding inside the width you set.
<input class="text-field" type="text" placeholder="Course name" />
<style>
.text-field {
box-sizing: border-box;
width: 100%;
max-width: 320px;
padding: 10px 12px;
border: 1px solid #9ca3af;
border-radius: 6px;
font-family: Arial, sans-serif;
font-size: 1rem;
}
</style>Use rem for text size when possible so the field can respect the visitor's browser font settings.
Styling placeholder text
A placeholder is the hint text inside an empty field.
You can style it with the ::placeholder pseudo-element.
Do not use placeholders as the only label. Once the user types, the placeholder disappears.
Styling focus states
A field has focus when the user clicks into it or tabs to it with the keyboard.
Browsers show a default focus outline so users know where they are. You can keep the default, or replace it with your own clear focus style.
The :focus-visible pseudo-class is often useful for buttons because it usually appears for keyboard focus, not every mouse click.
<input class="focus-field" type="email" placeholder="you@example.com" />
<style>
.focus-field {
padding: 10px 12px;
border: 1px solid #9ca3af;
border-radius: 6px;
font-family: Arial, sans-serif;
font-size: 1rem;
}
.focus-field:focus {
border-color: #2563eb;
outline: 3px solid #bfdbfe;
}
</style>This rule changes the border and keeps a visible outline when the field is active.
Styling checkboxes
Checkboxes are different from text inputs.
Browsers and operating systems draw them in their own way, so fully custom checkboxes are more advanced. For beginners, keep the native checkbox and improve its spacing.
You can also use accent-color to set the checked color in modern browsers.
<label class="checkbox-row">
<input type="checkbox" />
Send me lesson updates
</label>
<style>
.checkbox-row {
display: flex;
gap: 8px;
align-items: center;
font-family: Arial, sans-serif;
}
.checkbox-row input {
accent-color: #2563eb;
}
</style>This keeps the checkbox familiar while making it fit your design.
Styling buttons
Buttons should look clickable.
Common button styles include padding, background color, text color, border, border radius, and cursor.
<button class="primary-button" type="button">Send message</button>
<style>
.primary-button {
padding: 10px 16px;
border: none;
border-radius: 6px;
background-color: #2563eb;
color: white;
font-family: Arial, sans-serif;
font-size: 1rem;
cursor: pointer;
}
.primary-button:hover {
background-color: #1d4ed8;
}
</style>Use :hover for mouse interaction. In full forms, also add a visible focus style so keyboard users can see which button is active.
Disabled buttons
A disabled button cannot be clicked.
In HTML, add the disabled attribute. In CSS, style :disabled so the button clearly looks unavailable.
<button class="save-button" type="button">Save</button>
<button class="save-button" type="button" disabled>Save</button>
<style>
.save-button {
padding: 10px 16px;
border: none;
border-radius: 6px;
background-color: #16a34a;
color: white;
font-family: Arial, sans-serif;
cursor: pointer;
}
.save-button:disabled {
background-color: #d1d5db;
color: #6b7280;
cursor: not-allowed;
}
.save-button:focus-visible {
outline: 3px solid #bbf7d0;
outline-offset: 2px;
}
</style>Do not rely only on color. The not-allowed cursor and muted text also help communicate the disabled state.
Default browser form styles
Browsers add default form styles so forms work even without CSS.
These defaults are useful, but they can look different in Chrome, Safari, Firefox, macOS, Windows, Android, and iOS. Setting your own spacing, borders, colors, and fonts makes the form feel more consistent.
Avoid removing every default style at once. Start with small, clear changes.
Runnable example: styled contact form
This example combines labels, text inputs, a checkbox, focus states, and buttons.
Try clicking or tabbing into the fields to see the focus style.
<form class="contact-form">
<label for="contact-name">Name</label>
<input id="contact-name" type="text" placeholder="Enter your name" />
<label for="contact-email">Email</label>
<input id="contact-email" type="email" placeholder="you@example.com" />
<label for="contact-message">Message</label>
<textarea id="contact-message" rows="4" placeholder="Write your message"></textarea>
<label class="checkbox-row">
<input type="checkbox" />
Send me a copy
</label>
<div class="button-row">
<button type="button">Send</button>
<button type="button" disabled>Disabled</button>
</div>
</form>
<style>
.contact-form {
max-width: 360px;
padding: 20px;
border: 1px solid #d1d5db;
border-radius: 8px;
background-color: #f9fafb;
font-family: Arial, sans-serif;
}
.contact-form label {
display: block;
margin-bottom: 6px;
font-weight: bold;
color: #111827;
}
.contact-form input[type="text"],
.contact-form input[type="email"],
.contact-form textarea {
box-sizing: border-box;
width: 100%;
margin-bottom: 14px;
padding: 10px 12px;
border: 1px solid #9ca3af;
border-radius: 6px;
font: inherit;
}
.contact-form input:focus,
.contact-form textarea:focus {
border-color: #2563eb;
outline: 3px solid #bfdbfe;
}
.contact-form textarea {
resize: vertical;
}
.contact-form .checkbox-row {
display: flex;
gap: 8px;
align-items: center;
margin-bottom: 16px;
font-weight: normal;
}
.contact-form .checkbox-row input {
accent-color: #2563eb;
}
.button-row {
display: flex;
gap: 10px;
flex-wrap: wrap;
}
.button-row button {
padding: 10px 16px;
border: none;
border-radius: 6px;
background-color: #2563eb;
color: white;
font: inherit;
cursor: pointer;
}
.button-row button:hover:not(:disabled) {
background-color: #1d4ed8;
}
.button-row button:focus-visible {
outline: 3px solid #bfdbfe;
outline-offset: 2px;
}
.button-row button:disabled {
background-color: #d1d5db;
color: #6b7280;
cursor: not-allowed;
}
</style>The form uses consistent spacing, visible focus states, and clear button states.
Common beginner mistakes
- Removing focus outlines without a replacement: keyboard users need to see which field is active.
- Forgetting to connect labels: use matching
forandidvalues, or wrap the input inside the label. - Using placeholders instead of labels: placeholders disappear when the user types.
- Forgetting
box-sizing: border-box: inputs withwidth: 100%and padding can overflow their container. - Over-styling checkboxes too early: start with spacing and
accent-colorbefore building custom controls.
Mini practice task
Look at this CSS rule:
What does box-sizing: border-box; help prevent in this input?
Check the quiz answers when you are ready.
Short quiz with answers
- Which label attribute connects a label to a matching input?
- Which pseudo-class styles a field when the user clicks or tabs into it?
- Why should you avoid using placeholder text as the only label?
Answers:
- The
forattribute. :focus.- Because placeholder text disappears when the user starts typing, and it is not a strong replacement for a real label.
Mini practice task answer: it keeps the padding inside the 100% width, so the input is less likely to overflow its container.
Small challenge
Style the comment form below.
Your goals:
- Make the
<textarea>full width with10pxof padding. - Add a visible
:focusstate that changes the textarea border color. - Make the button a full-width block with a black background and white text.
- Add a
:hoverstate that changes the button background to dark gray. - Add a clear
:focus-visiblestyle for the button.
<form class="challenge-form">
<label for="message">Your message</label>
<textarea id="message" rows="4" placeholder="Write your message"></textarea>
<button class="action-button" type="button">Send message</button>
</form>
<style>
.challenge-form {
max-width: 320px;
font-family: Arial, sans-serif;
}
.challenge-form label {
display: block;
margin-bottom: 8px;
font-weight: bold;
}
#message {
box-sizing: border-box;
margin-bottom: 12px;
border: 1px solid #9ca3af;
border-radius: 6px;
font: inherit;
resize: vertical;
/* Add width and padding */
}
#message:focus {
/* Add a border color and outline */
}
.action-button {
/* Add button layout and colors */
}
.action-button:hover {
/* Add hover background color */
}
.action-button:focus-visible {
/* Add a visible keyboard focus outline */
}
</style>Summary
- Forms collect user input.
- Labels explain fields and should be connected with
forandid. - Text inputs often need width, padding, border, border radius, and font styles.
- Placeholder text is a hint, not a replacement for a label.
- Focus states show which field is active.
- Native checkboxes are best kept simple for beginners.
- Buttons should have clear normal, hover, focus, and disabled states.
- Browser default form styles are useful, but custom CSS makes forms more consistent.