Buttons are essential form controls that allow users to submit forms, reset fields, or trigger custom actions. HTML provides multiple ways to create buttons, each with specific purposes and behaviors. Understanding when and how to use each type is crucial for effective form design.
Types of Form Buttons
There are three main types of buttons in HTML forms:
- Submit buttons: Submit the form data to the server
- Reset buttons: Clear all form fields to their default values
- Regular buttons: Trigger custom JavaScript actions
Submit Buttons
Submit buttons are the most common type. They trigger form submission, sending data to the server specified in the form's action attribute.
Using the button Element (Recommended)
<form action="/submit" method="post">
<label for="email">Email:</label>
<input type="email" id="email" name="email" required>
<!-- Recommended: button element -->
<button type="submit">Submit Form</button>
</form>
<!-- With icon or custom content -->
<button type="submit">
<span>✓</span> Submit Form
</button>
<!-- With emoji -->
<button type="submit">
🚀 Launch
</button>Using the input Element
<form action="/submit" method="post">
<label for="username">Username:</label>
<input type="text" id="username" name="username">
<!-- Alternative: input element -->
<input type="submit" value="Submit Form">
</form>
<!-- Custom text -->
<input type="submit" value="Send Message">
<input type="submit" value="Register Now">
<input type="submit" value="Place Order">💡 Button vs Input:
The <button> element is more flexible—it can contain HTML content like icons, images, or formatted text. The <input> element can only display plain text. Generally, use <button> for better styling options.
Reset Buttons
Reset buttons clear all form fields, returning them to their default values. Use these sparingly as they can frustrate users who accidentally click them.
<form>
<label for="name">Name:</label>
<input type="text" id="name" name="name" value="John Doe">
<label for="email">Email:</label>
<input type="email" id="email" name="email">
<!-- button element reset -->
<button type="reset">Reset Form</button>
<!-- input element reset -->
<input type="reset" value="Clear All">
</form>Reset buttons can be frustrating for users because they erase all entered data instantly without confirmation. Consider using a "Clear Form" button with a confirmation dialog instead, or avoid reset buttons entirely in most cases.
Regular Buttons
Regular buttons with type="button" don't submit or reset the form. They're used with JavaScript for custom functionality.
<form>
<label for="quantity">Quantity:</label>
<input type="number" id="quantity" name="quantity" value="1" min="1">
<!-- Regular buttons for custom actions -->
<button type="button" onclick="increaseQuantity()">+</button>
<button type="button" onclick="decreaseQuantity()">-</button>
<button type="submit">Add to Cart</button>
</form>
<script>
function increaseQuantity() {
const input = document.getElementById('quantity');
input.value = parseInt(input.value) + 1;
}
function decreaseQuantity() {
const input = document.getElementById('quantity');
if (parseInt(input.value) > 1) {
input.value = parseInt(input.value) - 1;
}
}
</script>Important Button Attributes
type
The type attribute defines the button's behavior. Always specify the type explicitly.
<!-- Submit button (submits form) -->
<button type="submit">Submit</button>
<!-- Reset button (resets form) -->
<button type="reset">Reset</button>
<!-- Regular button (no default action) -->
<button type="button">Click Me</button>
<!-- Default: if type is not specified, button acts as submit -->
<button>This submits the form</button>disabled
Disable a button so users can't interact with it. Useful when form isn't ready or during processing.
<!-- Disabled button -->
<button type="submit" disabled>Submit</button>
<!-- Enable/disable based on conditions -->
<form id="myForm">
<input type="checkbox" id="terms" onchange="toggleSubmit()">
<label for="terms">I agree to terms</label>
<button type="submit" id="submitBtn" disabled>Submit</button>
</form>
<script>
function toggleSubmit() {
const checkbox = document.getElementById('terms');
const button = document.getElementById('submitBtn');
button.disabled = !checkbox.checked;
}
</script>name and value
Buttons can have names and values that get submitted with the form, useful for multiple submit buttons.
<form action="/process" method="post">
<label for="content">Post Content:</label>
<textarea id="content" name="content"></textarea>
<!-- Different actions based on which button is clicked -->
<button type="submit" name="action" value="draft">Save as Draft</button>
<button type="submit" name="action" value="publish">Publish Now</button>
<button type="submit" name="action" value="schedule">Schedule Post</button>
</form>formaction
Override the form's action attribute for specific buttons:
<form action="/default-action" method="post">
<input type="text" name="data">
<!-- Submit to default action -->
<button type="submit">Submit</button>
<!-- Submit to different URL -->
<button type="submit" formaction="/alternative-action">
Save as Draft
</button>
<!-- Delete action -->
<button type="submit" formaction="/delete" formmethod="post">
Delete
</button>
</form>formmethod
Override the form's HTTP method for specific buttons:
<form action="/item/123" method="post">
<input type="text" name="title">
<!-- Use POST (default) -->
<button type="submit">Update</button>
<!-- Override to use DELETE -->
<button type="submit" formmethod="post" formaction="/item/123/delete">
Delete
</button>
</form>Multiple Submit Buttons
Forms can have multiple submit buttons with different purposes:
<form action="/save" method="post">
<label for="title">Title:</label>
<input type="text" id="title" name="title" required>
<label for="body">Content:</label>
<textarea id="body" name="body" rows="10" required></textarea>
<!-- Primary action -->
<button type="submit" name="action" value="publish">
Publish Article
</button>
<!-- Secondary actions -->
<button type="submit" name="action" value="draft">
Save as Draft
</button>
<button type="submit" name="action" value="preview" formtarget="_blank">
Preview
</button>
</form>Styling Form Buttons
CSS can make buttons more attractive and user-friendly:
<style>
button, input[type="submit"] {
padding: 12px 24px;
font-size: 16px;
font-weight: 600;
border: none;
border-radius: 4px;
cursor: pointer;
transition: all 0.3s;
}
/* Primary button */
.btn-primary {
background-color: #4CAF50;
color: white;
}
.btn-primary:hover {
background-color: #45a049;
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0,0,0,0.2);
}
/* Secondary button */
.btn-secondary {
background-color: #6c757d;
color: white;
}
.btn-secondary:hover {
background-color: #5a6268;
}
/* Danger button */
.btn-danger {
background-color: #dc3545;
color: white;
}
.btn-danger:hover {
background-color: #c82333;
}
/* Disabled state */
button:disabled {
background-color: #ccc;
color: #666;
cursor: not-allowed;
opacity: 0.6;
}
/* Loading state */
.btn-loading {
position: relative;
color: transparent;
}
.btn-loading::after {
content: "";
position: absolute;
width: 16px;
height: 16px;
top: 50%;
left: 50%;
margin: -8px 0 0 -8px;
border: 2px solid #ffffff;
border-radius: 50%;
border-top-color: transparent;
animation: spinner 0.6s linear infinite;
}
@keyframes spinner {
to { transform: rotate(360deg); }
}
</style>
<form>
<button type="submit" class="btn-primary">Submit</button>
<button type="button" class="btn-secondary">Cancel</button>
<button type="button" class="btn-danger">Delete</button>
<button type="submit" disabled>Processing...</button>
</form>Button with Loading State
Show feedback when form is being processed:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Button Loading State</title>
<style>
button {
padding: 12px 24px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 4px;
font-size: 16px;
cursor: pointer;
min-width: 120px;
}
button:disabled {
background-color: #ccc;
cursor: not-allowed;
}
.spinner {
display: none;
width: 16px;
height: 16px;
border: 2px solid #ffffff;
border-top: 2px solid transparent;
border-radius: 50%;
animation: spin 0.6s linear infinite;
margin: 0 auto;
}
.loading .spinner {
display: block;
}
.loading .btn-text {
display: none;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
</head>
<body>
<form onsubmit="handleSubmit(event)">
<input type="email" name="email" placeholder="Email" required>
<button type="submit" id="submitBtn">
<span class="btn-text">Submit Form</span>
<div class="spinner"></div>
</button>
</form>
<script>
function handleSubmit(event) {
event.preventDefault();
const button = document.getElementById('submitBtn');
// Add loading state
button.classList.add('loading');
button.disabled = true;
// Simulate API call
setTimeout(() => {
// Remove loading state
button.classList.remove('loading');
button.disabled = false;
alert('Form submitted successfully!');
}, 2000);
}
</script>
</body>
</html>Practical Examples
Button with Confirmation
<form action="/delete-account" method="post">
<h3>Delete Account</h3>
<p>This action cannot be undone.</p>
<button
type="submit"
onclick="return confirm('Are you sure you want to delete your account? This cannot be undone.')"
style="background-color: #dc3545; color: white;"
>
Delete My Account
</button>
<button type="button" onclick="window.location.href='/dashboard'">
Cancel
</button>
</form>Save and Continue Pattern
<form action="/checkout" method="post">
<h3>Shipping Information</h3>
<label for="address">Address:</label>
<input type="text" id="address" name="address" required>
<label for="city">City:</label>
<input type="text" id="city" name="city" required>
<label for="zip">Zip Code:</label>
<input type="text" id="zip" name="zip" required>
<div style="display: flex; gap: 10px; margin-top: 20px;">
<button type="submit" name="action" value="continue">
Save and Continue →
</button>
<button type="submit" name="action" value="save">
Save for Later
</button>
<button type="button" onclick="history.back()">
← Back
</button>
</div>
</form>Form Wizard Navigation
<form id="wizardForm">
<div class="step" id="step1">
<h3>Step 1: Personal Info</h3>
<input type="text" name="name" placeholder="Full Name" required>
<input type="email" name="email" placeholder="Email" required>
<button type="button" onclick="nextStep()">Next →</button>
</div>
<div class="step" id="step2" style="display: none;">
<h3>Step 2: Address</h3>
<input type="text" name="address" placeholder="Address" required>
<input type="text" name="city" placeholder="City" required>
<button type="button" onclick="prevStep()">← Previous</button>
<button type="button" onclick="nextStep()">Next →</button>
</div>
<div class="step" id="step3" style="display: none;">
<h3>Step 3: Review</h3>
<p>Please review your information...</p>
<button type="button" onclick="prevStep()">← Previous</button>
<button type="submit">Submit ✓</button>
</div>
</form>
<script>
let currentStep = 1;
function nextStep() {
document.getElementById('step' + currentStep).style.display = 'none';
currentStep++;
document.getElementById('step' + currentStep).style.display = 'block';
}
function prevStep() {
document.getElementById('step' + currentStep).style.display = 'none';
currentStep--;
document.getElementById('step' + currentStep).style.display = 'block';
}
</script>Best Practices
Use Descriptive Button Text
Make button labels clear and action-oriented:
<!-- Good: Clear and specific -->
<button type="submit">Create Account</button>
<button type="submit">Send Message</button>
<button type="submit">Download Report</button>
<button type="submit">Add to Cart</button>
<!-- Bad: Vague or generic -->
<button type="submit">Submit</button>
<button type="submit">OK</button>
<button type="submit">Click Here</button>Always Specify the type Attribute
Explicitly set type to avoid unexpected behavior:
<!-- Good: Type specified -->
<button type="submit">Submit</button>
<button type="button">Cancel</button>
<button type="reset">Reset</button>
<!-- Risky: Type not specified (defaults to submit) -->
<button>Click Me</button> <!-- This will submit the form! -->Provide Visual Hierarchy
Make primary actions stand out:
<style>
.primary {
background: #4CAF50;
color: white;
padding: 12px 32px;
font-size: 16px;
}
.secondary {
background: transparent;
color: #666;
border: 1px solid #ddd;
padding: 12px 24px;
}
</style>
<form>
<!-- Primary action is prominent -->
<button type="submit" class="primary">Save Changes</button>
<!-- Secondary action is subtle -->
<button type="button" class="secondary">Cancel</button>
</form>Avoid Reset Buttons (Usually)
Reset buttons often cause frustration. Consider alternatives:
<!-- Instead of a reset button... -->
<button type="reset">Reset Form</button>
<!-- Consider these alternatives: -->
<!-- Option 1: Clear specific fields with confirmation -->
<button type="button" onclick="clearFormWithConfirmation()">
Clear Form
</button>
<!-- Option 2: Provide an undo feature -->
<button type="button" onclick="undoLastChange()">
Undo
</button>
<!-- Option 3: Just let users refresh the page -->
<!-- No reset button needed -->Accessibility Considerations
- Use clear, descriptive button text
- Ensure buttons are keyboard accessible (Tab to focus, Enter/Space to activate)
- Provide sufficient contrast between button text and background
- Make buttons large enough to click easily (minimum 44x44 pixels)
- Show focus states clearly for keyboard navigation
- Don't rely solely on color to convey button purpose
- Use
aria-labelif button contains only an icon - Disable buttons during processing to prevent double-submission
Key Takeaways
type="submit"submits the formtype="reset"resets form fields (use sparingly)type="button"has no default action (for JavaScript)- Always explicitly specify the
typeattribute - Use
<button>over<input>for flexibility - Multiple submit buttons can have different
nameandvalueattributes - Use descriptive button text that clearly indicates the action
- Provide visual hierarchy with primary and secondary styling
What's Next?
Now that you understand form buttons, the next lesson will cover fieldsets and legends—elements that help organize and group related form fields for better structure and accessibility.