search results:

    • Standard
    • React
    License Free hosting Learn Services Community
    • + D
    • Light
    • Dark
    • System
    logo Tailwind Elements
    • Getting started
      • Quick start
      • Tutorials
      • Design system
      • Local installation
      • Optimization
      • Dark mode
      • Theming
      • Changelog
      • Contribute
      • Internationalization guide
    • Integrations
      • Angular
      • Django
      • Express
      • Laravel
      • Next
      • Nuxt
      • React
      • Remix
      • Solid
      • Svelte
      • Vue
    • Content & styles
      • Animations
      • Animations Extended
      • Colors
      • Dividers
      • Figures
      • Headings
      • Hover effects
      • Icons
      • Images
      • Mask
      • Shadows
      • Typography
    • Navigation
      • Breadcrumbs
      • Footer
      • Headers
      • Mega menu
      • Navbar
      • Offcanvas
      • Pagination
      • Pills
      • Scrollspy
      • Sidenav
      • Tabs
    • Components
      • Accordion
      • Alerts
      • Avatar
      • Badges
      • Button group
      • Buttons
      • Cards
      • Carousel
      • Chips
      • Collapse
      • Dropdown
      • Gallery
      • Jumbotron
      • Lightbox
      • Link
      • List group
      • Modal
      • Notifications
      • Paragraphs
      • Placeholders
      • Popconfirm
      • Popover
      • Progress
      • Rating
      • Scroll back to top button
      • Social buttons
      • Spinners
      • Stepper
      • Testimonials
      • Timeline
      • Toast
      • Tooltip
      • Video
      • Video carousel
    • Forms
      • Checkbox
      • Datepicker
      • Datetimepicker
      • File input
      • Form templates
      • Input Group
      • Inputs
      • Login form
      • Radio
      • Range
      • Registration form
      • Search
      • Select
      • Switch
      • Textarea
      • Timepicker
      • Validation
    • Data
      • Charts
      • Charts advanced
      • Datatables
      • Tables
    • Methods
      • Clipboard
      • Infinite scroll
      • Lazy loading
      • Loading management
      • Ripple
      • Scrollbar
      • Smooth scroll
      • Sticky
      • Touch
    • Design Blocks
      • Banners
      • Contact
      • Content
      • CTA
      • FAQ
      • Features
      • Headers
      • Hero / Intro sections
      • Logo clouds
      • Mega menu
      • News
      • Newsletter
      • Pricing
      • Projects
      • Stats
      • Team
      • Testimonials
    • Coming Soon
      • Angular
      • Builder
      • Templates
      • Vue
    • ResourcesNew
      • Playground
      • YouTube Channel
      • Private FB Group
      • Newsletter
      • UI Design course New
      • UI / UX tips
    • Overview
    • API

    Validation

    Tailwind CSS Validation

    Validate Tailwind Elements components with ease. Validation is a simple and lightweight component that adds validation to your forms.

    Required ES init: Validation *
    * UMD autoinits are enabled by default. This means that you don't need to initialize the component manually. However if you are using Tailwind Elements ES format then you should pass the required components to the initTE method.

    Basic example

    Tailwind Elements Validation allows you to show the result of you validation in a simple and elegant way. You can use just the styling that Validation component provides or you can add rules and messages for each input. Validation component is fully customizable.

    If you want to control the validation yourself and only use the styling, add data-te-validated="true" to the form and data-te-validation-state="valid/invalid" to the element if it's value is valid.

    To initialize the component use data-te-validation-init attribute and add data-te-validate="input" to the wrapper of element you want the styles to be applied to.

    Inside the data-te-validate attribute you can provide

    • input - for Tailwind-Elements input components
    • basic - for native inputs
    • checkbox - for checkboxes and switches
    • radio - radio component
    • HTML
    • javascript
    • umd
            
                
          <form id="form-1" data-te-validation-init>
            <div
              class="relative mb-3"
              id="input-1"
              data-te-input-wrapper-init
              data-te-validate="input">
              <input
                type="text"
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 data-[te-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-neutral-200 dark:placeholder:text-neutral-200 [&:not([data-te-input-placeholder-active])]:placeholder:opacity-0"
                id="exampleFormControlInput1"
                placeholder="Example label" />
              <label
                for="exampleFormControlInput1"
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[te-input-state-active]:-translate-y-[0.9rem] peer-data-[te-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-200 dark:peer-focus:text-primary"
                >Example label
              </label>
            </div>
            <button
              type="button"
              id="validation-1"
              class="inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]">
              Validate
            </button>
          </form>
          
            
        
            
                
          import {
            Validation,
            Input,
            initTE,
          } from "tw-elements";
          
          initTE({ Validation, Input });
    
          const validation1 = document.getElementById("validation-1");
          const form1 = document.getElementById("form-1");
          const input1 = document.getElementById("input-1");
          let valid = true;
          validation1.addEventListener("click", (e) => {
            e.preventDefault();
            input1.setAttribute(
              "data-te-validation-state",
              valid ? "valid" : "invalid"
            );
            form1.setAttribute("data-te-validated", true);
            valid = !valid;
          });
          
            
        
            
                
          const validation1 = document.getElementById("validation-1");
          const form1 = document.getElementById("form-1");
          const input1 = document.getElementById("input-1");
          let valid = true;
          validation1.addEventListener("click", (e) => {
            e.preventDefault();
            input1.setAttribute(
              "data-te-validation-state",
              valid ? "valid" : "invalid"
            );
            form1.setAttribute("data-te-validated", true);
            valid = !valid;
          });
          
            
        

    Hey there 👋 we want to make Tailwind Elements a community-driven project. It's open source and free, and we would like it to stay that way. If you enjoy it, help the project grow by sharing it with your peers. Every share counts, thank you!

    Share via Dev.to Share via Twitter Share via Facebook Share via Pinterest Share via Reddit Share via StumbleUpon Share via Vkontakte Share via Weibo Share via HackerNews Share via Gmail Share via Email

    Advanced Example

    Add data-te-validation-ruleset attribute with a | separated list of validation rules to make the component check them for you. Add data-te-submit-btn-ref to the submit button so that you don't have to listen on the button clicks yourself.

    Click the Validate button to validate the form again.

    • HTML
    • javascript
            
                
          <form data-te-validation-init>
            <div
              class="relative mb-3"
              data-te-input-wrapper-init
              data-te-validate="input"
              data-te-validation-ruleset="isRequired">
              <input
                type="text"
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 data-[te-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-neutral-200 dark:placeholder:text-neutral-200 [&:not([data-te-input-placeholder-active])]:placeholder:opacity-0"
                id="exampleFormAdvancedInput1"
                placeholder="Example label" />
              <label
                for="exampleFormAdvancedInput1"
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[te-input-state-active]:-translate-y-[0.9rem] peer-data-[te-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-200 dark:peer-focus:text-primary"
                >Example label
              </label>
            </div>
            <button
              type="button"
              class="inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]"
              data-te-submit-btn-ref>
              Validate
            </button>
          </form>
          
            
        
            
                
          // Initialization for ES Users
          import {
            Validation,
            Input,
            initTE,
          } from "tw-elements";
          
          initTE({ Validation, Input });
          
            
        

    Existing validation rules

    In Tailwind Elements validation we have already provided few rules that can be used to check the value of inputs. You can extend the list with use of customRules and customErrorMessages options. Example on how to do this can be found in section Custom Validation

    • isRequired - checks if any value was set
    • isEmail - checks for valid email address
    • isLongerThan - checks if string is longer than (n) length
    • isShorterThan - checks if string is shorter than (n) length
    • isChecked - checks if value was checked
    • isPhone - checks if the value has length equal to 9
    • isNumber - checks if value is type number
    • isString - checks if value is type string
    • isBoolean - checks if value is type boolean
    • isDate - checks if value is a date in format DD/MM/YYYY
    • is12hFormat - checks if value is time in 12h format
    • is24hFormat - checks if value is time in 24h format

    Supported components

    The Validation component supports:

    Select

    Used rules: isRequired

    • HTML
    • javascript
            
                
          <form data-te-validation-init>
            <div data-te-validate="input" data-te-validation-ruleset="isRequired">
              <select data-te-select-init data-te-select-clear-button="true">
                <option value="" hidden selected></option>
                <option value="1">One</option>
                <option value="2">Two</option>
                <option value="3">Three</option>
                <option value="4">Four</option>
                <option value="5">Five</option>
                <option value="6">Six</option>
                <option value="7">Seven</option>
                <option value="8">Eight</option>
              </select>
              <label data-te-select-label-ref>Example label</label>
            </div>
            <button
              type="button"
              class="mt-2 inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]"
              data-te-submit-btn-ref>
              Validate
            </button>
          </form>
          
            
        
            
                
          // Initialization for ES Users
          import {
            Validation,
            Select,
            initTE,
          } from "tw-elements";
          
          initTE({ Validation, Select });
          
            
        

    Datepicker

    Used rules: isRequired, isDate

    • HTML
    • javascript
            
                
          <form data-te-validation-init>
            <div
              class="relative mb-3"
              data-te-datepicker-init
              data-te-input-wrapper-init
              data-te-validate="input"
              data-te-validation-ruleset="isRequired|isDate">
              <input
                type="text"
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 peer-focus:text-primary data-[te-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-neutral-200 dark:placeholder:text-neutral-200 dark:peer-focus:text-primary [&:not([data-te-input-placeholder-active])]:placeholder:opacity-0"
                placeholder="Select a date" />
              <label
                for="floatingInput"
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[te-input-state-active]:-translate-y-[0.9rem] peer-data-[te-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-200 dark:peer-focus:text-primary"
                >Select a date</label
              >
            </div>
            <button
              type="button"
              class="mt-2 inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]"
              data-te-submit-btn-ref>
              Validate
            </button>
          </form>
          
            
        
            
                
          // Initialization for ES Users
          import {
            Validation,
            Datepicker,
            Input,
            initTE,
          } from "tw-elements";
          
          initTE({ Validation, Datepicker, Input });
          
            
        

    Timepicker

    Used rules: isRequired, is12hFormat

    • HTML
    • javascript
            
                
          <form data-te-validation-init>
            <div
              class="relative mb-3"
              data-te-timepicker-init
              data-te-input-wrapper-init
              data-te-validate="input"
              data-te-validation-ruleset="isRequired|is12hFormat">
              <input
                type="text"
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 peer-focus:text-primary data-[te-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-neutral-200 dark:placeholder:text-neutral-200 dark:peer-focus:text-primary [&:not([data-te-input-placeholder-active])]:placeholder:opacity-0"
                id="form1" />
              <label
                for="form1"
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[te-input-state-active]:-translate-y-[0.9rem] peer-data-[te-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-200 dark:peer-focus:text-primary"
                >Select a time</label
              >
            </div>
            <button
              type="button"
              class="mt-2 inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]"
              data-te-submit-btn-ref>
              Validate
            </button>
          </form>
          
            
        
            
                
          // Initialization for ES Users
          import {
            Validation,
            Timepicker,
            Input,
            initTE,
          } from "tw-elements";
          
          initTE({ Validation, Timepicker, Input });
          
            
        

    Input Group

    With default input. Used rules: isRequired

    @
    • HTML
    • javascript
            
                
          <form data-te-validation-init>
            <div class="relative flex flex-nowrap items-start">
              <span
                class="flex items-center whitespace-nowrap rounded-l border border-r-0 border-solid border-neutral-300 px-3 py-[0.25rem] text-center text-base font-normal leading-[1.6] text-neutral-700 dark:border-neutral-600 dark:text-neutral-200 dark:placeholder:text-neutral-200"
                id="addon-wrapping"
                >@</span
              >
              <div
                class="relative inline-block w-full"
                data-te-validate="basic"
                data-te-validation-ruleset="isRequired">
                <input
                  type="text"
                  class="relative m-0 block w-full min-w-0 flex-auto rounded-r border border-solid border-neutral-300 bg-transparent bg-clip-padding px-3 py-[0.25rem] text-base font-normal leading-[1.6] text-neutral-700 outline-none transition duration-200 ease-in-out focus:z-[3] focus:border-primary focus:text-neutral-700 focus:shadow-[inset_0_0_0_1px_rgb(59,113,202)] focus:outline-none dark:border-neutral-600 dark:text-neutral-200 dark:placeholder:text-neutral-200 dark:focus:border-primary"
                  placeholder="Username"
                  aria-label="Username"
                  aria-describedby="addon-wrapping" />
              </div>
            </div>
            <button
              type="button"
              class="mt-2 inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]"
              data-te-submit-btn-ref>
              Validate
            </button>
          </form>
          
            
        
            
                
          // Initialization for ES Users
          import {
            Validation,
            initTE,
          } from "tw-elements";
          
          initTE({ Validation });
          
            
        

    With TE Input. Used rules: isRequired

    @
    • HTML
    • javascript
            
                
          <form data-te-validation-init>
            <div
              class="relative mb-4 flex items-stretch"
              data-te-input-wrapper-init
              data-te-input-group-ref
              data-te-validate="input"
              data-te-validation-ruleset="isRequired">
              <span
                class="flex items-center whitespace-nowrap rounded-l border border-solid border-neutral-300 px-3 py-[0.25rem] text-center text-base font-normal leading-[1.6] text-neutral-700 dark:border-neutral-600 dark:text-neutral-200 dark:placeholder:text-neutral-200"
                id="basic-addon1"
                data-te-input-group-text-ref
                >@</span
              >
              <input
                type="text"
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 data-[te-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-neutral-200 dark:placeholder:text-neutral-200 [&:not([data-te-input-placeholder-active])]:placeholder:opacity-0"
                placeholder="Username"
                aria-label="Username"
                id="exampleFormControlInput"
                aria-describedby="basic-addon1" />
              <label
                for="exampleFormControlInput"
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-700 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[te-input-state-active]:-translate-y-[0.9rem] peer-data-[te-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-200 dark:peer-focus:text-primary"
                >Example label
              </label>
            </div>
            <button
              type="button"
              class="mt-2 inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]"
              data-te-submit-btn-ref>
              Validate
            </button>
          </form>
          
            
        
            
                
          // Initialization for ES Users
          import {
            Validation,
            Input,
            initTE,
          } from "tw-elements";
          
          initTE({ Validation, Input });
          
            
        

    Textarea

    Used rules: isRequired

    • HTML
    • javascript
            
                
          <form data-te-validation-init>
            <div
              class="relative mb-4 flex items-stretch"
              data-te-input-wrapper-init
              data-te-validate="input"
              data-te-validation-ruleset="isRequired">
              <textarea
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 data-[te-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-neutral-200 dark:placeholder:text-neutral-200 [&:not([data-te-input-placeholder-active])]:placeholder:opacity-0"
                id="exampleFormControlTextarea1"
                rows="3"
                placeholder="Your message"></textarea>
              <label
                for="exampleFormControlTextarea1"
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[te-input-state-active]:-translate-y-[0.9rem] peer-data-[te-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-200 dark:peer-focus:text-primary"
                >Example textarea</label
              >
            </div>
            <button
              type="button"
              class="mt-2 inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]"
              data-te-submit-btn-ref>
              Validate
            </button>
          </form>
          
            
        
            
                
          // Initialization for ES Users
          import {
            Validation,
            Input,
            initTE,
          } from "tw-elements";
          
          initTE({ Validation, Input });
          
            
        

    Checkbox

    Used rules: isChecked

    • HTML
    • javascript
            
                
          <form data-te-validation-init>
            <div
              class="relative block min-h-[1.5rem] pl-[1.5rem]"
              data-te-validate="checkbox"
              data-te-validation-ruleset="isChecked">
              <input
                class="relative float-left -ml-[1.5rem] mr-[6px] mt-[0.15rem] h-[1.125rem] w-[1.125rem] appearance-none rounded-[0.25rem] border-[0.125rem] border-solid border-neutral-300 outline-none before:pointer-events-none before:absolute before:h-[0.875rem] before:w-[0.875rem] before:scale-0 before:rounded-full before:bg-transparent before:opacity-0 before:shadow-[0px_0px_0px_13px_transparent] before:content-[''] checked:border-primary checked:bg-primary checked:before:opacity-[0.16] checked:after:absolute checked:after:-mt-px checked:after:ml-[0.25rem] checked:after:block checked:after:h-[0.8125rem] checked:after:w-[0.375rem] checked:after:rotate-45 checked:after:border-[0.125rem] checked:after:border-l-0 checked:after:border-t-0 checked:after:border-solid checked:after:border-white checked:after:bg-transparent checked:after:content-[''] hover:cursor-pointer hover:before:opacity-[0.04] hover:before:shadow-[0px_0px_0px_13px_rgba(0,0,0,0.6)] focus:shadow-none focus:transition-[border-color_0.2s] focus:before:scale-100 focus:before:opacity-[0.12] focus:before:shadow-[0px_0px_0px_13px_rgba(0,0,0,0.6)] focus:before:transition-[box-shadow_0.2s,transform_0.2s] focus:after:absolute focus:after:z-[1] focus:after:block focus:after:h-[0.875rem] focus:after:w-[0.875rem] focus:after:rounded-[0.125rem] focus:after:content-[''] checked:focus:before:scale-100 checked:focus:before:shadow-[0px_0px_0px_13px_#3b71ca] checked:focus:before:transition-[box-shadow_0.2s,transform_0.2s] checked:focus:after:-mt-px checked:focus:after:ml-[0.25rem] checked:focus:after:h-[0.8125rem] checked:focus:after:w-[0.375rem] checked:focus:after:rotate-45 checked:focus:after:rounded-none checked:focus:after:border-[0.125rem] checked:focus:after:border-l-0 checked:focus:after:border-t-0 checked:focus:after:border-solid checked:focus:after:border-white checked:focus:after:bg-transparent dark:border-neutral-600 dark:checked:border-primary dark:checked:bg-primary dark:focus:before:shadow-[0px_0px_0px_13px_rgba(255,255,255,0.4)] dark:checked:focus:before:shadow-[0px_0px_0px_13px_#3b71ca]"
                type="checkbox"
                value=""
                id="checkboxChecked"
                checked />
              <label
                class="inline-block pl-[0.15rem] hover:cursor-pointer"
                for="checkboxChecked">
                Checked checkbox
              </label>
            </div>
            <button
              type="button"
              class="mt-2 inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]"
              data-te-submit-btn-ref>
              Validate
            </button>
          </form>
          
            
        
            
                
          // Initialization for ES Users
          import {
            Validation,
            initTE,
          } from "tw-elements";
          
          initTE({ Validation });
          
            
        

    Switch

    Used rules: isChecked

    • HTML
    • javascript
            
                
          <form data-te-validation-init>
            <div
              class="relative block min-h-[1.5rem]"
              data-te-validate="checkbox"
              data-te-validation-ruleset="isChecked">
              <input
                class="mr-2 mt-[0.3rem] h-3.5 w-8 appearance-none rounded-[0.4375rem] bg-neutral-300 before:pointer-events-none before:absolute before:h-3.5 before:w-3.5 before:rounded-full before:bg-transparent before:content-[''] after:absolute after:z-[2] after:-mt-[0.1875rem] after:h-5 after:w-5 after:rounded-full after:border-none after:bg-neutral-100 after:shadow-[0_0px_3px_0_rgb(0_0_0_/_7%),_0_2px_2px_0_rgb(0_0_0_/_4%)] after:transition-[background-color_0.2s,transform_0.2s] after:content-[''] checked:bg-primary checked:after:absolute checked:after:z-[2] checked:after:-mt-[3px] checked:after:ml-[1.0625rem] checked:after:h-5 checked:after:w-5 checked:after:rounded-full checked:after:border-none checked:after:bg-primary checked:after:shadow-[0_3px_1px_-2px_rgba(0,0,0,0.2),_0_2px_2px_0_rgba(0,0,0,0.14),_0_1px_5px_0_rgba(0,0,0,0.12)] checked:after:transition-[background-color_0.2s,transform_0.2s] checked:after:content-[''] hover:cursor-pointer focus:outline-none focus:ring-0 focus:before:scale-100 focus:before:opacity-[0.12] focus:before:shadow-[3px_-1px_0px_13px_rgba(0,0,0,0.6)] focus:before:transition-[box-shadow_0.2s,transform_0.2s] focus:after:absolute focus:after:z-[1] focus:after:block focus:after:h-5 focus:after:w-5 focus:after:rounded-full focus:after:content-[''] checked:focus:border-primary checked:focus:bg-primary checked:focus:before:ml-[1.0625rem] checked:focus:before:scale-100 checked:focus:before:shadow-[3px_-1px_0px_13px_#3b71ca] checked:focus:before:transition-[box-shadow_0.2s,transform_0.2s] dark:bg-neutral-600 dark:after:bg-neutral-400 dark:checked:bg-primary dark:checked:after:bg-primary dark:focus:before:shadow-[3px_-1px_0px_13px_rgba(255,255,255,0.4)] dark:checked:focus:before:shadow-[3px_-1px_0px_13px_#3b71ca]"
                type="checkbox"
                role="switch"
                id="flexSwitchCheckDefault" />
              <label
                class="inline-block pl-[0.15rem] hover:cursor-pointer"
                for="flexSwitchCheckDefault"
                >Default switch checkbox input</label
              >
            </div>
            <button
              type="button"
              class="mt-2 inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]"
              data-te-submit-btn-ref>
              Validate
            </button>
          </form>
          
            
        
            
                
          // Initialization for ES Users
          import {
            Validation,
            initTE,
          } from "tw-elements";
          
          initTE({ Validation });
          
            
        

    Radio

    Used rules: isChecked

    • HTML
    • javascript
            
                
          <form data-te-validation-init>
            <div
              class="relative block min-h-[1.5rem] pl-[1.5rem]"
              data-te-validate="radio"
              data-te-validation-ruleset="isChecked">
              <input
                class="relative float-left -ml-[1.5rem] mr-1 mt-0.5 h-5 w-5 appearance-none rounded-full border-2 border-solid border-neutral-300 before:pointer-events-none before:absolute before:h-4 before:w-4 before:scale-0 before:rounded-full before:bg-transparent before:opacity-0 before:shadow-[0px_0px_0px_13px_transparent] before:content-[''] after:absolute after:z-[1] after:block after:h-4 after:w-4 after:rounded-full after:content-[''] checked:border-primary checked:before:opacity-[0.16] checked:after:absolute checked:after:left-1/2 checked:after:top-1/2 checked:after:h-[0.625rem] checked:after:w-[0.625rem] checked:after:rounded-full checked:after:border-primary checked:after:bg-primary checked:after:content-[''] checked:after:[transform:translate(-50%,-50%)] hover:cursor-pointer hover:before:opacity-[0.04] hover:before:shadow-[0px_0px_0px_13px_rgba(0,0,0,0.6)] focus:shadow-none focus:outline-none focus:ring-0 focus:before:scale-100 focus:before:opacity-[0.12] focus:before:shadow-[0px_0px_0px_13px_rgba(0,0,0,0.6)] focus:before:transition-[box-shadow_0.2s,transform_0.2s] checked:focus:border-primary checked:focus:before:scale-100 checked:focus:before:shadow-[0px_0px_0px_13px_#3b71ca] checked:focus:before:transition-[box-shadow_0.2s,transform_0.2s] dark:border-neutral-600 dark:checked:border-primary dark:checked:after:border-primary dark:checked:after:bg-primary dark:focus:before:shadow-[0px_0px_0px_13px_rgba(255,255,255,0.4)] dark:checked:focus:border-primary dark:checked:focus:before:shadow-[0px_0px_0px_13px_#3b71ca]"
                type="radio"
                name="flexRadioDefault"
                id="radioDefault01" />
              <label
                class="mt-px inline-block pl-[0.15rem] hover:cursor-pointer"
                for="radioDefault01">
                Default radio
              </label>
            </div>
            <button
              type="button"
              class="mt-2 inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]"
              data-te-submit-btn-ref>
              Validate
            </button>
          </form>
          
            
        
            
                
          // Initialization for ES Users
          import {
            Validation,
            initTE,
          } from "tw-elements";
          
          initTE({ Validation });
          
            
        

    Active validation

    Add data-te-active-validation="true" to make the validation listen to the input changes.

    • HTML
    • javascript
            
                
          <form
            data-te-validation-init
            data-te-active-validation="true"
            autocomplete="off">
            <div
              class="relative mb-3"
              data-te-input-wrapper-init
              data-te-validate="input"
              data-te-validation-ruleset="isRequired|isNumber|isLongerThan(2)|isShorterThan(6)">
              <input
                type="text"
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 data-[te-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-neutral-200 dark:placeholder:text-neutral-200 [&:not([data-te-input-placeholder-active])]:placeholder:opacity-0"
                id="exampleActive1"
                placeholder="Example label" />
              <label
                for="exampleActive1"
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[te-input-state-active]:-translate-y-[0.9rem] peer-data-[te-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-200 dark:peer-focus:text-primary"
                >Example label
              </label>
            </div>
            <button
              type="button"
              class="inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]"
              data-te-submit-btn-ref>
              Validate
            </button>
          </form>
          
            
        
            
                
          // Initialization for ES Users
          import {
            Validation,
            Input,
            initTE,
          } from "tw-elements";
          
          initTE({ Validation, Input });
          
            
        

    Custom validation

    You can add custom rules to the validation. Simply add a new method to the customRules option and add customErrorMessages for that method. You can also add a callback to the validation so that the Validation component will call it after the validation is done. Check the inspect tools to see how it works.

    • HTML
    • javascript
    • umd
            
                
          <form id="form-0" data-te-active-validation="true">
            <div
              class="relative mb-3"
              data-te-input-wrapper-init
              data-te-validate="input"
              data-te-validation-ruleset="isRequired|isNumber|isLongerThan(2)">
              <input
                type="text"
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 data-[te-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-neutral-200 dark:placeholder:text-neutral-200 [&:not([data-te-input-placeholder-active])]:placeholder:opacity-0"
                id="exampleInput1"
                placeholder="Example label" />
              <label
                for="exampleInput1"
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[te-input-state-active]:-translate-y-[0.9rem] peer-data-[te-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-200 dark:peer-focus:text-primary"
                >Example label
              </label>
            </div>
            <div
              class="relative mb-3"
              data-te-input-wrapper-init
              data-te-validate="input"
              data-te-validation-ruleset="isRequired|isEmail|contains(test)">
              <input
                type="text"
                name="email"
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 data-[te-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-neutral-200 dark:placeholder:text-neutral-200 [&:not([data-te-input-placeholder-active])]:placeholder:opacity-0"
                id="exampleInput2"
                placeholder="Example label" />
              <label
                for="exampleInput2"
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[te-input-state-active]:-translate-y-[0.9rem] peer-data-[te-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-200 dark:peer-focus:text-primary"
                >Example label
              </label>
            </div>
            <div
              class="relative mb-3"
              data-te-datepicker-init
              data-te-input-wrapper-init
              data-te-validate="input"
              data-te-validation-ruleset="isRequired|isDate">
              <input
                type="text"
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 peer-focus:text-primary data-[te-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-neutral-200 dark:placeholder:text-neutral-200 dark:peer-focus:text-primary [&:not([data-te-input-placeholder-active])]:placeholder:opacity-0"
                placeholder="Select a date" />
              <label
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[te-input-state-active]:-translate-y-[0.9rem] peer-data-[te-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-200 dark:peer-focus:text-primary"
                >Select a date</label
              >
            </div>
            <div
              class="relative mb-3"
              data-te-timepicker-init
              data-te-input-wrapper-init
              data-te-validate="input"
              data-te-validation-ruleset="isRequired|is12hFormat">
              <input
                type="text"
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 peer-focus:text-primary data-[te-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-neutral-200 dark:placeholder:text-neutral-200 dark:peer-focus:text-primary [&:not([data-te-input-placeholder-active])]:placeholder:opacity-0"
                id="exampleInput3" />
              <label
                for="exampleInput3"
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[te-input-state-active]:-translate-y-[0.9rem] peer-data-[te-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-200 dark:peer-focus:text-primary"
                >Select a time</label
              >
            </div>
            <button
              type="button"
              class="inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]"
              data-te-submit-btn-ref>
              Validate
            </button>
            <button
              class="inline-block rounded px-2 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-danger hover:text-danger-600 focus:text-danger-600 focus:outline-none focus:ring-0 active:text-danger-700"
              id="dispose">
              Dispose validation
            </button>
          </form>
          
            
        
            
                
          import {
            Validation,
            Input,
            Datepicker,
            Timepicker,
            initTE,
          } from "tw-elements";
          
          initTE({ Validation, Input, Datepicker, Timepicker });
    
          const fullValidationDisposeBtn = document.getElementById("dispose");
          const fullValidationForm = document.getElementById("form-0");
        
          const fullValidation = new Validation(fullValidationForm, {
            customErrorMessages: {
              contains: "The field must contain the '{contains}' word",
            },
            customRules: {
              contains: (value, message, string) => {
                return value.includes(string)
                  ? true
                  : message.replace("{contains}", string);
              },
            },
            submitCallback: (e, valid) => {
              console.log("Do something ...", "Validation passed: ", valid);
            },
          });
        
          fullValidationDisposeBtn.addEventListener("click", (e) => {
            e.preventDefault();
            fullValidation.dispose();
          });
        
          fullValidationForm.addEventListener("invalid.te.validation", (e) => {
            console.log("Something went wrong!");
          });
          fullValidationForm.addEventListener("valid.te.validation", (e) => {
            console.log("All good!");
          });
          
            
        
            
                
          const fullValidationDisposeBtn = document.getElementById("dispose");
          const fullValidationForm = document.getElementById("form-0");
        
          const fullValidation = new te.Validation(fullValidationForm, {
            customErrorMessages: {
              contains: "The field must contain the '{contains}' word",
            },
            customRules: {
              contains: (value, message, string) => {
                return value.includes(string)
                  ? true
                  : message.replace("{contains}", string);
              },
            },
            submitCallback: (e, valid) => {
              console.log("Do something ...", "Validation passed: ", valid);
            },
          });
        
          fullValidationDisposeBtn.addEventListener("click", (e) => {
            e.preventDefault();
            fullValidation.dispose();
          });
        
          fullValidationForm.addEventListener("invalid.te.validation", (e) => {
            console.log("Something went wrong!");
          });
          fullValidationForm.addEventListener("valid.te.validation", (e) => {
            console.log("All good!");
          });
          
            
        

    Validation with tooltips

    Use emitted events to show tooltips on validation results.

    • HTML
    • javascript
    • umd
            
                
          <form id="tooltips" class="mr-10" data-te-active-validation="true">
            <div
              class="relative mb-3"
              data-te-input-wrapper-init
              data-te-validate="input"
              data-te-validation-ruleset="isRequired|isLongerThan(4)">
              <input
                type="text"
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 peer-focus:text-primary data-[te-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-neutral-200 dark:placeholder:text-neutral-200 dark:peer-focus:text-primary [&:not([data-te-input-placeholder-active])]:placeholder:opacity-0"
                name="name" />
              <label
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[te-input-state-active]:-translate-y-[0.9rem] peer-data-[te-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-200 dark:peer-focus:text-primary"
                >Full name
              </label>
              <span
                class="absolute -right-8 top-1/2 -translate-y-1/2 cursor-pointer text-neutral-500 dark:text-neutral-200 [&>svg]:h-5 [&>svg]:w-5"
                id="fullNameInfo">
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  fill="none"
                  viewBox="0 0 24 24"
                  stroke-width="1.5"
                  stroke="currentColor"
                  class="h-6 w-6">
                  <path
                    stroke-linecap="round"
                    stroke-linejoin="round"
                    d="M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9 5.25h.008v.008H12v-.008z" />
                </svg>
              </span>
            </div>
            <div
              class="relative mb-3"
              data-te-input-wrapper-init
              data-te-validate="input"
              data-te-validation-ruleset="isRequired|isEmail">
              <input
                type="text"
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 peer-focus:text-primary data-[te-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-neutral-200 dark:placeholder:text-neutral-200 dark:peer-focus:text-primary [&:not([data-te-input-placeholder-active])]:placeholder:opacity-0"
                name="email" />
              <label
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[te-input-state-active]:-translate-y-[0.9rem] peer-data-[te-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-200 dark:peer-focus:text-primary"
                >Email address
              </label>
              <span
                class="absolute -right-8 top-1/2 -translate-y-1/2 cursor-pointer text-neutral-500 dark:text-neutral-200 [&>svg]:h-5 [&>svg]:w-5"
                id="emailInfo">
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  fill="none"
                  viewBox="0 0 24 24"
                  stroke-width="1.5"
                  stroke="currentColor"
                  class="h-6 w-6">
                  <path
                    stroke-linecap="round"
                    stroke-linejoin="round"
                    d="M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9 5.25h.008v.008H12v-.008z" />
                </svg>
              </span>
            </div>
            <div
              class="relative mb-4 flex items-stretch"
              data-te-input-wrapper-init
              data-te-validate="input"
              data-te-validation-ruleset="isRequired|isLongerThan(10)">
              <textarea
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 data-[te-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-neutral-200 dark:placeholder:text-neutral-200 [&:not([data-te-input-placeholder-active])]:placeholder:opacity-0"
                rows="3"
                name="issue"></textarea>
              <label
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[te-input-state-active]:-translate-y-[0.9rem] peer-data-[te-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-200 dark:peer-focus:text-primary"
                >Describe your issue</label
              >
              <span
                class="absolute -right-8 top-1/2 -translate-y-1/2 cursor-pointer text-neutral-500 dark:text-neutral-200 [&>svg]:h-5 [&>svg]:w-5"
                id="issueInfo">
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  fill="none"
                  viewBox="0 0 24 24"
                  stroke-width="1.5"
                  stroke="currentColor"
                  class="h-6 w-6">
                  <path
                    stroke-linecap="round"
                    stroke-linejoin="round"
                    d="M9.879 7.519c1.171-1.025 3.071-1.025 4.242 0 1.172 1.025 1.172 2.687 0 3.712-.203.179-.43.326-.67.442-.745.361-1.45.999-1.45 1.827v.75M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9 5.25h.008v.008H12v-.008z" />
                </svg>
              </span>
            </div>
            <button
              type="button"
              class="mt-2 inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]"
              data-te-submit-btn-ref>
              Validate
            </button>
          </form>
          
            
        
            
                
          import {
            Validation,
            Input,
            Tooltip,
            initTE,
          } from "tw-elements";
          
          initTE({ Input });
    
          const tooltipsForm = document.getElementById("tooltips");
    
          const tooltipsInfo = [
            {
              element: document.getElementById("fullNameInfo"),
              name: "name",
              message: {
                isRequired: "This value is required",
                isLongerThan: "Must be longer than 4 characters",
              },
            },
            {
              element: document.getElementById("emailInfo"),
              name: "email",
              message: {
                isRequired: "This value is required",
                isEmail: "Must be a valid email address",
              },
            },
            {
              element: document.getElementById("issueInfo"),
              name: "issue",
              message: {
                isRequired: "This value is required",
                isLongerThan: "Must be longer than 10 characters",
              },
            },
          ];
        
          const generateMessage = (result, message) =>
            `<p class="${result ? 'text-[#14a44d]' : 'text-[#dc4c64]'}">${message}</p>`;
        
          tooltipsInfo.forEach((tooltip) => {
            const title = Object.entries(tooltip.message)
              .map(([key, value]) => generateMessage(false, value))
              .join("");
        
            tooltip.instance = new Tooltip(tooltip.element, {
              html: true,
              template: `
                <div>
                  <div class="tooltip-inner bg-white text-xs p-4 ml-4 rounded border dark:bg-neutral-800 dark:border-neutral-400"></div>
                </div>
              `,
              placement: "right",
              title,
            });
          });
        
          const tooltipsValidation = new Validation(tooltipsForm);
        
          tooltipsForm.addEventListener("changed.te.validation", (e) => {
            const element = tooltipsInfo.find(
              (tooltip) => tooltip.name === e.value.name
            );
            element.instance.dispose();
        
            const title = Object.entries(element.message)
              .map(([key, value]) => {
                const result = e.value.validation.find(
                  (res) => key === res.name
                ).result;
                return generateMessage(result, value);
              })
              .join("");
        
            const borderColor =
              e.value.result === "valid" ? "border-[#14a44d]" : "border-[#dc4c64]";
        
            element.instance = new Tooltip(element.element, {
              html: true,
              template: `
                <div>
                  <div class="tooltip-inner bg-white text-xs p-4 ml-4 rounded border ${borderColor} dark:bg-neutral-800"></div>
                </div>
              `,
              placement: "right",
              title: title,
            });
          });
          
            
        
            
                
          const tooltipsForm = document.getElementById("tooltips");
    
          const tooltipsInfo = [
            {
              element: document.getElementById("fullNameInfo"),
              name: "name",
              message: {
                isRequired: "This value is required",
                isLongerThan: "Must be longer than 4 characters",
              },
            },
            {
              element: document.getElementById("emailInfo"),
              name: "email",
              message: {
                isRequired: "This value is required",
                isEmail: "Must be a valid email address",
              },
            },
            {
              element: document.getElementById("issueInfo"),
              name: "issue",
              message: {
                isRequired: "This value is required",
                isLongerThan: "Must be longer than 10 characters",
              },
            },
          ];
        
          const generateMessage = (result, message) =>
            `<p class="${result ? 'text-[#14a44d]' : 'text-[#dc4c64]'}">${message}</p>`;
        
          tooltipsInfo.forEach((tooltip) => {
            const title = Object.entries(tooltip.message)
              .map(([key, value]) => generateMessage(false, value))
              .join("");
        
            tooltip.instance = new te.Tooltip(tooltip.element, {
              html: true,
              template: `
                <div>
                  <div class="tooltip-inner bg-white text-xs p-4 ml-4 rounded border dark:bg-neutral-800 dark:border-neutral-400"></div>
                </div>
              `,
              placement: "right",
              title,
            });
          });
        
          const tooltipsValidation = new te.Validation(tooltipsForm);
        
          tooltipsForm.addEventListener("changed.te.validation", (e) => {
            const element = tooltipsInfo.find(
              (tooltip) => tooltip.name === e.value.name
            );
            element.instance.dispose();
        
            const title = Object.entries(element.message)
              .map(([key, value]) => {
                const result = e.value.validation.find(
                  (res) => key === res.name
                ).result;
                return generateMessage(result, value);
              })
              .join("");
        
            const borderColor =
              e.value.result === "valid" ? "border-[#14a44d]" : "border-[#dc4c64]";
        
            element.instance = new te.Tooltip(element.element, {
              html: true,
              template: `
                <div>
                  <div class="tooltip-inner bg-white text-xs p-4 ml-4 rounded border ${borderColor} dark:bg-neutral-800"></div>
                </div>
              `,
              placement: "right",
              title: title,
            });
          });
          
            
        

    Show results with Alert

    Use the data provided by events to show the validation results with an Alert.

    Result
    • HTML
    • javascript
    • umd
            
                
          <form id="form-results" data-te-active-validation="true">
            <div
              class="relative mb-3"
              data-te-input-wrapper-init
              data-te-validate="input"
              data-te-validation-ruleset="isRequired|isLongerThan(2)">
              <input
                type="text"
                name="name"
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 data-[te-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-neutral-200 dark:placeholder:text-neutral-200 [&:not([data-te-input-placeholder-active])]:placeholder:opacity-0"
                id="exampleAlertInput1"
                placeholder="Example label" />
              <label
                for="exampleAlertInput1"
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[te-input-state-active]:-translate-y-[0.9rem] peer-data-[te-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-200 dark:peer-focus:text-primary"
                >Full name
              </label>
            </div>
            <div
              class="relative mb-3"
              data-te-input-wrapper-init
              data-te-validate="input"
              data-te-validation-ruleset="isRequired|isEmail">
              <input
                type="text"
                name="email"
                class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 data-[te-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-neutral-200 dark:placeholder:text-neutral-200 [&:not([data-te-input-placeholder-active])]:placeholder:opacity-0"
                id="exampleAlertInput2"
                placeholder="Example label" />
              <label
                for="exampleAlertInput2"
                class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[te-input-state-active]:-translate-y-[0.9rem] peer-data-[te-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-200 dark:peer-focus:text-primary"
                >Email address
              </label>
            </div>
            <button
              type="button"
              class="inline-block rounded bg-primary px-6 pb-2 pt-2.5 text-xs font-medium uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]"
              data-te-submit-btn-ref>
              Validate
            </button>
          </form>
    
          <div
            id="result-container"
            class="fixed right-4 top-4 z-[100] mb-3 hidden w-1/4 items-center rounded-lg bg-primary-100 px-6 py-4 text-base text-primary-800 data-[te-alert-show]:inline-flex"
            role="alert"
            data-te-alert-init
            data-te-autohide="true"
            data-te-delay="4000">
            Result
          </div>
          
            
        
            
                
          import {
            Validation,
            Input,
            Alert,
            initTE,
          } from "tw-elements";
          
          initTE({ Input, Alert });
    
          const resultContainer = document.getElementById("result-container");
          const alertInstance = Alert.getInstance(resultContainer);
        
          const resultsForm = document.getElementById("form-results");
        
          const resultValidation = new Validation(resultsForm);
        
          resultsForm.addEventListener("valid.te.validation", (e) => {
            const results = [];
            resultsForm.querySelectorAll("input").forEach((input) => {
              results.push({ [input.name]: input.value });
            });
        
            resultContainer.innerHTML = `
          <div>
            <h3 class="mb-3">Validation passed! Here is the result:</h3>
            <div>${JSON.stringify(results, null, 2)}</div>
          </div>
          `; alertInstance.show(); });
          
            
        
            
                
          const resultContainer = document.getElementById("result-container");
          const alertInstance = te.Alert.getInstance(resultContainer);
        
          const resultsForm = document.getElementById("form-results");
        
          const resultValidation = new te.Validation(resultsForm);
        
          resultsForm.addEventListener("valid.te.validation", (e) => {
            const results = [];
            resultsForm.querySelectorAll("input").forEach((input) => {
              results.push({ [input.name]: input.value });
            });
        
            resultContainer.innerHTML = `
          <div>
            <h3 class="mb-3">Validation passed! Here is the result:</h3>
            <div>${JSON.stringify(results, null, 2)}</div>
          </div>
          `; alertInstance.show(); });
          
            
        

    Custom feedback messages

    You can set the feedback messages to have the content you want. Simply add data-te-invalid-feedback and data-te-valid-feedback attributes with your custom message.

    Sample image

    Sign in with

    Or

    Forgot password?

    Don't have an account? Register

    • HTML
    • javascript
            
                
          <div>
            <!-- Left column container with background-->
            <div
              class="g-6 flex h-full flex-wrap items-center justify-center lg:justify-between">
              <div
                class="shrink-1 mb-12 grow-0 basis-auto md:mb-0 md:w-9/12 md:shrink-0 lg:w-6/12 xl:w-6/12">
                <img
                  src="https://tecdn.b-cdn.net/img/Photos/new-templates/bootstrap-login-form/draw2.webp"
                  class="w-full"
                  alt="Sample image" />
              </div>
    
              <!-- Right column container -->
              <div class="mb-12 md:mb-0 md:w-8/12 lg:w-5/12 xl:w-5/12">
                <form data-te-validation-init data-te-active-validation="true">
                  <!--Sign in section-->
                  <div
                    class="flex flex-row items-center justify-center lg:justify-start">
                    <p class="mb-0 mr-4 text-lg">Sign in with</p>
    
                    <!-- Facebook -->
                    <button
                      type="button"
                      data-te-ripple-init
                      data-te-ripple-color="light"
                      class="mx-1 h-9 w-9 rounded-full bg-primary uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]">
                      <!-- Facebook -->
                      <svg
                        xmlns="http://www.w3.org/2000/svg"
                        class="mx-auto h-3.5 w-3.5"
                        fill="currentColor"
                        viewBox="0 0 24 24">
                        <path
                          d="M9 8h-3v4h3v12h5v-12h3.642l.358-4h-4v-1.667c0-.955.192-1.333 1.115-1.333h2.885v-5h-3.808c-3.596 0-5.192 1.583-5.192 4.615v3.385z" />
                      </svg>
                    </button>
    
                    <!-- Twitter -->
                    <button
                      type="button"
                      data-te-ripple-init
                      data-te-ripple-color="light"
                      class="mx-1 h-9 w-9 rounded-full bg-primary uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]">
                      <!-- Twitter -->
                      <svg
                        xmlns="http://www.w3.org/2000/svg"
                        class="mx-auto h-3.5 w-3.5"
                        fill="currentColor"
                        viewBox="0 0 24 24">
                        <path
                          d="M24 4.557c-.883.392-1.832.656-2.828.775 1.017-.609 1.798-1.574 2.165-2.724-.951.564-2.005.974-3.127 1.195-.897-.957-2.178-1.555-3.594-1.555-3.179 0-5.515 2.966-4.797 6.045-4.091-.205-7.719-2.165-10.148-5.144-1.29 2.213-.669 5.108 1.523 6.574-.806-.026-1.566-.247-2.229-.616-.054 2.281 1.581 4.415 3.949 4.89-.693.188-1.452.232-2.224.084.626 1.956 2.444 3.379 4.6 3.419-2.07 1.623-4.678 2.348-7.29 2.04 2.179 1.397 4.768 2.212 7.548 2.212 9.142 0 14.307-7.721 13.995-14.646.962-.695 1.797-1.562 2.457-2.549z" />
                      </svg>
                    </button>
    
                    <!-- Linkedin -->
                    <button
                      type="button"
                      data-te-ripple-init
                      data-te-ripple-color="light"
                      class="mx-1 h-9 w-9 rounded-full bg-primary uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]">
                      <!-- Linkedin -->
                      <svg
                        xmlns="http://www.w3.org/2000/svg"
                        class="mx-auto h-3.5 w-3.5"
                        fill="currentColor"
                        viewBox="0 0 24 24">
                        <path
                          d="M4.98 3.5c0 1.381-1.11 2.5-2.48 2.5s-2.48-1.119-2.48-2.5c0-1.38 1.11-2.5 2.48-2.5s2.48 1.12 2.48 2.5zm.02 4.5h-5v16h5v-16zm7.982 0h-4.968v16h4.969v-8.399c0-4.67 6.029-5.052 6.029 0v8.399h4.988v-10.131c0-7.88-8.922-7.593-11.018-3.714v-2.155z" />
                      </svg>
                    </button>
                  </div>
    
                  <!-- Separator between social media sign in and email/password sign in -->
                  <div
                    class="my-4 flex items-center before:mt-0.5 before:flex-1 before:border-t before:border-neutral-300 after:mt-0.5 after:flex-1 after:border-t after:border-neutral-300">
                    <p class="mx-4 mb-0 text-center font-semibold dark:text-white">
                      Or
                    </p>
                  </div>
    
                  <!-- Email input -->
                  <div
                    class="relative mb-6"
                    data-te-input-wrapper-init
                    data-te-validate="input"
                    data-te-validation-ruleset="isRequired|isEmail"
                    data-te-invalid-feedback="The email address is invalid"
                    data-te-valid-feedback="The email address is valid">
                    <input
                      type="text"
                      class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[2.15] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 data-[te-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-neutral-200 dark:placeholder:text-neutral-200 [&:not([data-te-input-placeholder-active])]:placeholder:opacity-0"
                      id="exampleFormControlLogin1"
                      placeholder="Email address" />
                    <label
                      for="exampleFormControlLogin1"
                      class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[2.15] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[1.15rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[te-input-state-active]:-translate-y-[1.15rem] peer-data-[te-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-200 dark:peer-focus:text-primary"
                      >Email address
                    </label>
                  </div>
    
                  <!-- Password input -->
                  <div
                    class="relative mb-6"
                    data-te-input-wrapper-init
                    data-te-validate="input"
                    data-te-validation-ruleset="isRequired|isLongerThan(6)"
                    data-te-invalid-feedback="Please provide a password longer than 6 characters"
                    data-te-valid-feedback="Your password is longer than 6 characters!">
                    <input
                      type="password"
                      class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[2.15] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 data-[te-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-neutral-200 dark:placeholder:text-neutral-200 [&:not([data-te-input-placeholder-active])]:placeholder:opacity-0"
                      id="exampleFormControlLogin2"
                      placeholder="Password" />
                    <label
                      for="exampleFormControlLogin2"
                      class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[2.15] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[1.15rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[te-input-state-active]:-translate-y-[1.15rem] peer-data-[te-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-200 dark:peer-focus:text-primary"
                      >Password
                    </label>
                  </div>
    
                  <div class="mb-6 flex items-center justify-between">
                    <!-- Remember me checkbox -->
                    <div
                      class="relative mb-[0.125rem] mt-3 block min-h-[1.5rem] pl-[1.5rem]"
                      data-te-validate="checkbox"
                      data-te-validation-ruleset="isChecked">
                      <input
                        class="relative float-left -ml-[1.5rem] mr-[6px] mt-[0.15rem] h-[1.125rem] w-[1.125rem] appearance-none rounded-[0.25rem] border-[0.125rem] border-solid border-neutral-300 outline-none before:pointer-events-none before:absolute before:h-[0.875rem] before:w-[0.875rem] before:scale-0 before:rounded-full before:bg-transparent before:opacity-0 before:shadow-[0px_0px_0px_13px_transparent] before:content-[''] checked:border-primary checked:bg-primary checked:before:opacity-[0.16] checked:after:absolute checked:after:-mt-px checked:after:ml-[0.25rem] checked:after:block checked:after:h-[0.8125rem] checked:after:w-[0.375rem] checked:after:rotate-45 checked:after:border-[0.125rem] checked:after:border-l-0 checked:after:border-t-0 checked:after:border-solid checked:after:border-white checked:after:bg-transparent checked:after:content-[''] hover:cursor-pointer hover:before:opacity-[0.04] hover:before:shadow-[0px_0px_0px_13px_rgba(0,0,0,0.6)] focus:shadow-none focus:transition-[border-color_0.2s] focus:before:scale-100 focus:before:opacity-[0.12] focus:before:shadow-[0px_0px_0px_13px_rgba(0,0,0,0.6)] focus:before:transition-[box-shadow_0.2s,transform_0.2s] focus:after:absolute focus:after:z-[1] focus:after:block focus:after:h-[0.875rem] focus:after:w-[0.875rem] focus:after:rounded-[0.125rem] focus:after:content-[''] checked:focus:before:scale-100 checked:focus:before:shadow-[0px_0px_0px_13px_#3b71ca] checked:focus:before:transition-[box-shadow_0.2s,transform_0.2s] checked:focus:after:-mt-px checked:focus:after:ml-[0.25rem] checked:focus:after:h-[0.8125rem] checked:focus:after:w-[0.375rem] checked:focus:after:rotate-45 checked:focus:after:rounded-none checked:focus:after:border-[0.125rem] checked:focus:after:border-l-0 checked:focus:after:border-t-0 checked:focus:after:border-solid checked:focus:after:border-white checked:focus:after:bg-transparent dark:border-neutral-600 dark:checked:border-primary dark:checked:bg-primary dark:focus:before:shadow-[0px_0px_0px_13px_rgba(255,255,255,0.4)] dark:checked:focus:before:shadow-[0px_0px_0px_13px_#3b71ca]"
                        type="checkbox"
                        value=""
                        id="exampleFormControlLogin3" />
                      <label
                        class="inline-block pl-[0.15rem] hover:cursor-pointer"
                        for="exampleFormControlLogin3">
                        Remember me
                      </label>
                    </div>
    
                    <!--Forgot password link-->
                    <a class="mt-3" href="#!">Forgot password?</a>
                  </div>
    
                  <!-- Login button -->
                  <div class="text-center lg:text-left">
                    <button
                      type="button"
                      class="inline-block rounded bg-primary px-7 pb-2.5 pt-3 text-sm font-medium uppercase leading-normal text-white shadow-[0_4px_9px_-4px_#3b71ca] transition duration-150 ease-in-out hover:bg-primary-600 hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:bg-primary-600 focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] focus:outline-none focus:ring-0 active:bg-primary-700 active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.3),0_4px_18px_0_rgba(59,113,202,0.2)] dark:shadow-[0_4px_9px_-4px_rgba(59,113,202,0.5)] dark:hover:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:focus:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)] dark:active:shadow-[0_8px_9px_-4px_rgba(59,113,202,0.2),0_4px_18px_0_rgba(59,113,202,0.1)]"
                      data-te-ripple-init
                      data-te-ripple-color="light"
                      data-te-submit-btn-ref>
                      Login
                    </button>
    
                    <!-- Register link -->
                    <p class="mb-0 mt-2 pt-1 text-sm font-semibold">
                      Don't have an account?
                      <a
                        href="#!"
                        class="text-danger transition duration-150 ease-in-out hover:text-danger-600 focus:text-danger-600 active:text-danger-700"
                        >Register</a
                      >
                    </p>
                  </div>
                </form>
              </div>
            </div>
          </div>
          
            
        
            
                
          // Initialization for ES Users
          import {
            Validation,
            Input,
            Ripple,
            initTE,
          } from "tw-elements";
          
          initTE({ Validation, Input, Ripple });
          
            
        

    Related resources

    Tutorials:

    focus active and others dark mode spacing utility first rounded corners cards sizing inputs forms

    Extended Docs:

    datepicker file input form templates input group login form registration form search select textarea timepicker border opacity borders center grid items dark theme display flex icons position spacing

    Design System (Figma):

    introduction art of prioritization de emphasize with no mercy lowering contrast beyond borders let it breathe user experience do not start with the roof secondary questions project personality design system principles tips and tricks
    • Basic example
    • Advanced Example
    • Existing validation rules
    • Supported components
    • Select
    • Datepicker
    • Timepicker
    • Input Group
    • Textarea
    • Checkbox
    • Switch
    • Radio
    • Active validation
    • Custom validation
    • Validation with tooltips
    • Show results with Alert
    • Custom feedback messages
    • Related resources

    Validation - API


    Import

    Importing components depends on how your application works. If you intend to use the Tailwind Elements ES format, you must first import the component and then initialize it with the initTE method. If you are going to use the UMD format, just import the tw-elements package.

    • javascript
    • umd
            
                
            import { Validation, initTE } from "tw-elements";
            initTE({ Validation });
            
            
        
            
                
            import "tw-elements";
            
            
        

    Via data attributes

    Elements with the data-te-validation-init attribute will be automatically initialized - you can set all available options with data attributes. For ES format, you must first import and call the initTE method.

    • HTML
            
                
            <form data-te-validation-init>
              <div
                class="relative mb-3"
                id="input-1"
                data-te-input-wrapper-init
                data-te-validate="input">
                <input
                  type="text"
                  class="peer block min-h-[auto] w-full rounded border-0 bg-transparent px-3 py-[0.32rem] leading-[1.6] outline-none transition-all duration-200 ease-linear focus:placeholder:opacity-100 data-[te-input-state-active]:placeholder:opacity-100 motion-reduce:transition-none dark:text-neutral-200 dark:placeholder:text-neutral-200 [&:not([data-te-input-placeholder-active])]:placeholder:opacity-0"
                  id="exampleFormControlInput1"
                  placeholder="Example label" />
                <label
                  for="exampleFormControlInput1"
                  class="pointer-events-none absolute left-3 top-0 mb-0 max-w-[90%] origin-[0_0] truncate pt-[0.37rem] leading-[1.6] text-neutral-500 transition-all duration-200 ease-out peer-focus:-translate-y-[0.9rem] peer-focus:scale-[0.8] peer-focus:text-primary peer-data-[te-input-state-active]:-translate-y-[0.9rem] peer-data-[te-input-state-active]:scale-[0.8] motion-reduce:transition-none dark:text-neutral-200 dark:peer-focus:text-primary"
                  >Example label
                </label>
              </div>
            </form>
            
            
        

    Via JavaScript

    You can access an instance from your Javascript code, by using the getInstance static method of the Input class - it allows making use of all the public methods listed in the Methods section.

    • javascript
    • umd
            
                
            const myValidation = new Validation(document.getElementById("myValidation"), options, classes);
            
            
        
            
                
            const myValidation = new te.Validation(document.getElementById("myValidation"), options, classes);
            
            
        

    Options

    Options can be passed via data attributes or JavaScript. For data attributes, append the option name to data-te-, as in data-te-active-validation="true".

    Name Type Default Description
    activeValidation Boolean false Adds listeners for input events. Checks the validation elements with every input update.
    customErrorMessages Object - Changes the default error messages for each validation type and adds new ones.
    customRules Object - Adds new rules to the existing rule set.
    disableFeedback Boolean false Disables the feedback messages for all validation elements.
    invalidFeedback String "Something is wrong!" Changes the default invalid feedback message for all validation elements.
    submitCallback Function Callback function that is called when the form is submitted and all elements were validated. Example: submitCallback: (e, isValid) => { console.log("Do something ...") }
    validFeedback String "Looks good!" Changes the default valid feedback message for all validation elements.

    Classes

    Custom classes can be passed via data attributes or JavaScript. For data attributes, append the class name to data-te-class, as in data-te-class-notch-leading-valid="border-[#ff0] dark:border-[#ff0] group-data-[te-input-focused]:shadow-[-1px_0_0_#ff0,_0_1px_0_0_#ff0,_0_-1px_0_0_#ff0] group-data-[te-input-focused]:border-[#ff0]"

    Name Default Description
    notchLeadingValid border-[#14a44d] dark:border-[#14a44d] group-data-[te-input-focused]:shadow-[-1px_0_0_#14a44d,_0_1px_0_0_#14a44d,_0_-1px_0_0_#14a44d] group-data-[te-input-focused]:border-[#14a44d] Sets border and shadow of the valid leading notch.
    notchMiddleValid border-[#14a44d] dark:border-[#14a44d] group-data-[te-input-focused]:shadow-[0_1px_0_0_#14a44d] group-data-[te-input-focused]:border-[#14a44d] Sets border and shadow of the valid middle notch.
    notchTrailingValid border-[#14a44d] dark:border-[#14a44d] group-data-[te-input-focused]:shadow-[1px_0_0_#14a44d,_0_-1px_0_0_#14a44d,_0_1px_0_0_#14a44d] group-data-[te-input-focused]:border-[#14a44d] Sets border and shadow of the valid trailing notch.
    notchLeadingInvalid border-[#dc4c64] dark:border-[#dc4c64] group-data-[te-input-focused]:shadow-[-1px_0_0_#dc4c64,_0_1px_0_0_#dc4c64,_0_-1px_0_0_#dc4c64] group-data-[te-input-focused]:border-[#dc4c64] Sets border and shadow of the invalid leading notch.
    notchMiddleInvalid border-[#dc4c64] dark:border-[#dc4c64] group-data-[te-input-focused]:shadow-[0_1px_0_0_#dc4c64] group-data-[te-input-focused]:border-[#dc4c64] Sets border and shadow of the invalid middle notch.
    notchTrailingInvalid border-[#dc4c64] dark:border-[#dc4c64] group-data-[te-input-focused]:shadow-[1px_0_0_#dc4c64,_0_-1px_0_0_#dc4c64,_0_1px_0_0_#dc4c64] group-data-[te-input-focused]:border-[#dc4c64] Sets border and shadow of the invalid trailing notch.
    basicInputValid !border-[#14a44d] focus:!border-[#14a44d] focus:!shadow-[inset_0_0_0_1px_#14a44d] Sets border and shadow of the valid input element.
    basicInputInvalid !border-[#dc4c64] focus:!border-[#dc4c64] focus:!shadow-[inset_0_0_0_1px_#dc4c64] Sets border and shadow of the invalid input element.
    checkboxValid checked:!border-[#14a44d] checked:!bg-[#14a44d] checked:after:!bg-[#14a44d] Sets border and background of the valid checkbox element and its checkmark.
    checkboxInvalid checked:!border-[#dc4c64] checked:!bg-[#dc4c64] checked:after:!bg-[#dc4c64] Sets border and background of the invalid checkbox element and its checkmark.
    radioValid checked:!border-[#14a44d] checked:after:!bg-[#14a44d] Sets border and background of the valid radio element and its checkmark.
    radioInvalid checked:!border-[#dc4c64] checked:after:!bg-[#dc4c64] Sets border and background of the invalid radio element and its checkmark.
    labelValid !text-[#14a44d] Sets the text color of the valid label element.
    labelInvalid !text-[#dc4c64] Sets the text color of the invalid label element.
    validFeedback absolute top-full left-0 m-1 w-auto text-sm text-[#14a44d] animate-[fade-in_0.3s_both] Sets the position, color and animation of the valid feedback message element.
    invalidFeedback absolute top-full left-0 m-1 w-auto text-sm text-[#dc4c64] animate-[fade-in_0.3s_both] Sets the position, color and animation of the invalid feedback message element.
    elementValidated mb-8 Classes that are added to the validated elements when they are validated and feedback is shown.

    Methods

    Asynchronous methods and transitions:
    All API methods are asynchronous and start a transition. They return to the caller as soon as the transition is started but before it ends. In addition, a method call on a transitioning component will be ignored.

    Method Description Example
    dispose Disposes a Validation instance myValidation.dispose()
    getInstance Static method which allows you to get the Validation instance associated to a DOM element. Validation.getInstance(validationEl)
    getOrCreateInstance Static method which returns the Validation instance associated to a DOM element or create a new one in case it wasn't initialized. Validation.getOrCreateInstance(validationEl)
    • javascript
    • umd
            
                
            const validationEl = document.getElementById('myValidation');
            const validation = new Validation(validationEl);
            validation.dispose();
            
            
        
            
                
            const validationEl = document.getElementById('myValidation');
            const validation = new te.Validation(validationEl);
            validation.dispose();
            
            
        

    Events

    Event type Description
    validated.te.validation This event is fired when a validation is performed.
    valid.te.validation This event is fired when a validation is performed and the element is valid.
    invalid.te.validation This event is fired when a validation is performed and the element is invalid.
    changed.te.validation This event is fired when the value of the input element changes.
    • JavaScript
            
                
                const validation = document.getElementById("myValidation");
                validation.addEventListener("changed.te.validation", (event) => {
                  console.log("Do something ...");
                });
              
            
        
    • Import
    • Usage
    • Options
    • Classes
    • Methods
    • Events
    Get useful tips & free resources directly to your inbox along with exclusive subscriber-only content.
    Join our mailing list now
    © 2023 Copyright: MDBootstrap.com