Skip to content

Tag Input

<quiet-tag-input> stable since 5.0 form control This component is a form-associated custom element. It will submit its value when given a name and placed inside a <form>.

Allows users to add and remove tags by typing and pressing Enter.

Use tag inputs when users need to enter multiple, freeform values in a single field. They're ideal for things like keywords, labels, and categories where the input isn't constrained to a predefined list.

Type each cat's name and press Enter
<quiet-tag-input
  label="Pet names"
  placeholder="Type a name"
  with-clear
>
  <span slot="description">
    Type each cat's name and press <kbd>Enter</kbd>
  </span>
</quiet-tag-input>

Examples Jump to heading

Labels and descriptions Jump to heading

You can use the label and description attributes to provide plain text labels and descriptions for the tag input. If you want to provide HTML, use the label and description slots instead.

Favorite treats Type a treat and press Enter to add it
<quiet-tag-input placeholder="Add a treat">
  <span slot="label">Favorite treats</span>
  <span slot="description">
    Type a treat and press <kbd>Enter</kbd> to add it
  </span>
</quiet-tag-input>

Providing an initial value Jump to heading

Use the value attribute to pre-populate tags with a comma-separated list. To add or remove tags after initialization, use the addTag() and removeTag() methods or set the value property directly.

<quiet-tag-input
  label="Favorite nap spots"
  placeholder="Add a nap spot"
  value="Cardboard box, Sunbeam, Laundry basket"
  with-clear
></quiet-tag-input>

You can change the delimiter used to parse the value attribute with the delimiter property.

Adding a clear button Jump to heading

Add the with-clear attribute to show a clear button when the tag input has tags. This allows users to quickly remove all tags at once.

<quiet-tag-input
  label="Grocery list"
  placeholder="Add an item"
  value="Tuna, Catnip, Wet food"
  with-clear
></quiet-tag-input>

Start and end content Jump to heading

Use the start and end slots to add presentational icons or text. Avoid interactive elements such as buttons, links, etc. Works well with <quiet-icon> and <svg> elements.


<quiet-tag-input label="Favorite toys" placeholder="Add a toy" with-clear>
  <quiet-icon slot="start" name="tag"></quiet-icon>
</quiet-tag-input>

<br>

<quiet-tag-input label="Pet sitters" placeholder="Add an email" with-clear>
  <quiet-icon slot="start" name="mail"></quiet-icon>
  <quiet-icon slot="end" name="send"></quiet-icon>
</quiet-tag-input>

Filled and unstyled tag inputs Jump to heading

Use the appearance attribute to change the visual style of the tag input. Options are normal (default), filled, and unstyled.



<quiet-tag-input
  label="Normal"
  appearance="normal"
  placeholder="Add a cat"
></quiet-tag-input>

<br>

<quiet-tag-input
  label="Filled"
  appearance="filled"
  placeholder="Add a cat"
></quiet-tag-input>

<br>

<quiet-tag-input
  label="Unstyled"
  appearance="unstyled"
  placeholder="Add a cat"
></quiet-tag-input>

Pill-shaped tag inputs Jump to heading

Add the pill attribute to give the tag input rounded edges. Tags inside will also become pill-shaped.

<quiet-tag-input
  label="Hobbies"
  placeholder="Add a hobby"
  value="Napping, Knocking things off tables, Zooming at 3 AM"
  pill
  with-clear
></quiet-tag-input>

Changing the size Jump to heading

Use the size attribute to change the tag input's size. Available sizes are xs, sm, md (default), lg, and xl.

<quiet-select label="Select a size" value="xs" style="max-width: 18rem; margin-block-end: 2rem;">
  <option value="xs">Extra small</option>
  <option value="sm">Small</option>
  <option value="md">Medium</option>
  <option value="lg">Large</option>
  <option value="xl">Extra large</option>
</quiet-select>

<quiet-tag-input
  size="xs"
  label="Cat breeds"
  description="Size changes dynamically based on selection above"
  placeholder="Add a breed"
  value="Persian, Siamese"
  id="tag-input__size"
  with-clear
></quiet-tag-input>

<script>
  const tagInput = document.getElementById('tag-input__size');
  const select = tagInput.previousElementSibling;

  select.addEventListener('quiet-change', () => {
    tagInput.size = select.value;
  });
</script>

Disabling the tag input Jump to heading

Add the disabled attribute to disable the tag input. Existing tags will still be visible but cannot be removed.

<quiet-tag-input
  label="Feeding schedule"
  description="This tag input is disabled"
  value="Breakfast, Dinner"
  disabled
></quiet-tag-input>

Readonly Jump to heading

Add the readonly attribute to make the tag input read-only. Existing tags are visible but cannot be added or removed. Unlike disabled, a readonly tag input can still receive focus and its value is included in form submissions.

