Solution: Make HTML5 Validation Work in Safari (iOS & OSX)

Hi Everyone,

Solution
Here is a solution to the problem of HTML5 form validation not working on iOS & OSX Safari due to the :invalid pseudo class not being applied correctly.

Safari Web Browser
In practical terms this meant that on a locally hosted Infusionsoft web form, if a field value was not filled out or incorrectly filled (with an invalid value) then you would leave your beautifully coded & formatted webpage and land on the unstyled Infusionsoft form validation page on Apple’s iOS (iPhone/iPad) or Apple’s OSX (Macintosh) Safari web browsers.

Desired Outcome
You want your locally hosted form to fully validate to stop any unfilled/incorrectly filled form field values from being submitted. Only when every field is correctly filled out should the form be submitted so the customer never sees the ugly unstyled Infusionsoft form validation page.

Github Credit
I found a JavaScript solution on Github but did slightly modify the code after some testing and confirm the modified code is working on all my locally hosted forms.
https://gist.github.com/ashblue/7759368

JavaScript

<!-- JavaScript for WebKit (iOS & OSX) forces HTML5 validation (:invalid pseudo class) on form submit by adding .invalid class to trigger ---> 
<script type="text/javascript">
	 function hasHtml5Validation () {
		return typeof document.createElement('input').checkValidity === 'function';
	}
	if (hasHtml5Validation()) {
		$('.validate-form').submit(function (e) {
		if (!this.checkValidity()) {
			e.preventDefault();
			$(this).addClass('invalid');
		} else {
			$(this).removeClass('invalid');
		}
		});
	}
</script>

CSS Visual Validation
Every browser out there does HTML5 validation slightly differently and the visual indicator of an invalid field varies.

To try and make the visual experience more unified, I added some visual CSS code to apply (a similar looking) red border on an invaid state and a green border on a valid state.

Obviously this can be modified to apply whatever valid or invalid state indicator you wish to appear. The code is cosmetic to the solution and not necessary to include for the HTML5 validation JavaScript to work correctly.

/* Start - Infusionsoft Generated Web Form CSS Needed For Required Field Validation, custom code for WebKit (iOS & OSX) incomplete HTML5 validation support */

form#joinForm input:invalid, form#videoForm input:invalid {
	outline:none; /* Removes default red rectangle :invalid styling in IE & Edge, which competes with the new :invalid border styling */
}
form#joinForm input:required:focus:invalid, form#videoForm input:required:focus:invalid { /* Shows red border only on :invalid fields with focus */
	border-color:#FF0000;
	border-width:2px;
	border-style:solid;
}
form#joinForm input:required:valid, form#videoForm input:required:valid { /* Shows green border on all :valid fields regardless of focus */
	border-color:#669e00;
	border-width:2px;
	border-style:solid;
}
.invalid input:required:invalid { /* iOS & OSX, shows red border on all :invalid fields regardless of focus */
	border-color:#FF0000;
	border-width:2px;
	border-style:solid;
}
.invalid input:required:valid { /* iOS & OSX, shows green border on all :valid fields regardless of focus */
	border-color:#669e00;
	border-width:2px;
	border-style:solid;
}

/* End - Infusionsoft CSS  */

Example HTML Form Code that Works with CSS

  • You need to modify this example code with your values before it will work.
  • Replace “xxxxx…” with the appropriate values for your Infusionsoft account & form values.
  • The form name & ID can be anything you like but must match up with the #form code in the optional CSS for the visual styling to be applied.
  • The form class has to include .validate-form for the HTML5 validation JavaScript to work with the form.
  • Use of aria-required is to provide backward code compatibility on web browsers that do not support HTML5 validation. This field value is not required to make the solution work and is somewhat depreciated at this time.
  • Use of placeholders in the <input…> fields is optional
  • Use of title in the <input…> fields is optional
  • Use of a validation pattern in the email <input…> field is optional, it attempts to insure a correct email format entered email@domain.com.
  • There are many different validation patterns you can use, Google “email validation pattern in html5” or just skip this and allow any value to be entered in the email field.
  • Use of <input type=“Submit”…> is an older code form and can be updated to the more modern <button type=“Submit”…> either will work to submit a form.

.

<form name="joinForm" id="joinForm" accept-charset="UTF-8" action="https://xxxxx.infusionsoft.com/app/form/process/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" class="validate-form infusion-form" method="POST">
	<input name="inf_form_xid" type="hidden" value="Your Form xid value here...xxxxxxxxxxxxxxxxxxxxxxxxxxxx" />
	<input name="inf_form_name" type="hidden" value="Your Form Name Here" />
	<input name="infusionsoft_version" type="hidden" value="The latest Infusionsoft build version here...1.63.0.52" />
	<div class="infusion-field">
		<label for="inf_field_FirstName"><strong>First Name:</strong></label>
		<div>
			<input id="inf_field_FirstName" name="inf_field_FirstName" type="text" placeholder="FIRST NAME" class="form-control" required aria-required="true" title="Please fill out this field." />
		</div>
	</div>
	<div class="infusion-field">
		<label for="inf_field_LastName"><strong>Last Name:</strong></label>
		<div>
			<input id="inf_field_LastName" name="inf_field_LastName" type="text" placeholder="LAST NAME" class="form-control" required aria-required="true" title="Please fill out this field." />
		</div>
	</div>
	<div class="infusion-field">
		<label for="inf_field_Email"><strong>Email:</strong></label>
		<div>
			<input id="inf_field_Email" name="inf_field_Email" type="email" placeholder="EMAIL ADDRESS" class="form-control" required aria-required="true" pattern="[^@\s]+@[^@\s]+\.[^@\s]+" title="Must be formatted email@domain.com" />
		</div>
	</div>
	<div class="infusion-submit">
		<input type="Submit" name="submit" value="Get Webinar" />
	</div>
</form>