Form Design Project

Create modern, accessible forms with validation and responsive design.

Project Overview

This project will guide you through creating modern, accessible forms using CSS. You'll learn to design form layouts, input styling, validation states, and responsive behavior.

  • Modern form layout and styling
  • Input validation and error states
  • Accessible form design
  • Responsive form behavior

Estimated Time

Beginner: 2-3 hours | Intermediate: 1-2 hours

Difficulty Level: Beginner to Intermediate

Step-by-Step Implementation

1 Create the HTML Structure

HTML Example

<div class="form-container">
    <div class="form-header">
        <h1>Contact Us</h1>
        <p>Get in touch with our team</p>
    </div>
    <form class="contact-form" novalidate>
        <div class="form-group">
            <label for="name">Full Name *</label>
            <input type="text" id="name" name="name" required>
            <span class="error-message">Please enter your full name</span>
        </div>
        <div class="form-group">
            <label for="email">Email Address *</label>
            <input type="email" id="email" name="email" required>
            <span class="error-message">Please enter a valid email address</span>
        </div>
        <div class="form-group">
            <label for="phone">Phone Number</label>
            <input type="tel" id="phone" name="phone">
        </div>
        <div class="form-group">
            <label for="subject">Subject *</label>
            <select id="subject" name="subject" required>
                <option value="">Select a subject</option>
                <option value="general">General Inquiry</option>
                <option value="support">Technical Support</option>
                <option value="billing">Billing Question</option>
                <option value="other">Other</option>
            </select>
            <span class="error-message">Please select a subject</span>
        </div>
        <div class="form-group">
            <label for="message">Message *</label>
            <textarea id="message" name="message" rows="5" required></textarea>
            <span class="error-message">Please enter your message</span>
        </div>
        <div class="form-group checkbox-group">
            <label class="checkbox-label">
                <input type="checkbox" name="newsletter">
                <span class="checkmark"></span>
                Subscribe to our newsletter
            </label>
        </div>
        <button type="submit" class="submit-btn">
            <i class="fas fa-paper-plane"></i>
            Send Message
        </button>
    </form>
</div>

2 Add CSS for Layout & Design

Basic CSS Example

.form-container {
    max-width: 600px;
    margin: 2rem auto;
    background: white;
    border-radius: 20px;
    box-shadow: 0 10px 30px rgba(0,0,0,0.1);
    overflow: hidden;
}
.form-header {
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    color: white;
    padding: 2rem;
    text-align: center;
}
.form-header h1 {
    margin-bottom: 0.5rem;
    font-size: 2rem;
}
.form-header p {
    opacity: 0.9;
    margin: 0;
}
.contact-form {
    padding: 2rem;
}
.form-group {
    margin-bottom: 1.5rem;
    position: relative;
}
.form-group label {
    display: block;
    margin-bottom: 0.5rem;
    font-weight: 500;
    color: #333;
}
.form-group input,
.form-group select,
.form-group textarea {
    width: 100%;
    padding: 0.75rem 1rem;
    border: 2px solid #e9ecef;
    border-radius: 10px;
    font-size: 1rem;
    transition: all 0.3s;
    background: white;
}
.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
    outline: none;
    border-color: #667eea;
    box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
}
.form-group input:invalid:not(:placeholder-shown),
.form-group select:invalid:not(:placeholder-shown),
.form-group textarea:invalid:not(:placeholder-shown) {
    border-color: #e74c3c;
}
.error-message {
    display: none;
    color: #e74c3c;
    font-size: 0.8rem;
    margin-top: 0.25rem;
}
.form-group.error .error-message {
    display: block;
}
.form-group.error input,
.form-group.error select,
.form-group.error textarea {
    border-color: #e74c3c;
}
.checkbox-group {
    display: flex;
    align-items: center;
}
.checkbox-label {
    display: flex;
    align-items: center;
    cursor: pointer;
    font-weight: normal;
}
.checkbox-label input[type="checkbox"] {
    display: none;
}
.checkmark {
    width: 20px;
    height: 20px;
    border: 2px solid #e9ecef;
    border-radius: 4px;
    margin-right: 0.75rem;
    position: relative;
    transition: all 0.3s;
}
.checkbox-label input[type="checkbox"]:checked + .checkmark {
    background: #667eea;
    border-color: #667eea;
}
.checkbox-label input[type="checkbox"]:checked + .checkmark::after {
    content: '✓';
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    color: white;
    font-size: 12px;
    font-weight: bold;
}
.submit-btn {
    width: 100%;
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    color: white;
    border: none;
    padding: 1rem 2rem;
    border-radius: 10px;
    font-size: 1rem;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.3s;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
}
.submit-btn:hover {
    transform: translateY(-2px);
    box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
}
.submit-btn:active {
    transform: translateY(0);
}
.submit-btn:disabled {
    opacity: 0.6;
    cursor: not-allowed;
    transform: none;
}
/* Success state */
.form-group.success input,
.form-group.success select,
.form-group.success textarea {
    border-color: #28a745;
}
/* Responsive design */
@media (max-width: 768px) {
    .form-container {
        margin: 1rem;
        border-radius: 15px;
    }
    .contact-form {
        padding: 1.5rem;
    }
    .form-header {
        padding: 1.5rem;
    }
    .form-header h1 {
        font-size: 1.5rem;
    }
}