<quiet-tag-input
  label="Things to do"
  description="These roles are managed by your furry friend"
  value="Nap supervisor, Treat inspector, Box tester"
  readonly
></quiet-tag-input>

Showing labels on the side Jump to heading

With the quiet-side-label utility, you can show labels on the side instead of on top of the tag input. You can control the width of the label by setting the --label-width custom property.


<quiet-tag-input
  class="quiet-side-label"
  style="--label-width: 10ch;"
  label="Indoor cats"
  placeholder="Add a cat"
></quiet-tag-input>
<br>
<quiet-tag-input
  class="quiet-side-label"
  style="--label-width: 10ch;"
  label="Outdoor cats"
  placeholder="Add a cat"
></quiet-tag-input>

Allowing duplicates Jump to heading

By default, duplicate values are silently rejected. Add the allow-duplicates attribute to allow the same value to be added more than once.

<quiet-tag-input
  label="Cat sounds"
  description="The same sound can be added more than once"
  placeholder="Add a sound"
  allow-duplicates
  with-clear
></quiet-tag-input>

Limiting the number of tags Jump to heading

Use the max attribute to set a maximum number of tags. Once the limit is reached, no more tags can be added.

<quiet-tag-input
  label="Top 3 nap spots"
  description="You can add up to 3 nap spots"
  placeholder="Add a nap spot"
  max="3"
  with-clear
></quiet-tag-input>

Changing the delimiter Jump to heading

By default, typing a comma will create a tag from the preceding text. You can change the delimiter character(s) using the delimiter attribute. Each character in the string is treated as a separate delimiter. Set delimiter="" to disable delimiter-based tag creation entirely.

Pasting text that contains delimiters will automatically split the pasted text into individual tags.

<quiet-tag-input
  label="Comma-separated cats"
  description="Type a comma or press Enter to add a cat"
  placeholder="Add a cat"
  with-clear
></quiet-tag-input>

Use a custom delimiter such as a space:

<quiet-tag-input
  label="Space-separated cats"
  description="Type a space or press Enter to add a cat"
  placeholder="Add a cat"
  delimiter=" "
  with-clear
></quiet-tag-input>

You can also use multiple delimiter characters. In this example, both commas and semicolons will create tags:

<quiet-tag-input
  label="Multiple delimiters"
  description="Commas and semicolons both work"
  placeholder="Add a cat"
  delimiter=",;"
  with-clear
></quiet-tag-input>

To disable delimiter-based tag creation, set delimiter to an empty string:

<quiet-tag-input
  label="Enter only"
  description="Only pressing Enter adds a cat"
  placeholder="Add a cat"
  delimiter=""
  with-clear
></quiet-tag-input>

Customizing tag values and display Jump to heading

Override the getTagValue() method to transform typed text into a stored value, and the getTagContent() method to customize how tags are rendered. The getTagContent() method receives the tag's value and returns a string.

In this example, typing "Sleepy Kittens" will store the value as sleepy-kittens and display the tag as #sleepy-kittens.

<quiet-tag-input
  label="Hashtags"
  description="Values are converted to slugs and shown with a # prefix"
  placeholder="Add one or more hashtags"
  with-clear
  id="tag-input__custom"
></quiet-tag-input>

<script>
  const tagInput = document.getElementById('tag-input__custom');
  tagInput.getTagValue = (query) => query.trim().toLowerCase().replace(/\s+/g, '-');
  tagInput.getTagContent = (value) => `#${value}`;
</script>

Rejecting tags Jump to heading

The quiet-create event is cancelable. Call event.preventDefault() to reject a tag before it gets added. This is useful for custom validation, such as ensuring tags match a specific format.

<quiet-tag-input
  label="Pet sitters"
  description="Only valid email addresses are accepted"
  placeholder="Add a cat sitter's email"
  with-clear
  id="tag-input__reject"
></quiet-tag-input>

<script>
  const tagInput = document.getElementById('tag-input__reject');

  tagInput.addEventListener('quiet-create', event => {
    const email = event.detail.value;
    if (!email.includes('@') || !email.includes('.')) {
      event.preventDefault();
    }
  });
</script>

Validation Jump to heading

The required attribute can be used to enable validation using the Constraint Validation API .


Submit Reset
<form action="about:blank" method="get" target="_blank">
  <quiet-tag-input
    name="tags"
    label="Required cats"
    placeholder="Add at least one cat"
    required
  ></quiet-tag-input>
  <br>
  <quiet-button type="submit" variant="primary">Submit</quiet-button>
  <quiet-button type="reset">Reset</quiet-button>
</form>

Min and max validation Jump to heading

