# How to Style the OTP Input with is-complete Class in vue3-otp-input

> Learn to style Vue 3 OTP inputs with the is-complete class. Target filled OTP boxes using .your-input-class.is-complete for custom styling in vue3-otp-input.

- Repository: [Ejiro Asiuwhu/vue3-otp-input](https://github.com/ejirocodes/vue3-otp-input)
- Tags: how-to-guide
- Published: 2026-03-01

---

**The vue3-otp-input component automatically applies the `is-complete` CSS class to each input field once it contains a value, allowing you to style filled OTP boxes by targeting the combined selector `.your-input-class.is-complete` in your stylesheet.**

The vue3-otp-input library by ejirocodes provides a customizable one-time password input component for Vue 3 applications. When implementing OTP inputs, providing visual feedback for filled fields improves user experience significantly. The component handles this automatically through its built-in `is-complete` class mechanism, which triggers specific styling when an input contains a value.

## Understanding the is-complete Class Mechanism in vue3-otp-input

The automatic styling behavior originates in the `SingleOtpInput` component. In [`src/components/single-otp-input.vue`](https://github.com/ejirocodes/vue3-otp-input/blob/main/src/components/single-otp-input.vue), the input element uses a dynamic class binding that conditionally applies the `is-complete` class based on the input's current value.

At lines 154-155, the template contains:

```html
<input
  ...
  :class="[inputClasses, conditionalClass, { 'is-complete': model }]"
  ...
/>

```

The `model` ref stores the current character value for that specific input field. When `model` contains any non-empty string, the object `{ 'is-complete': model }` evaluates to truthy, causing Vue to apply the `is-complete` class to the element.

## Implementing Custom Styles with input-classes and conditionalClass Props

The parent `vue3-otp-input` component exposes two key props that control CSS class distribution: `input-classes` and `conditionalClass`.

In [`src/components/vue3-otp-input.vue`](https://github.com/ejirocodes/vue3-otp-input/blob/main/src/components/vue3-otp-input.vue) (lines 37-38), the component passes these props to each `SingleOtpInput` instance:

```html
<SingleOtpInput
  ...
  :input-classes="inputClasses"
  :conditionalClass="conditionalClass?.[i]"
  ...
/>

```

- **input-classes**: Applies base classes to every OTP input field
- **conditionalClass**: Accepts an array of classes, applying a specific class to each corresponding input position

### Basic Styling Example

To style filled OTP inputs, define CSS rules targeting the combination of your base input class and the state class. For example, if you passed `input-classes="otp-box"`, use `.otp-box.is-complete` to style filled states:

```vue
<script setup lang="ts">
import { ref } from "vue";
import VOtpInput from "vue3-otp-input";

const otpValue = ref("");
</script>

<template>
  <v-otp-input
    v-model:value="otpValue"
    :num-inputs="4"
    input-classes="otp-box"
    :should-auto-focus="true"
  />
</template>

<style scoped>
.otp-box {
  width: 3rem;
  height: 3rem;
  font-size: 1.5rem;
  text-align: center;
  border: 2px solid #d1d5db;
  border-radius: 0.5rem;
  transition: all 0.2s ease;
}

.otp-box.is-complete {
  background-color: #dbeafe;
  border-color: #3b82f6;
  color: #1e40af;
}
</style>

```

### Per-Input Styling with conditionalClass

For differentiated styling across OTP fields, such as color-coding each position when filled, combine `conditionalClass` with the `is-complete` selector:

```vue
<script setup lang="ts">
import { ref } from "vue";
import VOtpInput from "vue3-otp-input";

const otpValue = ref("");
const positionClasses = ["digit-1", "digit-2", "digit-3", "digit-4"];
</script>

<template>
  <v-otp-input
    v-model:value="otpValue"
    :num-inputs="4"
    input-classes="base-otp"
    :conditionalClass="positionClasses"
  />
</template>

<style scoped>
.base-otp {
  width: 40px;
  height: 40px;
  text-align: center;
  border: 1px solid #ccc;
  margin: 0 4px;
  border-radius: 4px;
}

/* Default filled state */
.base-otp.is-complete {
  font-weight: bold;
}

/* Position-specific filled states */
.digit-1.is-complete { background-color: #fee2e2; border-color: #ef4444; }
.digit-2.is-complete { background-color: #dcfce7; border-color: #22c55e; }
.digit-3.is-complete { background-color: #dbeafe; border-color: #3b82f6; }
.digit-4.is-complete { background-color: #f3e8ff; border-color: #a855f7; }
</style>

```

The `conditionalClass` array is forwarded to each `SingleOtpInput` via the index-specific binding `conditionalClass?.[i]`, allowing you to target individual input positions with CSS.

## Summary

- The `vue3-otp-input` component automatically applies the `is-complete` CSS class to each input field when it contains a value.
- This behavior is implemented in [`src/components/single-otp-input.vue`](https://github.com/ejirocodes/vue3-otp-input/blob/main/src/components/single-otp-input.vue) through the conditional class binding `{ 'is-complete': model }` at lines 154-155.
- Use the `input-classes` prop to apply base styling to all OTP fields, and target `.your-class.is-complete` for filled states.
- The `conditionalClass` prop accepts an array to apply unique classes to specific input positions, enabling per-field styling variations as implemented in [`src/components/vue3-otp-input.vue`](https://github.com/ejirocodes/vue3-otp-input/blob/main/src/components/vue3-otp-input.vue) lines 37-38.

## Frequently Asked Questions

### How do I change the background color only when an OTP input is filled?

Target the `is-complete` class in combination with your base input class. If you passed `input-classes="otp-box"` to the component, define `.otp-box.is-complete { background-color: #e0e0e0; }` in your stylesheet. The component automatically toggles this class when the internal `model` ref contains a non-empty string.

### Can I apply different styles to each OTP input field when filled?

Yes. Use the `conditionalClass` prop to pass an array of class names, where each index corresponds to an OTP input position. Then define CSS rules combining these position classes with `is-complete`, such as `.position-1.is-complete { border-color: red; }` and `.position-2.is-complete { border-color: green; }`.

### Why isn't the is-complete class appearing on my OTP inputs?

Verify that you are using the correct CSS selector that combines your custom class (passed via `input-classes`) with `is-complete`. Also ensure the component is receiving the `input-classes` prop value correctly. The class only appears when the input actually contains a character, as determined by the `model` ref in [`single-otp-input.vue`](https://github.com/ejirocodes/vue3-otp-input/blob/main/single-otp-input.vue).

### Does the is-complete class work with Tailwind CSS?

Yes. When using Tailwind, pass your utility classes via the `input-classes` prop, and use the `@apply` directive in your style block or arbitrary variants to style the `is-complete` state. For example: `<v-otp-input input-classes="w-12 h-12 text-center border rounded" />` and in your CSS: `.is-complete { @apply bg-blue-100 border-blue-500; }`.