3 Add Form Validation (JS)

Form Validation (JS)

class FormValidator {
    constructor() {
        this.form = document.querySelector('.contact-form');
        this.init();
    }
    
    init() {
        this.bindEvents();
    }
    
    bindEvents() {
        this.form.addEventListener('submit', (e) => this.handleSubmit(e));
        
        // Real-time validation
        this.form.querySelectorAll('input, select, textarea').forEach(field => {
            field.addEventListener('blur', () => this.validateField(field));
            field.addEventListener('input', () => this.clearError(field));
        });
    }
    
    validateField(field) {
        const formGroup = field.closest('.form-group');
        let isValid = true;
        
        // Remove previous states
        formGroup.classList.remove('error', 'success');
        
        // Required field validation
        if (field.hasAttribute('required') && !field.value.trim()) {
            this.showError(formGroup, field.dataset.error || 'This field is required');
            isValid = false;
        }
        
        // Email validation
        if (field.type === 'email' && field.value) {
            const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
            if (!emailRegex.test(field.value)) {
                this.showError(formGroup, 'Please enter a valid email address');
                isValid = false;
            }
        }
        
        // Phone validation
        if (field.type === 'tel' && field.value) {
            const phoneRegex = /^[\+]?[1-9][\d]{0,15}$/;
            if (!phoneRegex.test(field.value.replace(/\s/g, ''))) {
                this.showError(formGroup, 'Please enter a valid phone number');
                isValid = false;
            }
        }
        
        // Show success state if valid
        if (isValid && field.value.trim()) {
            formGroup.classList.add('success');
        }
        
        return isValid;
    }
    
    showError(formGroup, message) {
        formGroup.classList.add('error');
        const errorElement = formGroup.querySelector('.error-message');
        if (errorElement) {
            errorElement.textContent = message;
        }
    }
    
    clearError(field) {
        const formGroup = field.closest('.form-group');
        formGroup.classList.remove('error');
    }
    
    handleSubmit(e) {
        e.preventDefault();
        
        let isValid = true;
        const fields = this.form.querySelectorAll('input, select, textarea');
        
        // Validate all fields
        fields.forEach(field => {
            if (!this.validateField(field)) {
                isValid = false;
            }
        });
        
        if (isValid) {
            this.submitForm();
        } else {
            // Focus on first error
            const firstError = this.form.querySelector('.form-group.error input, .form-group.error select, .form-group.error textarea');
            if (firstError) {
                firstError.focus();
            }
        }
    }
    
    submitForm() {
        const submitBtn = this.form.querySelector('.submit-btn');
        const originalText = submitBtn.innerHTML;
        
        // Show loading state
        submitBtn.disabled = true;
        submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Sending...';
        
        // Simulate form submission
        setTimeout(() => {
            // Show success message
            this.showSuccessMessage();
            
            // Reset form
            this.form.reset();
            this.form.querySelectorAll('.form-group').forEach(group => {
                group.classList.remove('success');
            });
            
            // Reset button
            submitBtn.disabled = false;
            submitBtn.innerHTML = originalText;
        }, 2000);
    }
    
    showSuccessMessage() {
        const successDiv = document.createElement('div');
        successDiv.className = 'success-message';
        successDiv.innerHTML = `
            <div style="background: #d4edda; color: #155724; padding: 1rem; border-radius: 8px; margin-top: 1rem; text-align: center;">
                <i class="fas fa-check-circle"></i>
                Thank you! Your message has been sent successfully.
            </div>
        `;
        
        this.form.appendChild(successDiv);
        
        // Remove success message after 5 seconds
        setTimeout(() => {
            successDiv.remove();
        }, 5000);
    }
}

new FormValidator();

4 Test Responsiveness & Accessibility

Checklist

  • Test on mobile, tablet, and desktop
  • Check keyboard navigation and focus states
  • Use semantic HTML for form elements
  • Ensure color contrast is accessible
  • Validate your HTML and CSS

Project Checklist

Back to Photo Gallery Back to Projects Overview