Use the min and max attributes to validate the number of tags. The max attribute also prevents adding tags beyond the limit. Validation messages are shown after the user interacts with the form control or when the form is submitted.


Submit Reset
<form action="about:blank" method="get" target="_blank">
  <quiet-tag-input
    name="tags"
    label="Favorite tricks"
    description="Add between two and five tricks your cat likes to do"
    placeholder="Add a trick"
    min="2"
    max="5"
    with-clear
  ></quiet-tag-input>
  <br>
  <quiet-button type="submit" variant="primary">Submit</quiet-button>
  <quiet-button type="reset">Reset</quiet-button>
</form>

Using custom validation Jump to heading

Use the setCustomValidity() method to make the tag input invalid and show a custom error message on submit. This will override all other validation parameters. To clear the error, call the method with an empty string.


Submit
<form action="about:blank" method="get" target="_blank" id="tag-input__custom-validation">
  <quiet-tag-input
    name="tags"
    label="Dinner menu"
    description="Don't forget the wet food!"
    placeholder="Add a meal"
    with-clear
  ></quiet-tag-input>
  <br>
  <quiet-button type="submit" variant="primary">Submit</quiet-button>
</form>

<script type="module">
  import { allDefined } from '/dist/quiet.js';

  await allDefined();

  const form = document.getElementById('tag-input__custom-validation');
  const tagInput = form.querySelector('quiet-tag-input');

  tagInput.setCustomValidity('The schedule must include "Wet food"');

  tagInput.addEventListener('quiet-change', () => {
    const hasWetFood = tagInput.value.some(
      (tag) => tag.toLowerCase() === 'wet food'
    );

    if (hasWetFood) {
      tagInput.setCustomValidity('');
    } else {
      tagInput.setCustomValidity('The schedule must include "Wet food"');
    }
  });
</script>

Styling validation Jump to heading

You can style valid and invalid tag inputs using the user-valid and user-invalid custom states. These styles are only shown after the user interacts with the form control or when the form is submitted.


Submit Reset
<form action="about:blank" method="get" target="_blank" class="tag-input__validation-custom">
  <quiet-tag-input
    name="tags"
    label="Required cats"
    placeholder="Add at least one cat"
    required
  ></quiet-tag-input>
  <br>
  <quiet-button type="submit" variant="primary">Submit</quiet-button>
  <quiet-button type="reset">Reset</quiet-button>
</form>

<style>
  .tag-input__validation-custom {
    quiet-tag-input:state(user-valid) {
      outline: solid 2px var(--quiet-constructive-stroke-mid);
      outline-offset: .5rem;
    }

    quiet-tag-input:state(user-invalid) {
      outline: solid 2px var(--quiet-destructive-stroke-mid);
      outline-offset: .5rem;
    }
  }
</style>

API Jump to heading

Importing Jump to heading

The autoloader is the recommended way to import components but, if you prefer to do it manually, the following code snippets will be helpful.

CDN Self-hosted

To manually import <quiet-tag-input> from the CDN, use the following code.

import 'https://cdn.quietui.org/v5.0.0/components/tag-input/tag-input.js';

To manually import <quiet-tag-input> from a self-hosted distribution, use the following code. Remember to replace /path/to/quiet with the appropriate local path.

import '/path/to/quiet/components/tag-input/tag-input.js';

Slots Jump to heading

Tag Input supports the following slots. Learn more about using slots

Name Description
label The tag input's label. For plain-text labels, use the label attribute instead.
description The tag input's description. For plain-text descriptions, use the description attribute instead.
start An icon or similar element to place before the input. Works great with <quiet-icon>.
end An icon or similar element to place after the input. Works great with <quiet-icon>.

Properties Jump to heading

Tag Input has the following properties that can be set with corresponding attributes. In many cases, the attribute's name is the same as the property's name. If an attribute is different, it will be displayed after the property. Learn more about attributes and properties

