Documentation
Webflow
Code
Setup: External Scripts
External Scripts in Webflow
Make sure to always put the External Scripts before the Javascript step of the resource.
In this video you learn where to put these in your Webflow project? Or how to include a paid GSAP Club plugin in your project?
HTML
Step 1: Copy structure to Webflow
Copy structure to Webflow
In the video below we described how you can copy + paste the structure of this resource to your Webflow project.
Copy to Webflow
Webflow structure is not required for this resource.
Step 1: Add HTML
HTML
<div data-form-validate="" class="form-group w-form">
<form id="wf-form-Default-Form" name="wf-form-Default-Form" data-name="Default Form" method="get" class="form" data-wf-page-id="6780d77ea8657fba8f267b71" data-wf-element-id="7310ef1a-7190-2f9a-9ac2-8af00a76fc82">
<div data-validate="" class="form-field-group">
<label for="name" class="form-label">Name <span class="form-required">*</span></label>
<div class="form-field">
<input class="form-input w-input" maxlength="256" name="name" data-name="Name" min="1" placeholder="Osmo" type="text" id="name" required="">
<div class="form-field-icon is--success"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 24 24" fill="none"><path d="M11.25 14.25L9 12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M15 10.5L11.25 14.25" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M3 12C3 16.9706 7.02943 21 12 21C16.9706 21 21 16.9706 21 12C21 7.02943 16.9706 3 12 3C7.02943 3 3 7.02943 3 12Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path></svg></div>
<div class="form-field-icon is--error"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 24 24" fill="none"><path opacity="0.1" d="M12 3C16.971 3 21 7.029 21 12C21 16.971 16.971 21 12 21C7.029 21 3 16.971 3 12C3 7.029 7.029 3 12 3Z" fill="currentColor" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 3C16.971 3 21 7.029 21 12C21 16.971 16.971 21 12 21C7.029 21 3 16.971 3 12C3 7.029 7.029 3 12 3Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 12.5V7.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M11.996 14.5C11.444 14.5 10.996 14.948 11 15.5C11 16.052 11.448 16.5 12 16.5C12.552 16.5 13 16.052 13 15.5C13 14.948 12.552 14.5 11.996 14.5Z" fill="currentColor"></path></svg></div>
</div>
</div>
<div data-validate="" class="form-field-group">
<label for="email" class="form-label">Email Address <span class="form-required">*</span></label>
<div class="form-field"><input class="form-input w-input" maxlength="256" name="email" data-name="Email" placeholder="hello@osmo.supply" type="email" id="email" required="">
<div class="form-field-icon is--success"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 24 24" fill="none"><path d="M11.25 14.25L9 12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M15 10.5L11.25 14.25" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M3 12C3 16.9706 7.02943 21 12 21C16.9706 21 21 16.9706 21 12C21 7.02943 16.9706 3 12 3C7.02943 3 3 7.02943 3 12Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path></svg></div>
<div class="form-field-icon is--error"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 24 24" fill="none"><path opacity="0.1" d="M12 3C16.971 3 21 7.029 21 12C21 16.971 16.971 21 12 21C7.029 21 3 16.971 3 12C3 7.029 7.029 3 12 3Z" fill="currentColor" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 3C16.971 3 21 7.029 21 12C21 16.971 16.971 21 12 21C7.029 21 3 16.971 3 12C3 7.029 7.029 3 12 3Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 12.5V7.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M11.996 14.5C11.444 14.5 10.996 14.948 11 15.5C11 16.052 11.448 16.5 12 16.5C12.552 16.5 13 16.052 13 15.5C13 14.948 12.552 14.5 11.996 14.5Z" fill="currentColor"></path></svg></div>
</div>
</div>
<div data-validate="" class="form-field-group">
<label for="location" class="form-label">Location <span class="form-required">*</span> <span class="form-inactive-text">(select min. 2)</span></label>
<div max="2" data-radiocheck-group="" min="2" class="radiocheck-group">
<label class="w-checkbox radiocheck-field">
<input type="checkbox" name="Location-Netherlands" id="Location-Netherlands" data-name="Location Netherlands" class="w-checkbox-input checkbox-input">
<span class="radiocheck-label w-form-label" for="Location-Netherlands">The Netherlands</span>
<div class="radiocheck-custom"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewbox="0 0 24 24" fill="none" class="radiocheck-check-svg"><path d="M7 11.5L10.5 15L17 8.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg></div>
</label>
<label class="w-checkbox radiocheck-field">
<input type="checkbox" name="Location-Germany" id="Location-Germany" data-name="Location Germany" class="w-checkbox-input checkbox-input">
<span class="radiocheck-label w-form-label" for="Location-Germany">Germany</span>
<div class="radiocheck-custom"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewbox="0 0 24 24" fill="none" class="radiocheck-check-svg"><path d="M7 11.5L10.5 15L17 8.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg></div>
</label>
<label class="w-checkbox radiocheck-field">
<input type="checkbox" name="Location-Belgium" id="Location-Belgium" data-name="Location Belgium" class="w-checkbox-input checkbox-input">
<span class="radiocheck-label w-form-label" for="Location-Belgium">Belgium</span>
<div class="radiocheck-custom"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewbox="0 0 24 24" fill="none" class="radiocheck-check-svg"><path d="M7 11.5L10.5 15L17 8.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg></div>
</label>
<div class="radiocheck-field-icon is--success"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 24 24" fill="none"><path d="M11.25 14.25L9 12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M15 10.5L11.25 14.25" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M3 12C3 16.9706 7.02943 21 12 21C16.9706 21 21 16.9706 21 12C21 7.02943 16.9706 3 12 3C7.02943 3 3 7.02943 3 12Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path></svg></div>
<div class="radiocheck-field-icon is--error"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 24 24" fill="none"><path opacity="0.1" d="M12 3C16.971 3 21 7.029 21 12C21 16.971 16.971 21 12 21C7.029 21 3 16.971 3 12C3 7.029 7.029 3 12 3Z" fill="currentColor" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 3C16.971 3 21 7.029 21 12C21 16.971 16.971 21 12 21C7.029 21 3 16.971 3 12C3 7.029 7.029 3 12 3Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 12.5V7.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M11.996 14.5C11.444 14.5 10.996 14.948 11 15.5C11 16.052 11.448 16.5 12 16.5C12.552 16.5 13 16.052 13 15.5C13 14.948 12.552 14.5 11.996 14.5Z" fill="currentColor"></path></svg></div>
</div>
</div>
<div data-validate="" class="form-field-group">
<label for="category" class="form-label">Category <span class="form-required">*</span></label>
<div class="form-field">
<select id="field" name="field" data-name="Field" required="" class="form-input w-select">
<option value="">Select option</option>
<option value="First">First choice</option>
<option value="Second">Second choice</option>
<option value="Third">Third choice</option>
</select>
<div class="form-field-chevron"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewbox="0 0 24 24" fill="none"><path d="M8 10L12 14L16 10" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg></div>
<div class="form-field-icon is--select is--success"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 24 24" fill="none"><path d="M11.25 14.25L9 12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M15 10.5L11.25 14.25" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M3 12C3 16.9706 7.02943 21 12 21C16.9706 21 21 16.9706 21 12C21 7.02943 16.9706 3 12 3C7.02943 3 3 7.02943 3 12Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path></svg></div>
<div class="form-field-icon is--select is--error"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 24 24" fill="none"><path opacity="0.1" d="M12 3C16.971 3 21 7.029 21 12C21 16.971 16.971 21 12 21C7.029 21 3 16.971 3 12C3 7.029 7.029 3 12 3Z" fill="currentColor" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 3C16.971 3 21 7.029 21 12C21 16.971 16.971 21 12 21C7.029 21 3 16.971 3 12C3 7.029 7.029 3 12 3Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 12.5V7.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M11.996 14.5C11.444 14.5 10.996 14.948 11 15.5C11 16.052 11.448 16.5 12 16.5C12.552 16.5 13 16.052 13 15.5C13 14.948 12.552 14.5 11.996 14.5Z" fill="currentColor"></path></svg></div>
</div>
</div>
<div data-validate="" class="form-field-group">
<label for="mode" class="form-label">Mode <span class="form-required">*</span></label>
<div data-radiocheck-group="" class="radiocheck-group">
<label class="radiocheck-field w-radio">
<input type="radio" name="Mode" id="Dark-mode" data-name="Mode" class="w-form-formradioinput radio-input w-radio-input" value="Dark mode">
<span class="radiocheck-label w-form-label" for="Dark-mode">Dark mode</span>
<div class="radiocheck-custom is--radio"><div class="radio-dot"></div></div>
</label>
<label class="radiocheck-field w-radio">
<input type="radio" name="Mode" id="Light-mode" data-name="Mode" class="w-form-formradioinput radio-input w-radio-input" value="Light mode">
<span class="radiocheck-label w-form-label" for="Light-mode">Light mode</span>
<div class="radiocheck-custom is--radio"><div class="radio-dot"></div></div>
</label>
<div class="radiocheck-field-icon is--success"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 24 24" fill="none"><path d="M11.25 14.25L9 12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M15 10.5L11.25 14.25" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M3 12C3 16.9706 7.02943 21 12 21C16.9706 21 21 16.9706 21 12C21 7.02943 16.9706 3 12 3C7.02943 3 3 7.02943 3 12Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path></svg></div>
<div class="radiocheck-field-icon is--error"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 24 24" fill="none"><path opacity="0.1" d="M12 3C16.971 3 21 7.029 21 12C21 16.971 16.971 21 12 21C7.029 21 3 16.971 3 12C3 7.029 7.029 3 12 3Z" fill="currentColor" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 3C16.971 3 21 7.029 21 12C21 16.971 16.971 21 12 21C7.029 21 3 16.971 3 12C3 7.029 7.029 3 12 3Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 12.5V7.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M11.996 14.5C11.444 14.5 10.996 14.948 11 15.5C11 16.052 11.448 16.5 12 16.5C12.552 16.5 13 16.052 13 15.5C13 14.948 12.552 14.5 11.996 14.5Z" fill="currentColor"></path></svg></div>
</div>
</div>
<div data-validate="" class="form-field-group">
<label for="message" class="form-label">Message <span class="form-required">*</span></label>
<div class="form-field">
<textarea class="form-input is--textarea w-input" maxlength="5000" name="message" data-name="Message" min="3" placeholder="Hello Osmo, " id="message" required=""></textarea>
<div class="form-field-icon is--success"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 24 24" fill="none"><path d="M11.25 14.25L9 12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M15 10.5L11.25 14.25" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M3 12C3 16.9706 7.02943 21 12 21C16.9706 21 21 16.9706 21 12C21 7.02943 16.9706 3 12 3C7.02943 3 3 7.02943 3 12Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path></svg></div>
<div class="form-field-icon is--error"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 24 24" fill="none"><path opacity="0.1" d="M12 3C16.971 3 21 7.029 21 12C21 16.971 16.971 21 12 21C7.029 21 3 16.971 3 12C3 7.029 7.029 3 12 3Z" fill="currentColor" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 3C16.971 3 21 7.029 21 12C21 16.971 16.971 21 12 21C7.029 21 3 16.971 3 12C3 7.029 7.029 3 12 3Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 12.5V7.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M11.996 14.5C11.444 14.5 10.996 14.948 11 15.5C11 16.052 11.448 16.5 12 16.5C12.552 16.5 13 16.052 13 15.5C13 14.948 12.552 14.5 11.996 14.5Z" fill="currentColor"></path></svg></div>
</div>
</div>
<div class="form-field-group">
<div class="form-divider"></div>
</div>
<div data-validate="" class="form-field-group">
<div data-radiocheck-group="" class="radiocheck-group">
<label class="w-checkbox radiocheck-field">
<input type="checkbox" name="Terms-Conditions" id="Terms-Conditions" data-name="Terms Conditions" required="" class="w-checkbox-input checkbox-input">
<span class="radiocheck-label is--small w-form-label" for="Terms-Conditions">Accept the Terms and Conditions <span class="form-required">*</span></span>
<div class="radiocheck-custom"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewbox="0 0 24 24" fill="none" class="radiocheck-check-svg"><path d="M7 11.5L10.5 15L17 8.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path></svg></div>
<div class="radiocheck-field-icon is--success"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 24 24" fill="none"><path d="M11.25 14.25L9 12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M15 10.5L11.25 14.25" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M3 12C3 16.9706 7.02943 21 12 21C16.9706 21 21 16.9706 21 12C21 7.02943 16.9706 3 12 3C7.02943 3 3 7.02943 3 12Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path></svg></div>
<div class="radiocheck-field-icon is--error"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 24 24" fill="none"><path opacity="0.1" d="M12 3C16.971 3 21 7.029 21 12C21 16.971 16.971 21 12 21C7.029 21 3 16.971 3 12C3 7.029 7.029 3 12 3Z" fill="currentColor" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 3C16.971 3 21 7.029 21 12C21 16.971 16.971 21 12 21C7.029 21 3 16.971 3 12C3 7.029 7.029 3 12 3Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 12.5V7.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M11.996 14.5C11.444 14.5 10.996 14.948 11 15.5C11 16.052 11.448 16.5 12 16.5C12.552 16.5 13 16.052 13 15.5C13 14.948 12.552 14.5 11.996 14.5Z" fill="currentColor"></path></svg></div>
</label>
</div>
</div>
<div class="form-field-group">
<div class="form-field">
<div data-submit="" tabindex="0" class="form-submit-btn">
<p class="form-submit-btn-p">Submit</p>
<input type="submit" data-wait="Please wait..." class="form-submit w-button" value="Submit">
</div>
</div>
</div>
</form>
<div class="form-notifcation w-form-done">
<div class="form-notification-bg"></div>
<div class="form-notification-p">Success! We’ll be in touch soon.</div>
<div class="form-notification-icon"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 24 24" fill="none"><path d="M11.25 14.25L9 12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M15 10.5L11.25 14.25" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M3 12C3 16.9706 7.02943 21 12 21C16.9706 21 21 16.9706 21 12C21 7.02943 16.9706 3 12 3C7.02943 3 3 7.02943 3 12Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path></svg></div>
</div>
<div class="form-notifcation is--error w-form-fail">
<div class="form-notification-bg"></div>
<div class="form-notification-p">Something went wrong while submitting.</div>
<div class="form-notification-icon"><svg xmlns="http://www.w3.org/2000/svg" width="100%" viewBox="0 0 24 24" fill="none"><path opacity="0.1" d="M12 3C16.971 3 21 7.029 21 12C21 16.971 16.971 21 12 21C7.029 21 3 16.971 3 12C3 7.029 7.029 3 12 3Z" fill="currentColor" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 3C16.971 3 21 7.029 21 12C21 16.971 16.971 21 12 21C7.029 21 3 16.971 3 12C3 7.029 7.029 3 12 3Z" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"></path><path d="M12 12.5V7.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"></path><path d="M11.996 14.5C11.444 14.5 10.996 14.948 11 15.5C11 16.052 11.448 16.5 12 16.5C12.552 16.5 13 16.052 13 15.5C13 14.948 12.552 14.5 11.996 14.5Z" fill="currentColor"></path></svg></div>
</div>
</div>
HTML structure is not required for this resource.
Step 2: Add CSS
CSS
.form-group {
grid-column-gap: 1.5em;
grid-row-gap: 1.5em;
flex-flow: column;
width: 25em;
margin-bottom: 0;
display: flex;
}
.form {
grid-column-gap: 1.5em;
grid-row-gap: 1.5em;
flex-flow: column;
width: 100%;
display: flex;
}
.form-field-group {
grid-column-gap: .75em;
grid-row-gap: .75em;
flex-flow: column;
align-items: flex-start;
display: flex;
}
.form-field {
width: 100%;
position: relative;
}
.form-label {
color: #131313;
width: 100%;
margin-bottom: 0;
font-size: .875em;
font-weight: 500;
line-height: 1;
}
.form-required {
color: #ff4c24;
}
.form-input {
outline-offset: 0px;
color: #131313;
-webkit-appearance: none;
appearance: none;
box-sizing: border-box;
vertical-align: middle;
background-color: #efeeec;
border: 1px solid #efeeec;
border-radius: .328125em;
outline: 0 #0000;
height: auto;
margin-bottom: 0;
padding: .9em 3.5em .9em 1em;
font-size: 1.125em;
font-weight: 500;
line-height: 1.2;
box-shadow: 0 0 #0000;
}
.form-input.is--textarea {
resize: vertical;
min-height: 9em;
}
.form-input:focus {
border-color: #cbc8c5;
}
.form-input::placeholder {
color: #1313134d;
background-color: #efeeec;
}
.form-field-icon {
opacity: 0;
pointer-events: none;
color: #cbc8c5;
-webkit-user-select: none;
user-select: none;
border-radius: .375em;
justify-content: center;
align-items: center;
width: 3.5em;
max-height: 3.5em;
padding-left: 1em;
padding-right: 1em;
display: flex;
position: absolute;
top: 1px;
bottom: 1px;
right: 1px;
}
.form-field-icon.is--error {
color: #ff4c24;
}
.form-field-icon.is--select {
right: 1.75em;
}
.radio-dot {
color: inherit;
background-color: currentColor;
border-radius: 50%;
width: .375em;
height: .375em;
}
.radiocheck-field-icon {
opacity: 0;
pointer-events: none;
color: #cbc8c5;
-webkit-user-select: none;
user-select: none;
border-radius: .375em;
justify-content: center;
align-items: center;
width: 3.5em;
max-height: 3.5em;
padding-left: 1em;
padding-right: 1em;
display: flex;
position: absolute;
top: 1px;
right: 1px;
}
.radiocheck-field-icon.is--error {
color: #ff4c24;
}
.radiocheck-label {
color: #131313;
cursor: pointer;
flex-grow: 1;
margin-bottom: 0;
padding-left: 1.8em;
font-size: 1.125em;
font-weight: 500;
line-height: 1.2;
}
.radiocheck-label.is--small {
flex-grow: 1;
padding-left: 2em;
font-size: 1em;
}
.radiocheck-group {
grid-column-gap: .75em;
grid-row-gap: .75em;
flex-flow: column;
width: 100%;
display: flex;
position: relative;
}
.checkbox-input {
cursor: pointer;
width: 0;
height: 0;
margin-top: 0;
margin-left: 0;
position: absolute;
}
.form-field-chevron {
pointer-events: none;
color: #131313;
-webkit-user-select: none;
user-select: none;
border-radius: .375em;
justify-content: center;
align-items: center;
width: 3.5em;
max-height: 3.5em;
padding-left: 1em;
padding-right: 1em;
display: flex;
position: absolute;
top: 1px;
bottom: 1px;
right: 1px;
}
.form-inactive-text {
opacity: .35;
margin-left: auto;
padding-left: .5em;
}
.radiocheck-field {
align-items: flex-start;
margin-bottom: 0;
padding-left: 0;
display: flex;
position: relative;
}
.radio-input {
cursor: pointer;
width: 0;
height: 0;
margin-top: 0;
margin-left: 0;
position: absolute;
}
.radiocheck-custom {
pointer-events: none;
color: #efeeec;
-webkit-user-select: none;
user-select: none;
background-color: #efeeec;
border: 1px solid #131313;
border-radius: .125em;
order: -1;
justify-content: center;
align-items: center;
width: 1.25em;
height: 1.25em;
margin-top: .066em;
margin-right: .75em;
display: flex;
position: absolute;
}
.radiocheck-check-svg {
width: 1.5em;
position: absolute;
}
.radiocheck-custom.is--radio {
border-radius: 50%;
}
.form-submit {
visibility: hidden;
opacity: 0;
position: absolute;
inset: 0;
}
.form-submit-btn {
outline-offset: 0px;
color: #efeeec;
cursor: pointer;
background-color: #131313;
border: 1px solid #131313;
border-radius: .375rem;
outline: 0 #0000;
flex-flow: row;
justify-content: flex-start;
align-items: center;
padding: 1.005em 1.125em;
display: flex;
position: relative;
overflow: hidden;
box-shadow: inset 0 0 #0000;
}
.form-submit-btn:focus {
outline-offset: 0px;
border-width: 1px;
border-color: #cbc8c5;
outline-color: #131313;
}
.form-submit-btn-p {
margin-bottom: 0;
font-size: 1.125em;
font-weight: 500;
line-height: 1.2;
}
.form-divider {
opacity: .15;
background-color: #131313;
width: 100%;
height: 1px;
}
.form-notifcation {
outline-offset: 0px;
color: #0ba954;
text-align: left;
border: 1px solid #0ba954;
border-color: inherit;
background-color: #efeeec;
border-radius: .375rem;
outline: 0 #0000;
width: 100%;
padding: 1.125em;
font-size: 1em;
position: relative;
}
.form-notifcation.is--error {
color: #ff4c24;
margin-top: 0;
padding-right: 3.5em;
}
.form-notification-icon {
pointer-events: none;
color: inherit;
justify-content: center;
align-items: center;
width: 3.5em;
padding-left: 1em;
padding-right: 1em;
display: flex;
position: absolute;
top: 50%;
right: 0;
transform: translateY(-50%);
}
.form-notification-bg {
opacity: .1;
pointer-events: none;
color: inherit;
background-color: currentColor;
border-radius: calc(.375rem - 2px);
display: flex;
position: absolute;
inset: 0;
}
.form-notification-p {
color: inherit;
font-size: 1.125em;
font-weight: 500;
}
@media screen and (max-width: 767px) {
.form-group {
width: 100%;
}
}
/* Field: Error */
[data-validate].is--error input,
[data-validate].is--error textarea,
[data-validate].is--error select{
border-color: #FF4C24;
}
[data-validate].is--error .form-field-icon.is--error,
[data-validate].is--error .radiocheck-field-icon.is--error{
opacity: 1;
}
/* Field: Success */
[data-validate].is--success .form-field-icon.is--success,
[data-validate].is--success .radiocheck-field-icon.is--success{
opacity: 1;
}
/* Field: Custom Radio or Checkbox */
[data-form-validate] .radiocheck-field input:focus-visible ~ .radiocheck-custom {
background-color: #D0CFCD;
color: #E2E1DF;
}
[data-form-validate] .radiocheck-field input:focus-visible:checked ~ .radiocheck-custom,
[data-form-validate] .radiocheck-field input:checked ~ .radiocheck-custom {
background-color: #131313;
color: #EFEEEC;
}
[data-form-validate] .radiocheck-field .radiocheck-label.is--small {
margin-top: 0.125em;
}
[data-validate].is--error .radiocheck-custom {
border-color: #FF4C24;
}
[data-validate].is--error input:checked ~ .radiocheck-custom {
border-color: #131313;
}
/* Field: Select */
[data-form-validate] select:has(option[value=""]:checked) {
color: rgba(19, 19, 19, 0.3);
}
Step 2: Add custom Javascript
Custom Javascript in Webflow
In this video, Ilja gives you some guidance about using JavaScript in Webflow:
Step 2: Add Javascript
Step 3: Add Javascript
Javascript
function initAdvancedFormValidation() {
const forms = document.querySelectorAll('[data-form-validate]');
forms.forEach((formContainer) => {
const startTime = new Date().getTime();
const form = formContainer.querySelector('form');
if (!form) return;
const validateFields = form.querySelectorAll('[data-validate]');
const dataSubmit = form.querySelector('[data-submit]');
if (!dataSubmit) return;
const realSubmitInput = dataSubmit.querySelector('input[type="submit"]');
if (!realSubmitInput) return;
function isSpam() {
const currentTime = new Date().getTime();
return currentTime - startTime < 5000;
}
// Disable select options with invalid values on page load
validateFields.forEach(function (fieldGroup) {
const select = fieldGroup.querySelector('select');
if (select) {
const options = select.querySelectorAll('option');
options.forEach(function (option) {
if (
option.value === '' ||
option.value === 'disabled' ||
option.value === 'null' ||
option.value === 'false'
) {
option.setAttribute('disabled', 'disabled');
}
});
}
});
function validateAndStartLiveValidationForAll() {
let allValid = true;
let firstInvalidField = null;
validateFields.forEach(function (fieldGroup) {
const input = fieldGroup.querySelector('input, textarea, select');
const radioCheckGroup = fieldGroup.querySelector('[data-radiocheck-group]');
if (!input && !radioCheckGroup) return;
if (input) input.__validationStarted = true;
if (radioCheckGroup) {
radioCheckGroup.__validationStarted = true;
const inputs = radioCheckGroup.querySelectorAll('input[type="radio"], input[type="checkbox"]');
inputs.forEach(function (input) {
input.__validationStarted = true;
});
}
updateFieldStatus(fieldGroup);
if (!isValid(fieldGroup)) {
allValid = false;
if (!firstInvalidField) {
firstInvalidField = input || radioCheckGroup.querySelector('input');
}
}
});
if (!allValid && firstInvalidField) {
firstInvalidField.focus();
}
return allValid;
}
function isValid(fieldGroup) {
const radioCheckGroup = fieldGroup.querySelector('[data-radiocheck-group]');
if (radioCheckGroup) {
const inputs = radioCheckGroup.querySelectorAll('input[type="radio"], input[type="checkbox"]');
const checkedInputs = radioCheckGroup.querySelectorAll('input:checked');
const min = parseInt(radioCheckGroup.getAttribute('min')) || 1;
const max = parseInt(radioCheckGroup.getAttribute('max')) || inputs.length;
const checkedCount = checkedInputs.length;
if (inputs[0].type === 'radio') {
return checkedCount >= 1;
} else {
if (inputs.length === 1) {
return inputs[0].checked;
} else {
return checkedCount >= min && checkedCount <= max;
}
}
} else {
const input = fieldGroup.querySelector('input, textarea, select');
if (!input) return false;
let valid = true;
const min = parseInt(input.getAttribute('min')) || 0;
const max = parseInt(input.getAttribute('max')) || Infinity;
const value = input.value.trim();
const length = value.length;
if (input.tagName.toLowerCase() === 'select') {
if (
value === '' ||
value === 'disabled' ||
value === 'null' ||
value === 'false'
) {
valid = false;
}
} else if (input.type === 'email') {
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
valid = emailPattern.test(value);
} else {
if (input.hasAttribute('min') && length < min) valid = false;
if (input.hasAttribute('max') && length > max) valid = false;
}
return valid;
}
}
function updateFieldStatus(fieldGroup) {
const radioCheckGroup = fieldGroup.querySelector('[data-radiocheck-group]');
if (radioCheckGroup) {
const inputs = radioCheckGroup.querySelectorAll('input[type="radio"], input[type="checkbox"]');
const checkedInputs = radioCheckGroup.querySelectorAll('input:checked');
if (checkedInputs.length > 0) {
fieldGroup.classList.add('is--filled');
} else {
fieldGroup.classList.remove('is--filled');
}
const valid = isValid(fieldGroup);
if (valid) {
fieldGroup.classList.add('is--success');
fieldGroup.classList.remove('is--error');
} else {
fieldGroup.classList.remove('is--success');
const anyInputValidationStarted = Array.from(inputs).some(input => input.__validationStarted);
if (anyInputValidationStarted) {
fieldGroup.classList.add('is--error');
} else {
fieldGroup.classList.remove('is--error');
}
}
} else {
const input = fieldGroup.querySelector('input, textarea, select');
if (!input) return;
const value = input.value.trim();
if (value) {
fieldGroup.classList.add('is--filled');
} else {
fieldGroup.classList.remove('is--filled');
}
const valid = isValid(fieldGroup);
if (valid) {
fieldGroup.classList.add('is--success');
fieldGroup.classList.remove('is--error');
} else {
fieldGroup.classList.remove('is--success');
if (input.__validationStarted) {
fieldGroup.classList.add('is--error');
} else {
fieldGroup.classList.remove('is--error');
}
}
}
}
validateFields.forEach(function (fieldGroup) {
const input = fieldGroup.querySelector('input, textarea, select');
const radioCheckGroup = fieldGroup.querySelector('[data-radiocheck-group]');
if (radioCheckGroup) {
const inputs = radioCheckGroup.querySelectorAll('input[type="radio"], input[type="checkbox"]');
inputs.forEach(function (input) {
input.__validationStarted = false;
input.addEventListener('change', function () {
requestAnimationFrame(function () {
if (!input.__validationStarted) {
const checkedCount = radioCheckGroup.querySelectorAll('input:checked').length;
const min = parseInt(radioCheckGroup.getAttribute('min')) || 1;
if (checkedCount >= min) {
input.__validationStarted = true;
}
}
if (input.__validationStarted) {
updateFieldStatus(fieldGroup);
}
});
});
input.addEventListener('blur', function () {
input.__validationStarted = true;
updateFieldStatus(fieldGroup);
});
});
} else if (input) {
input.__validationStarted = false;
if (input.tagName.toLowerCase() === 'select') {
input.addEventListener('change', function () {
input.__validationStarted = true;
updateFieldStatus(fieldGroup);
});
} else {
input.addEventListener('input', function () {
const value = input.value.trim();
const length = value.length;
const min = parseInt(input.getAttribute('min')) || 0;
const max = parseInt(input.getAttribute('max')) || Infinity;
if (!input.__validationStarted) {
if (input.type === 'email') {
if (isValid(fieldGroup)) input.__validationStarted = true;
} else {
if (
(input.hasAttribute('min') && length >= min) ||
(input.hasAttribute('max') && length <= max)
) {
input.__validationStarted = true;
}
}
}
if (input.__validationStarted) {
updateFieldStatus(fieldGroup);
}
});
input.addEventListener('blur', function () {
input.__validationStarted = true;
updateFieldStatus(fieldGroup);
});
}
}
});
dataSubmit.addEventListener('click', function () {
if (validateAndStartLiveValidationForAll()) {
if (isSpam()) {
alert('Form submitted too quickly. Please try again.');
return;
}
realSubmitInput.click();
}
});
form.addEventListener('keydown', function (event) {
if (event.key === 'Enter' && event.target.tagName !== 'TEXTAREA') {
event.preventDefault();
if (validateAndStartLiveValidationForAll()) {
if (isSpam()) {
alert('Form submitted too quickly. Please try again.');
return;
}
realSubmitInput.click();
}
}
});
});
}
// Initialize Advanced Form Validation
document.addEventListener('DOMContentLoaded', () => {
initAdvancedFormValidation();
});
Step 3: Add custom CSS
Step 2: Add custom CSS
Custom CSS in Webflow
Curious about where to put custom CSS in Webflow? Ilja explains it in the below video:
CSS
/* Field: Error */
[data-validate].is--error input,
[data-validate].is--error textarea,
[data-validate].is--error select{
border-color: #FF4C24;
}
[data-validate].is--error .form-field-icon.is--error,
[data-validate].is--error .radiocheck-field-icon.is--error{
opacity: 1;
}
/* Field: Success */
[data-validate].is--success .form-field-icon.is--success,
[data-validate].is--success .radiocheck-field-icon.is--success{
opacity: 1;
}
/* Field: Custom Radio or Checkbox */
[data-form-validate] .radiocheck-field input:focus-visible ~ .radiocheck-custom {
background-color: #D0CFCD;
color: #E2E1DF;
}
[data-form-validate] .radiocheck-field input:focus-visible:checked ~ .radiocheck-custom,
[data-form-validate] .radiocheck-field input:checked ~ .radiocheck-custom {
background-color: #131313;
color: #EFEEEC;
}
[data-form-validate] .radiocheck-field .radiocheck-label.is--small {
margin-top: 0.125em;
}
[data-validate].is--error .radiocheck-custom {
border-color: #FF4C24;
}
[data-validate].is--error input:checked ~ .radiocheck-custom {
border-color: #131313;
}
/* Field: Select */
[data-form-validate] select:has(option[value=""]:checked) {
color: rgba(19, 19, 19, 0.3);
}
Implementation
Form Parent
Add the attribute [data-form-validate]
to the outer container of your form. This is usually the parent element of the <form>
element. This attribute signals the validation script where to look for form fields that need validation.
Form Element
Ensure the actual <form>
element resides inside the container with [data-form-validate]
. This is required for detecting form-level events such as “Enter” key presses.
Field Group
Add [data-validate]
to each field group. A field group typically includes a <label>
and its corresponding <input>
or <textarea>
element. Each group must have the [data-validate] attribute to enable validation.
Field Validation Rules
Input min and max
Use the attributes [min="3"]
and/or [max="12"]
with [data-validate] to define the minimum and maximum character limits for a field. These limits ensure that users enter values of appropriate lengths.
Email
No additional attributes are required for email validation. Email fields are automatically validated to ensure the entered address is in the correct format.
Select
For <select>
elements, options with invalid values (e.g., empty, null, or disabled) will automatically be disabled to prevent invalid selections.
Checkboxes and Radio Buttons
To validate groups of checkboxes or radio buttons, wrap them in a container with the [data-radiocheck-group]
attribute.
- Use [min] and
[max]
attributes on the[data-radiocheck-group]
element to define the required range of selected options. - For radio buttons, at least one option must be selected to pass validation.
Additional Features
Dynamic validation
- Fields are validated live as users interact with them (on input, change, or blur events).
- Validation will only trigger visually (e.g., applying
.is--error
or.is--success
) after the user begins interacting with the field. - For grouped checkboxes and radio buttons, validation starts when a user selects or deselects an option.
Validation Classes
The following classes are dynamically added or removed based on the validation state of a field:
- Class
.is--error
— Applied when the field fails validation. - Class
.is--success
— Applied when the field passes validation. - Class
.is--filled
— Applied when the user has entered a value into the field.
Anti-Spam Protection
To minimize spam submissions. The form includes a built-in delay mechanism. If the form is submitted in less than 5 seconds after loading, the submission will be rejected with a notification. This feature helps block bots that attempt to submit forms instantly.
Custom Submit Button
For enhanced customization:
- Wrap your submit button inside an element with the
[data-submit]
attribute. - The actual submit button should be an
<input type="submit">
inside the[data-submit]
container. - The script intercepts the click event on
[data-submit]
, validates the form, and only submits it programmatically if all fields pass validation.
Keyboard Behavior
Pressing “Enter” in any input field will trigger the form’s custom submission logic, ensuring all validations are performed before submission. This behavior is disabled for <textarea>
elements to allow users to add multi-line text.
Basic Version
Need less functionality? We also have a Live Form Validation (Basic)