[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"site-config":3,"blog-categories":6,"course-tree":35,"topic:html-form-validation-client-side":360},{"data":4},{"google_site_verification":5,"ga4_measurement_id":5,"site_name":5,"default_og_image":5,"twitter_handle":5},null,{"data":7},[8,14,19,25,30],{"name":9,"slug":10,"description":11,"post_count":12,"subcategories":13},"CSS","css","Learn CSS with practical tutorials and examples covering layouts, Flexbox, Grid, responsive design, typography, positioning, animations, and more.",2,[],{"name":15,"slug":16,"description":17,"post_count":12,"subcategories":18},"HTML","html","Learn HTML with practical tutorials and examples for beginners. Explore HTML tags, elements, attributes, links, images, forms, semantic HTML, and more with clear explanations and real code examples.",[],{"name":20,"slug":21,"description":22,"post_count":23,"subcategories":24},"WPF","wpf","Learn WPF with practical tutorials and examples covering XAML, windows, controls, layouts, data binding, MVVM, commands, styles, templates, debugging, and modern WPF UI development.",1,[],{"name":26,"slug":27,"description":28,"post_count":23,"subcategories":29},"Python","python","Learn Python with practical tutorials covering strings, lists, functions, exceptions, files, packages, virtual environments, modules, classes, and beginner programming concepts.",[],{"name":31,"slug":32,"description":33,"post_count":23,"subcategories":34},"Java","java","Learn Java with practical tutorials and examples for beginners. Explore Java syntax, variables, data types, classes, objects, methods, inheritance, exceptions, collections, and more with clear explanations and real code examples.",[],{"data":36},[37],{"id":23,"name":15,"slug":38,"icon":5,"icon_url":5,"short_description":39,"meta_title":40,"meta_description":41,"og_image":42,"locale":43,"subcategories":44},"html-tutorial","Welcome to our HTML Tutorial for Beginners, a complete guide designed to help you learn HTML from the ground up.\n\nHTML, which stands for HyperText Markup Language, is the standard language used to structure content on the web. Whether you want to become a web developer, build your own website, or continue learning CSS and JavaScript, understanding HTML is an essential first step.\n\nThis HTML course takes you through the fundamentals step by step, using simple explanations and practical examples. ","HTML Tutorial for Beginners - Learn HTML Step by Step","Learn HTML from scratch with our beginner-friendly HTML tutorial. Understand HTML tags, elements, forms, tables, links, images, semantic HTML and more with practical examples.","https:\u002F\u002Fwpfsharp.com\u002Fstorage\u002Fcourses\u002Fog\u002F01M2GK0XN45C0B937NF9XFAD4S.webp","en",[45,72,108,132,208,242,256,284,308,324],{"id":23,"name":46,"slug":47,"order_index":23,"topics":48},"HTML Fundamentals & Setup","html-fundamentals-setup",[49,53,56,60,64,68],{"id":23,"title":50,"slug":51,"order_index":23,"cornerstone":52,"reading_time_minutes":23},"HTML Introduction & History","html-introduction-and-history",false,{"id":12,"title":54,"slug":55,"order_index":23,"cornerstone":52,"reading_time_minutes":12},"HTML Editors & Environment Setup","html-editors-and-environment-setup",{"id":57,"title":58,"slug":59,"order_index":57,"cornerstone":52,"reading_time_minutes":12},3,"HTML Basic Syntax & Document Structure","html-basic-syntax-document-structure",{"id":61,"title":62,"slug":63,"order_index":61,"cornerstone":52,"reading_time_minutes":12},4,"HTML Elements & Tags Explained","html-elements-tags-explained",{"id":65,"title":66,"slug":67,"order_index":65,"cornerstone":52,"reading_time_minutes":12},5,"HTML Attributes (Global & Standard)","html-attributes-global-standard",{"id":69,"title":70,"slug":71,"order_index":69,"cornerstone":52,"reading_time_minutes":12},6,"Understanding the DOCTYPE & HTML5 Boilerplate","understanding-doctype-html5-boilerplate",{"id":12,"name":73,"slug":74,"order_index":12,"topics":75},"Text & Content Basics","text-content-basics",[76,80,84,88,92,96,100,104],{"id":77,"title":78,"slug":79,"order_index":77,"cornerstone":52,"reading_time_minutes":12},7,"HTML Headings (H1–H6) & SEO Best Practices","html-headings-h1-h6-seo-best-practices",{"id":81,"title":82,"slug":83,"order_index":81,"cornerstone":52,"reading_time_minutes":12},8,"HTML Paragraphs & Line Breaks","html-paragraphs-line-breaks",{"id":85,"title":86,"slug":87,"order_index":85,"cornerstone":52,"reading_time_minutes":23},9,"HTML Text Formatting (Bold, Italic, Mark, etc.)","html-text-formatting-bold-italic-mark",{"id":89,"title":90,"slug":91,"order_index":89,"cornerstone":52,"reading_time_minutes":12},10,"HTML Styles (Inline CSS Basics)","html-styles-inline-css-basics",{"id":93,"title":94,"slug":95,"order_index":93,"cornerstone":52,"reading_time_minutes":12},11,"HTML Quotations & Citations (blockquote, q, cite)","html-quotations-citations-blockquote-q-cite",{"id":97,"title":98,"slug":99,"order_index":97,"cornerstone":52,"reading_time_minutes":12},12,"HTML Comments (Best Practices)","html-comments-best-practices",{"id":101,"title":102,"slug":103,"order_index":101,"cornerstone":52,"reading_time_minutes":12},13,"HTML Colors (Names, HEX, RGB, HSL)","html-colors-names-hex-rgb-hsl",{"id":105,"title":106,"slug":107,"order_index":105,"cornerstone":52,"reading_time_minutes":12},14,"HTML & CSS Integration (Inline, Internal, External)","html-css-integration-inline-internal-external",{"id":57,"name":109,"slug":110,"order_index":57,"topics":111},"Links, Media & Navigation","links-media-navigation",[112,116,120,124,128],{"id":113,"title":114,"slug":115,"order_index":113,"cornerstone":52,"reading_time_minutes":12},15,"HTML Links (Anchor Tags & Hyperlinks)","html-links-anchor-tags-hyperlinks",{"id":117,"title":118,"slug":119,"order_index":117,"cornerstone":52,"reading_time_minutes":12},16,"HTML Images (Alt Text, Lazy Loading, Formats)","html-images-alt-text-lazy-loading-formats",{"id":121,"title":122,"slug":123,"order_index":121,"cornerstone":52,"reading_time_minutes":23},17,"HTML Favicon Setup","html-favicon-setup",{"id":125,"title":126,"slug":127,"order_index":125,"cornerstone":52,"reading_time_minutes":12},18,"HTML Page Title & Meta Tags (SEO Essentials)","html-page-title-meta-tags-seo-essentials",{"id":129,"title":130,"slug":131,"order_index":129,"cornerstone":52,"reading_time_minutes":12},19,"HTML File Paths (Absolute vs Relative)","html-file-paths-absolute-vs-relative",{"id":61,"name":133,"slug":134,"order_index":61,"topics":135},"Structuring Content","structuring-content",[136,141,146,151,156,160,164,168,172,176,180,184,188,192,196,200,204],{"id":137,"title":138,"slug":139,"order_index":140,"cornerstone":52,"reading_time_minutes":12},24,"HTML Tables Explained: Rows, Columns & Merging Cells","html-tables-rows-columns-merging-cells",20,{"id":142,"title":143,"slug":144,"order_index":145,"cornerstone":52,"reading_time_minutes":12},25,"HTML Lists: Ordered, Unordered & Description Lists","html-lists-ordered-unordered-description",21,{"id":147,"title":148,"slug":149,"order_index":150,"cornerstone":52,"reading_time_minutes":12},26,"HTML Block vs Inline Elements Explained","html-block-vs-inline-elements",22,{"id":152,"title":153,"slug":154,"order_index":155,"cornerstone":52,"reading_time_minutes":23},27,"HTML Div & Span: Generic Containers Explained","html-div-and-span-containers",23,{"id":157,"title":158,"slug":159,"order_index":137,"cornerstone":52,"reading_time_minutes":12},28,"HTML Classes vs ID: Selectors Explained","html-classes-vs-id-selectors-explained",{"id":161,"title":162,"slug":163,"order_index":142,"cornerstone":52,"reading_time_minutes":23},29,"HTML Iframes: Embedding External Content","html-iframes-embedding-content",{"id":165,"title":166,"slug":167,"order_index":147,"cornerstone":52,"reading_time_minutes":12},30,"HTML Head Element Deep Dive","html-head-element-deep-dive",{"id":169,"title":170,"slug":171,"order_index":152,"cornerstone":52,"reading_time_minutes":12},31,"HTML Layout Techniques: Header, Nav & Footer","html-layout-techniques-header-nav-footer",{"id":173,"title":174,"slug":175,"order_index":157,"cornerstone":52,"reading_time_minutes":12},32,"Responsive HTML Design: Mobile-First Approach","responsive-html-design-mobile-first-approach",{"id":177,"title":178,"slug":179,"order_index":161,"cornerstone":52,"reading_time_minutes":57},74,"HTML Semantic Elements (article, section, aside, nav)","html-semantic-elements-article-section-aside-nav",{"id":181,"title":182,"slug":183,"order_index":165,"cornerstone":52,"reading_time_minutes":12},75,"HTML Style Guide & Coding Conventions","html-style-guide-coding-conventions",{"id":185,"title":186,"slug":187,"order_index":169,"cornerstone":52,"reading_time_minutes":12},76,"HTML Entities & Special Characters","html-entities-special-characters",{"id":189,"title":190,"slug":191,"order_index":173,"cornerstone":52,"reading_time_minutes":23},77,"HTML Symbols","html-symbols",{"id":193,"title":194,"slug":195,"order_index":193,"cornerstone":52,"reading_time_minutes":23},33,"HTML Emojis 😀: How to Use Them in Web Pages","html-emojis-trending-guide",{"id":197,"title":198,"slug":199,"order_index":197,"cornerstone":52,"reading_time_minutes":12},34,"HTML Character Sets: UTF-8 & Encoding Explained","html-character-sets-utf-8-encoding",{"id":201,"title":202,"slug":203,"order_index":201,"cornerstone":52,"reading_time_minutes":23},35,"HTML URL Encoding Explained","html-url-encoding-explained",{"id":205,"title":206,"slug":207,"order_index":205,"cornerstone":52,"reading_time_minutes":23},36,"HTML vs XHTML: Key Differences","html-vs-xhtml-key-differences",{"id":77,"name":209,"slug":210,"order_index":65,"topics":211},"Forms & User Input","forms-user-input",[212,217,222,227,232,237],{"id":213,"title":214,"slug":215,"order_index":216,"cornerstone":52,"reading_time_minutes":12},49,"HTML Forms Introduction","html-forms-introduction",37,{"id":218,"title":219,"slug":220,"order_index":221,"cornerstone":52,"reading_time_minutes":23},50,"HTML Form Attributes (action, method, etc.)","html-form-attributes-action-method",38,{"id":223,"title":224,"slug":225,"order_index":226,"cornerstone":52,"reading_time_minutes":23},51,"HTML Form Elements (input, select, textarea, button)","html-form-elements-input-select-textarea-button",39,{"id":228,"title":229,"slug":230,"order_index":231,"cornerstone":52,"reading_time_minutes":12},52,"HTML Input Types (Modern Types: email, date, color, range)","html-input-types-modern-email-date-color-range",40,{"id":233,"title":234,"slug":235,"order_index":236,"cornerstone":52,"reading_time_minutes":12},53,"HTML Input Attributes (required, placeholder, pattern)","html-input-attributes-required-placeholder-pattern",41,{"id":238,"title":239,"slug":240,"order_index":241,"cornerstone":52,"reading_time_minutes":12},54,"HTML Form Validation (Client-Side)","html-form-validation-client-side",42,{"id":81,"name":243,"slug":244,"order_index":69,"topics":245},"Graphics & Visuals","graphics-visuals",[246,251],{"id":247,"title":248,"slug":249,"order_index":250,"cornerstone":52,"reading_time_minutes":57},55,"HTML Canvas (2D Drawing API) 🔥","html-canvas-2d-drawing-api",43,{"id":252,"title":253,"slug":254,"order_index":255,"cornerstone":52,"reading_time_minutes":57},56,"HTML SVG (Scalable Vector Graphics)","html-svg-scalable-vector-graphics",44,{"id":85,"name":257,"slug":258,"order_index":77,"topics":259},"Multimedia","multimedia",[260,265,270,275,280],{"id":261,"title":262,"slug":263,"order_index":264,"cornerstone":52,"reading_time_minutes":12},57,"HTML Media Overview","html-media-overview",45,{"id":266,"title":267,"slug":268,"order_index":269,"cornerstone":52,"reading_time_minutes":12},58,"HTML Video Embedding (Native Player)","html-video-embedding-native-player",46,{"id":271,"title":272,"slug":273,"order_index":274,"cornerstone":52,"reading_time_minutes":12},59,"HTML Audio Embedding","html-audio-embedding",47,{"id":276,"title":277,"slug":278,"order_index":279,"cornerstone":52,"reading_time_minutes":12},60,"HTML Plug-ins (Object & Embed Tags)","html-plugins-object-embed-tags",48,{"id":281,"title":282,"slug":283,"order_index":213,"cornerstone":52,"reading_time_minutes":12},61,"Embedding YouTube Videos in HTML","embedding-youtube-videos-in-html",{"id":89,"name":285,"slug":286,"order_index":81,"topics":287},"HTML5 Web APIs (Advanced\u002FTrending)","html5-web-apis-advancedtrending",[288,292,296,300,304],{"id":289,"title":290,"slug":291,"order_index":218,"cornerstone":52,"reading_time_minutes":12},62,"HTML Geolocation API","html-geolocation-api",{"id":293,"title":294,"slug":295,"order_index":223,"cornerstone":52,"reading_time_minutes":12},63,"HTML Drag & Drop API","html-drag-and-drop-api",{"id":297,"title":298,"slug":299,"order_index":228,"cornerstone":52,"reading_time_minutes":12},64,"HTML Web Storage (localStorage & sessionStorage)","html-web-storage-localstorage-sessionstorage",{"id":301,"title":302,"slug":303,"order_index":233,"cornerstone":52,"reading_time_minutes":12},65,"HTML Web Workers (Background Processing)","html-web-workers-background-processing",{"id":305,"title":306,"slug":307,"order_index":238,"cornerstone":52,"reading_time_minutes":12},66,"HTML Server-Sent Events (SSE)","html-server-sent-events-sse",{"id":93,"name":309,"slug":310,"order_index":85,"topics":311},"Accessibility & Best Practices (High-Demand  Skill) �","accessibility-best-practices-high-demand-skill",[312,316,320],{"id":313,"title":314,"slug":315,"order_index":247,"cornerstone":52,"reading_time_minutes":12},67,"HTML Accessibility (ARIA, Screen Readers)","html-accessibility-aria-screen-readers",{"id":317,"title":318,"slug":319,"order_index":252,"cornerstone":52,"reading_time_minutes":12},68,"Writing Semantic & SEO-Friendly HTML","writing-semantic-and-seo-friendly-html",{"id":321,"title":322,"slug":323,"order_index":261,"cornerstone":52,"reading_time_minutes":12},69,"HTML Performance Optimization Basics","html-performance-optimization-basics",{"id":97,"name":325,"slug":326,"order_index":89,"topics":327},"Reference & Practice","reference-practice",[328,332,336,340,344,348,352,356],{"id":329,"title":330,"slug":331,"order_index":23,"cornerstone":52,"reading_time_minutes":12},70,"HTML Tag List (Full Reference)","html-tag-list-full-reference",{"id":333,"title":334,"slug":335,"order_index":12,"cornerstone":52,"reading_time_minutes":12},71,"HTML Global Attributes Reference","html-global-attributes-reference",{"id":337,"title":338,"slug":339,"order_index":57,"cornerstone":52,"reading_time_minutes":12},72,"HTML Events Reference","html-events-reference",{"id":341,"title":342,"slug":343,"order_index":61,"cornerstone":52,"reading_time_minutes":12},73,"HTML Browser Support & Compatibility","html-browser-support-compatibility",{"id":345,"title":346,"slug":347,"order_index":65,"cornerstone":52,"reading_time_minutes":12},78,"HTML Doctypes Reference","html-doctypes-reference",{"id":349,"title":350,"slug":351,"order_index":69,"cornerstone":52,"reading_time_minutes":12},79,"HTTP Methods & Messages (Basics for Forms\u002FAPIs)","http-methods-messages-basics",{"id":353,"title":354,"slug":355,"order_index":77,"cornerstone":52,"reading_time_minutes":57},80,"HTML Interview Preparation (Top Q&A)","html-interview-preparation-top-qa",{"id":357,"title":358,"slug":359,"order_index":81,"cornerstone":52,"reading_time_minutes":23},81,"HTML Quiz & Practice Exercises","html-quiz-practice-exercises",{"data":361},{"id":238,"title":239,"slug":240,"content":362,"course":363,"subcategory":364,"author":365,"reading_time_minutes":12,"cornerstone":52,"schema_type":371,"faq_json":5,"video_url":5,"canonical_url":372,"meta_title":373,"meta_description":374,"og_image":5,"toc_json":375,"code_examples":404,"quiz":5,"exercises":413,"published_at":5,"updated_at":420,"prev":421,"next":422},"\u003Ch1 id=\"html-form-validation-client-side\">HTML Form Validation (Client-Side)\u003C\u002Fh1>\u003Cp>This \u003Cem>client-side form validation tutorial\u003C\u002Fem> ties together everything learned so far &mdash; form elements, input types, and input attributes &mdash; to show how the browser validates data before it is ever sent to a server, and how to extend that validation with JavaScript.\u003C\u002Fp>\u003Ch2 id=\"what-is-client-side-validation\">What Is Client-Side Validation?\u003C\u002Fh2>\u003Cp>Client-side validation checks user input in the browser, instantly, before submission &mdash; improving user experience by catching mistakes early instead of waiting for a server round-trip. It should always be paired with server-side validation for security, since client-side checks can be bypassed.\u003C\u002Fp>\u003Ch2 id=\"native-html5-validation\">Native HTML5 Validation\u003C\u002Fh2>\u003Cp>Simply using attributes like \u003Ccode>required\u003C\u002Fcode>, \u003Ccode>type=\"email\"\u003C\u002Fcode>, \u003Ccode>pattern\u003C\u002Fcode>, \u003Ccode>min\u003C\u002Fcode>, and \u003Ccode>max\u003C\u002Fcode> automatically enables free browser validation with zero JavaScript, as covered in the previous two topics.\u003C\u002Fp>\u003Ch2 id=\"the-valid-and-invalid-css-pseudo-classes\">The :valid and :invalid CSS Pseudo-Classes\u003C\u002Fh2>\u003Cp>You can style fields based on their validity state &mdash; a technique trending in modern sign-up form UX for real-time green\u002Fred visual feedback.\u003C\u002Fp>\u003Cpre>\u003Ccode>input:invalid {\n  border: 2px solid red;\n}\ninput:valid {\n  border: 2px solid green;\n}\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch2 id=\"the-constraint-validation-api-trending-custom-error-messages\">The Constraint Validation API (Trending: Custom Error Messages)\u003C\u002Fh2>\u003Cp>For full control, JavaScript's \u003Cstrong>Constraint Validation API\u003C\u002Fstrong> lets you write custom error messages and logic &mdash; a highly trending technique for polished, branded signup and checkout forms in 2026.\u003C\u002Fp>\u003Cpre>\u003Ccode>const input = document.querySelector('#email');\ninput.addEventListener('invalid', function(e) {\n  e.target.setCustomValidity('Please enter a valid email address!');\n});\ninput.addEventListener('input', function(e) {\n  e.target.setCustomValidity('');\n});\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch2 id=\"preventing-default-submission-for-custom-validation\">Preventing Default Submission for Custom Validation\u003C\u002Fh2>\u003Cp>Combine \u003Ccode>event.preventDefault()\u003C\u002Fcode> with \u003Ccode>checkValidity()\u003C\u002Fcode> to fully control the submission flow with JavaScript.\u003C\u002Fp>\u003Cpre>\u003Ccode>form.addEventListener('submit', function(e) {\n  if (!form.checkValidity()) {\n    e.preventDefault();\n    alert('Please fix the errors before submitting.');\n  }\n});\u003C\u002Fcode>\u003C\u002Fpre>\u003Ch2 id=\"best-practices\">Best Practices\u003C\u002Fh2>\u003Cul>\u003Cli>Always pair client-side validation with server-side validation\u003C\u002Fli>\u003Cli>Use \u003Ccode>novalidate\u003C\u002Fcode> on the form only if you fully replace validation with JavaScript\u003C\u002Fli>\u003Cli>Give clear, specific error messages, not just 'Invalid input'\u003C\u002Fli>\u003Cli>Use ARIA attributes like \u003Ccode>aria-invalid\u003C\u002Fcode> for accessibility\u003C\u002Fli>\u003C\u002Ful>\u003Ch2 id=\"live-example\">Live Example\u003C\u002Fh2>\u003Cp>Try submitting the form below with an empty or invalid email to see live custom validation messages.\u003C\u002Fp>\u003Cdiv class=\"try-it-yourself language-html\">\u003Cpre>\u003Ccode>&lt;form id='signupForm'&gt;\n  &lt;label for='email'&gt;Email:&lt;\u002Flabel&gt;\n  &lt;input type='email' id='email' name='email' required&gt;&lt;br&gt;&lt;br&gt;\n\n  &lt;label for='password'&gt;Password (min 8 chars):&lt;\u002Flabel&gt;\n  &lt;input type='password' id='password' name='password' minlength='8' required&gt;&lt;br&gt;&lt;br&gt;\n\n  &lt;button type='submit'&gt;Sign Up&lt;\u002Fbutton&gt;\n&lt;\u002Fform&gt;\n\n&lt;style&gt;\n  input:invalid { border: 2px solid #e74c3c; }\n  input:valid { border: 2px solid #2ecc71; }\n&lt;\u002Fstyle&gt;\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>\u003Cdiv class=\"try-it-yourself language-javascript\">\u003Cpre>\u003Ccode>const form = document.getElementById('signupForm');\nconst emailInput = document.getElementById('email');\n\nemailInput.addEventListener('invalid', function(e) {\n  e.target.setCustomValidity('Please enter a valid email, e.g. name@example.com');\n});\n\nemailInput.addEventListener('input', function(e) {\n  e.target.setCustomValidity('');\n});\n\nform.addEventListener('submit', function(e) {\n  if (!form.checkValidity()) {\n    e.preventDefault();\n    console.log('Form is invalid. Fix errors before submitting.');\n  } else {\n    console.log('Form is valid! Submitting...');\n  }\n});\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>",{"name":15,"slug":38},{"name":209,"slug":210},{"slug":366,"display_name":367,"job_title":5,"short_bio":5,"expertise_tags":368,"headshot":5,"long_bio":5,"credentials":5,"twitter_url":5,"linkedin_url":5,"github_url":5,"personal_website_url":5,"other_sameas_urls":5,"topics":369,"posts":370},"badar-khalil","Badar Khalil",[],[],[],"Article","https:\u002F\u002Fwpfsharp.com\u002Ftopics\u002Fhtml-form-validation-client-side","HTML Client-Side Form Validation Tutorial (2026 Guide)","Master client-side form validation tutorial using native HTML5 attributes and JavaScript Constraint Validation API with live code examples.",[376,380,384,388,392,396,400],{"id":377,"text":378,"level":12,"children":379},"what-is-client-side-validation","What Is Client-Side Validation?",[],{"id":381,"text":382,"level":12,"children":383},"native-html5-validation","Native HTML5 Validation",[],{"id":385,"text":386,"level":12,"children":387},"the-valid-and-invalid-css-pseudo-classes","The :valid and :invalid CSS Pseudo-Classes",[],{"id":389,"text":390,"level":12,"children":391},"the-constraint-validation-api-trending-custom-error-messages","The Constraint Validation API (Trending: Custom Error Messages)",[],{"id":393,"text":394,"level":12,"children":395},"preventing-default-submission-for-custom-validation","Preventing Default Submission for Custom Validation",[],{"id":397,"text":398,"level":12,"children":399},"best-practices","Best Practices",[],{"id":401,"text":402,"level":12,"children":403},"live-example","Live Example",[],[405,409],{"id":406,"language":16,"code":407,"is_editable":408},116,"\u003Cform id='signupForm'>\n  \u003Clabel for='email'>Email:\u003C\u002Flabel>\n  \u003Cinput type='email' id='email' name='email' required>\u003Cbr>\u003Cbr>\n\n  \u003Clabel for='password'>Password (min 8 chars):\u003C\u002Flabel>\n  \u003Cinput type='password' id='password' name='password' minlength='8' required>\u003Cbr>\u003Cbr>\n\n  \u003Cbutton type='submit'>Sign Up\u003C\u002Fbutton>\n\u003C\u002Fform>\n\n\u003Cstyle>\n  input:invalid { border: 2px solid #e74c3c; }\n  input:valid { border: 2px solid #2ecc71; }\n\u003C\u002Fstyle>",true,{"id":410,"language":411,"code":412,"is_editable":408},117,"javascript","const form = document.getElementById('signupForm');\nconst emailInput = document.getElementById('email');\n\nemailInput.addEventListener('invalid', function(e) {\n  e.target.setCustomValidity('Please enter a valid email, e.g. name@example.com');\n});\n\nemailInput.addEventListener('input', function(e) {\n  e.target.setCustomValidity('');\n});\n\nform.addEventListener('submit', function(e) {\n  if (!form.checkValidity()) {\n    e.preventDefault();\n    console.log('Form is invalid. Fix errors before submitting.');\n  } else {\n    console.log('Form is valid! Submitting...');\n  }\n});",[414],{"id":228,"title":415,"slug":416,"prompt":417,"starter_code":418,"expected_output":419,"language":411,"order_index":23},"Custom Password Validation Message","custom-password-validation-message","Using the Constraint Validation API, add a custom error message to the password input that says 'Password must be at least 8 characters long' whenever it is invalid, and clear the message as the user types.","const passwordInput = document.getElementById('password');\n\n\u002F\u002F TODO: add 'invalid' event listener with setCustomValidity\n\n\u002F\u002F TODO: add 'input' event listener to clear the custom message","passwordInput.addEventListener('invalid', ...) sets a custom message; passwordInput.addEventListener('input', ...) clears it via setCustomValidity('').","2026-09-27T18:13:58+00:00",{"id":233,"slug":235,"title":234},{"id":247,"slug":249,"title":248}]