Property Description Reflects Type Default
query The current text in the tag input's text box. Useful for reading when handling quiet-input events. (Property only) string ''
label The tag input's label. string
description The tag input's description. string
name The name of the tag input for form submission. string
value The tag input's value as an array of strings. Can be set via attribute as a delimiter-separated string. string[]
placeholder Placeholder text for the input. string
disabled Disables the tag input. boolean false
readonly Makes the tag input readonly. Tags are visible but cannot be added or removed. boolean false
required Makes the tag input required. boolean false
appearance The visual appearance of the tag input. 'normal'
'filled'
'unstyled'
'normal'
size The size of the tag input. 'xs'
'sm'
'md'
'lg'
'xl'
'md'
pill Draws the tag input in a pill shape. boolean false
min The minimum number of tags required for validation. Set to 0 for no minimum. number 0
max The maximum number of tags allowed. Set to 0 for no limit. When the limit is reached, no more tags can be added. number 0
delimiter One or more characters that will create a tag when typed. For example, set delimiter="," so typing a comma adds a tag. Each character in the string is treated as a separate delimiter. Set to an empty string to disable delimiter-based tag creation. string ','
form The form to associate with. string
allowDuplicates
allow-duplicates
Allows duplicate tag values. By default, duplicate values are silently rejected. boolean false
withClear
with-clear
Adds a clear button when not blank. boolean false
inputmode Provides the browser with a hint about the type of data that might be entered by the user, allowing the appropriate virtual keyboard to be displayed on supported devices. 'none'
'text'
'decimal'
'numeric'
'tel'
'search'
'email'
'url'
autocapitalize Turns autocapitalize on or off in supported browsers. 'off'
'none'
'on'
'sentences'
'words'
'characters'
autocorrect Turns autocorrect on or off in supported browsers. boolean
enterkeyhint Sets the enter key label on virtual keyboards. 'enter'
'done'
'go'
'next'
'previous'
'search'
'send'
spellcheck Turns spell checking on or off in supported browsers. boolean

Methods Jump to heading

Tag Input supports the following methods. You can obtain a reference to the element and call them like functions in JavaScript. Learn more about methods

Name Description Arguments
addTag() Adds a tag with the given text. Returns true if the tag was added, false otherwise. text: string
removeTag() Removes a tag by its value. Removes the first occurrence if duplicates exist. Returns true if removed. value: string
removeTagByIndex() Removes a tag by its index. Returns true if removed, false if the index is out of bounds or readonly. index: number
hasTag() Returns true if a tag with the given value exists. value: string
clear() Removes all tags.
getTagValue() Returns the value stored for a tag given the user's typed text. Override this method to customize how typed text is transformed into a stored value (e.g., lowercasing or converting to slug). query: string
getTagContent() Returns the display content for a tag. Override this method to customize how tags are rendered. By default, returns the tag's value as plain text. value: string
focus() Sets focus to the tag input.
blur() Removes focus from the tag input.
checkValidity() Checks if the form control has any restraints and whether it satisfies them. If invalid, false will be returned and the invalid event will be dispatched. If valid, true will be returned.
reportValidity() Checks if the form control has any restraints and whether it satisfies them. If invalid, false will be returned and the invalid event will be dispatched. In addition, the problem will be reported to the user. If valid, true will be returned.
setCustomValidity() Sets a custom validation message for the form control. If this message is not an empty string, then the form control is considered invalid and the specified message will be displayed to the user when reporting validity. Setting an empty string clears the custom validity state. message: string

Events Jump to heading

Tag Input dispatches the following custom events. You can listen to them the same way was native events. Learn more about custom events

Name Description
quiet-blur Emitted when the tag input loses focus.
quiet-change Emitted when a tag is added, removed, or cleared.
quiet-focus Emitted when the tag input receives focus.
quiet-input Emitted when the tag input receives input.
quiet-create Emitted when a new tag is about to be created. Call event.preventDefault() to reject the tag. The event detail contains value and label properties.

CSS custom properties Jump to heading

Tag Input supports the following CSS custom properties. You can style them like any other CSS property. Learn more about CSS custom properties

Name Description Default
--text-box-min-width The minimum width of the input field when shown next to tags. 12ch

CSS parts Jump to heading

Tag Input exposes internal elements that can be styled with CSS using the selectors shown below. Learn more about CSS parts

Name Description CSS selector
label The element that contains the tag input's label. ::part(label)
description The element that contains the tag input's description. ::part(description)
visual-box The element that wraps the internal text box. ::part(visual-box)
input-area The wrapper surrounding tags and the internal text box. ::part(input-area)
tag Individual tag elements. ::part(tag)
tag-label The text label inside a tag. ::part(tag-label)
tag-remove The remove button for tags. ::part(tag-remove)
text-box The internal text box, an <input> element. ::part(text-box)
clear-button The clear button. ::part(clear-button)

Custom States Jump to heading

Tag Input has the following custom states. You can target them with CSS using the selectors shown below. Learn more about custom states

Name Description CSS selector
disabled Applied when the tag input is disabled. :state(disabled)
focused Applied when the tag input has focus. :state(focused)
blank Applied when the tag input has no value. :state(blank)
user-valid Applied when valid after user interaction. :state(user-valid)
user-invalid Applied when invalid after user interaction. :state(user-invalid)

Dependencies Jump to heading

Tag Input automatically imports the following elements. Sub-dependencies are also included in this list.

Search this website Toggle dark mode View the code on GitHub Follow @quietui.org on Bluesky Follow @quiet_ui on X

    No results found