How to Customize OTP Input Styling with Conditional Classes per Input in Vue 3
Use the conditionalClass prop on the vue3-otp-input component to pass an array of class names—one per input box—allowing distinct styling for each OTP digit position.
The vue3-otp-input library provides a flexible way to build one-time password forms in Vue 3. To customize OTP input styling with conditional classes per input in Vue 3, the component exposes a conditionalClass prop that accepts an array of strings mapped to each individual input box.
How the conditionalClass Prop Works
The implementation spans two core components. The root vue3-otp-input component validates and forwards the class array, while the child SingleOtpInput applies the specific class to its rendered <input> element.
Prop Definition in the Root Component
In src/components/vue3-otp-input.vue, the component defines conditionalClass as an optional prop expecting an array of strings. The array length must match the numInputs prop to ensure every OTP box receives a class definition:
// src/components/vue3-otp-input.vue (lines 15-18)
props: {
conditionalClass: {
type: Array as PropType<string[]>,
default: [],
},
// ...
}
Forwarding Classes to Individual Inputs
The root component iterates over the numInputs range and passes the corresponding array index to each child. It uses optional chaining to safely handle cases where conditionalClass is undefined:
<!-- src/components/vue3-otp-input.vue (lines 38-40) -->
<SingleOtpInput
v-for="(item, i) in numInputs"
:key="i"
:conditionalClass="conditionalClass?.[i]"
...
/>
Class Binding in SingleOtpInput
The child component src/components/single-otp-input.vue receives the single string and merges it into the input's class list alongside base styles and completion states:
<!-- src/components/single-otp-input.vue (lines 54-55) -->
<input
:class="[inputClasses, conditionalClass, { 'is-complete': model }]"
...
/>
This binding ensures that any class passed from the parent array is applied directly to the specific OTP input element.
Practical Implementation Examples
The following patterns demonstrate how to customize OTP input styling with conditional classes per input in Vue 3 for static, dynamic, and utility-first CSS workflows.
Static Styling per Input Box
Apply distinct border colors to each position for visual segmentation:
<template>
<v-otp-input
:num-inputs="4"
:conditionalClass="['first-box', 'second-box', 'third-box', 'fourth-box']"
v-model:value="code"
/>
</template>
<style>
.first-box { border: 2px solid #4caf50; }
.second-box { border: 2px solid #2196f3; }
.third-box { border: 2px solid #ff9800; }
.fourth-box { border: 2px solid #f44336; }
</style>
Dynamic Classes Based on Input State
Toggle background colors depending on whether the user has entered a value:
<script setup lang="ts">
import { ref, computed } from 'vue';
const code = ref('');
const conditionalClasses = computed(() => {
const chars = code.value.padEnd(4, '_').split('');
return chars.map(c => (c === '_' ? 'empty-box' : 'filled-box'));
});
</script>
<template>
<v-otp-input
:num-inputs="4"
:conditionalClass="conditionalClasses"
v-model:value="code"
/>
</template>
<style>
.empty-box { background: #f0f0f0; }
.filled-box { background: #c8e6c9; }
</style>
Tailwind CSS Gradient Styling
Use utility classes to create a color progression across the OTP fields:
<template>
<v-otp-input
:num-inputs="6"
:conditionalClass="['bg-red-100', 'bg-orange-100', 'bg-amber-100', 'bg-yellow-100', 'bg-lime-100', 'bg-green-100']"
input-classes="w-10 h-10 text-center border rounded"
/>
</template>
Key Implementation Files
The styling pipeline relies on three specific source files in the ejirocodes/vue3-otp-input repository:
-
src/components/vue3-otp-input.vue– Defines theconditionalClassprop (lines 15‑18) and forwards the indexed class value to each child input (lines 38‑40). -
src/components/single-otp-input.vue– Receives the individual class string and binds it to the<input>element alongside base and state classes (lines 54‑55). -
README.md– Documents the prop signature and the requirement that the array length must equalnumInputs.
Summary
- The
conditionalClassprop accepts an array of strings where each index maps to a specific OTP input box. - The root component validates the prop and forwards the appropriate class via
conditionalClass?.[i]to eachSingleOtpInputchild. - Individual classes are merged into the input's class list in
single-otp-input.vue, allowing per-box styling without affecting sibling inputs. - You can use static arrays, computed properties, or Tailwind utilities to implement visual states such as color coding, completion indicators, or gradient effects.
Frequently Asked Questions
Can I use conditionalClass with any CSS framework?
Yes. The conditionalClass prop accepts plain strings, so you can pass Tailwind utility classes, Bootstrap classes, BEM naming conventions, or scoped CSS module identifiers. The component applies the string directly to the input's class attribute without transformation.
What happens if the array length doesn't match numInputs?
The component does not enforce runtime validation, but the README specifies that the array length should equal numInputs. If the array is shorter, undefined values are passed to the remaining inputs via optional chaining ?.[i], resulting in no extra classes being applied to those boxes. Excess entries in a longer array are ignored.
How do I apply different styles based on whether the input is filled?
Use a computed property to generate the conditionalClass array dynamically. Map over the current OTP value and return a class name for filled positions and a different one for empty positions. Because the array is reactive, Vue updates the classes instantly as the user types or deletes digits.
Can I combine conditionalClass with the input-classes prop?
Absolutely. The input-classes prop applies base styles to every OTP input, while conditionalClass provides per-index overrides. In single-otp-input.vue, the final class binding merges both: [inputClasses, conditionalClass, ...]. This allows you to set common sizing and spacing via input-classes and unique colors or borders via conditionalClass.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →