0Pricing
HTML Academy · Lesson

The novalidate Attribute

Disable browser validation when handling it yourself.

The novalidate Attribute is a free HTML Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the HTML Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Browser Validation Limitations

HTML5 built-in validation has limitations:

  • Error messages are browser-dependent and hard to style
  • Validation runs only on submit, not on blur or input
  • Complex business rules (password match, unique username) are impossible

When you need full control, disable built-in validation with novalidate.

novalidate on form

Adding novalidate to a form disables all browser validation:

<form action="/register" method="post" novalidate>
  <!-- Browser will NOT validate these on submit -->
  <input type="email" name="email" required>
  <input type="password" name="password" minlength="8" required>
  <button type="submit">Register</button>
</form>

Why Use novalidate?

Common reasons to disable browser validation:

  • Custom error message styling that matches your design system
  • Real-time validation (on blur/input, not just submit)
  • Multi-field validation (e.g. password confirmation)
  • Server-side error display after redirect
  • Third-party validation libraries (Zod, Yup, React Hook Form)

Custom Validation Pattern

Build custom validation with novalidate:

<form id="form" novalidate>
  <label for="email">Email</label>
  <input type="email" id="email" name="email" required>
  <span class="error" id="email-error" role="alert" hidden></span>

  <button type="submit">Submit</button>
</form>

<script>
document.getElementById('form').addEventListener('submit', (e) => {
  e.preventDefault();
  const email = document.getElementById('email');
  const error = document.getElementById('email-error');

  if (!email.value || !email.value.includes('@')) {
    error.textContent = 'Please enter a valid email address.';
    error.hidden = false;
    email.focus();
  } else {
    error.hidden = true;
    // Submit...
  }
});
</script>

formnovalidate on Button

Disable validation for a specific submit button without novalidate on the whole form:

<form action="/save" method="post">
  <input type="email" name="email" required>

  <!-- Save as draft: skip validation -->
  <button type="submit" formaction="/save-draft" formnovalidate>
    Save Draft
  </button>

  <!-- Final submit: normal validation -->
  <button type="submit">Submit</button>
</form>

Styling Custom Errors

Custom validation error styling:

.field-error {
  color: #ef4444;
  font-size: 0.875rem;
  margin-top: 0.25rem;
  display: flex;
  align-items: center;
  gap: 0.25rem;
}

input.invalid {
  border-color: #ef4444;
  box-shadow: 0 0 0 3px rgba(239, 68, 68, 0.15);
}

input.valid {
  border-color: #22c55e;
}

Accessible Custom Errors

Make custom error messages accessible:

<label for="email">Email</label>
<input
  type="email"
  id="email"
  name="email"
  aria-describedby="email-error"
  aria-invalid="false"
>
<span id="email-error" role="alert"></span>
<!-- aria-invalid="true" when invalid -->
<!-- role="alert" announces changes to screen readers -->
<!-- aria-describedby links the input to its error message -->

Validation Timing Strategies

When to validate with novalidate:

  • On submit — simplest; validate everything at once
  • On blur — validate each field when user leaves it
  • On input — real-time; best UX but can feel aggressive
  • Hybrid — validate on blur; clear errors on input

Blur + Input Hybrid Pattern

The most user-friendly validation approach:

function validateEmail(input, errorEl) {
  const val = input.value.trim();
  if (!val) {
    showError(input, errorEl, 'Email is required.');
  } else if (!/^[^@]+@[^@]+\.[^@]+$/.test(val)) {
    showError(input, errorEl, 'Enter a valid email address.');
  } else {
    clearError(input, errorEl);
  }
}

input.addEventListener('blur', () => validateEmail(input, errorEl));
input.addEventListener('input', () => {
  // Only clear the error while typing, don't re-validate until blur
  if (input.classList.contains('invalid')) validateEmail(input, errorEl);
});

novalidate and Server Validation

Always validate server-side as well:

  • Client-side validation is for user experience
  • Server-side validation is for security
  • Users can bypass HTML validation by modifying requests
  • novalidate + custom JS validation should mirror server rules

Validation Libraries

Popular JavaScript validation libraries that pair with novalidate:

  • Zod — TypeScript-first schema validation
  • Yup — object schema validation
  • Valibot — lightweight schema library
  • React Hook Form — form state + validation for React

Testing Custom Validation

How to test custom form validation:

  • Test empty submission (required fields)
  • Test invalid format (wrong email, phone pattern)
  • Test edge cases (only spaces, Unicode, very long strings)
  • Test with screen reader to verify error announcements
  • Test keyboard navigation between fields after error display

Quick Check

What does formnovalidate on a button do?

Recap: novalidate

novalidate essentials:

  • novalidate on form — disables all browser validation
  • formnovalidate on button — disables for that submit only
  • Use custom validation for UX control and complex rules
  • Always validate server-side — client validation is bypassed
  • Announce errors accessibly with role="alert" and aria-invalid

Frequently asked questions

Is the “The novalidate Attribute” lesson free?

Yes — the full text of “The novalidate Attribute” is free to read here on the web, and the HTML Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the HTML Academy course, upgrade to CoddyKit PRO.

What will I learn in “The novalidate Attribute”?

Disable browser validation when handling it yourself. You practise HTML Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start HTML Academy?

No prior experience is required. HTML Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “The novalidate Attribute” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this HTML Academy lesson?

Yes. Every HTML Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. required pattern min max and maxlength
  2. The novalidate Attribute
  3. Constraint Validation API Basics
  4. HTML5 vs JavaScript Validation Trade-offs
← Back to HTML Academy