Creating a Tags Input Field using CSS and JavaScript Tutorial

In this tutorial, you can learn how to create a simple Tags Input Field for your web forms or CMS projects. The tutorial aims to provide students and beginners with a reference for learning of building a useful website or web application component and providing them with a free web library for generating Tag Input Fields. Here, I created a simple web page script using the simple library that I created to demonstrate the main goal of this article.

What is a Tags Input Field?

The Tag Input Field is a custom component of a website or web application form that allows the users to dynamically add, update, and remove multiple keywords. This component is often used in a Content Management System or CMS project which allows the author or writers to insert the meta keywords regarding the article they are about to publish. Basically, this feature is compressing the keywords into one field to save some space on the page screen and to easily manage the list of keywords.

How to create a Tags Input Field?

The Tags Input Field can be easily achieved using HTML elements, CSS, and pure JavaScript. Using HTML input, div elements, and some CSS we can build and design a simple form input or more likely a textarea where the keywords will be input. JavaScript will be helpful for giving a creative UI/UX for managing the keywords inside the text field. Check out the sample web page scripts that I provided below to have a better idea of creating this component for an actual web project.

Sample Web Page

The scripts below result in a simple web page that contains a form field for keywords or meta descriptions. The keywords are displayed with a small container with a remove link or button beside each keyword to remove it. It contains also a validation feature for checking duplicates.

Page Interface

The below script is the HTML file script named index.html. It contains the page layout's elements and the Tags Input Field Container.

  1. <!DOCTYPE html>
  2. <html lang="en">
  3.     <meta charset="UTF-8">
  4.     <meta http-equiv="X-UA-Compatible" content="IE=edge">
  5.     <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6.     <title>CSS/JS - Tags Input Field</title>
  7.     <link rel="preconnect" href="https://fonts.googleapis.com">
  8.     <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  9.     <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,[email protected],100..700,0..1,-50..200" />
  10.     <link rel="stylesheet" href="style.css">
  11.     <link rel="stylesheet" href="tagInput.css">
  12.     <script src="tagInput.js"></script>
  13.  
  14. </head>
  15.     <div id="wrapper">
  16.         <div class="page-title">Dynamic Tags Input Field using JavaScript</div>
  17.         <hr style="width:25px">
  18.         <div id="content-wrapper">
  19.             <div>
  20.                 <label><span class="material-symbols-outlined">sell</span> Meta Tags</label>
  21.                 <!-- Tag Input Field -->
  22.                 <div id="tagSampleField"></div>
  23.                 <!-- Tag Input Field -->
  24.             </div>
  25.         </div>
  26.     </div>
  27.     <script>
  28.         /*
  29.         * Initialize Tag Input to selected Element
  30.         * options = (object)
  31.         *   - placeholder
  32.         *   - inputName
  33.         *   - containerClass
  34.         *   - values (Array)
  35.         */
  36.         let SampleTagField = new TagInput('tagSampleField',{
  37.             placeholder:"Enter Keywords Here...",
  38.             inputName:'sampleTagField1',
  39.             containerClass:'MyAdditionalClassName',
  40.             // values: ['test1', '123']
  41.         })
  42.         SampleTagField.init()
  43.        
  44.     </script>
  45. </body>
  46. </html>

Here's the stylesheet of the web page that contains the CSS styles of the layout design of the page interface. The file script is known as the style.css that is loaded on the index page file script.

  1. @import url('https://fonts.googleapis.com/css2?family=Rubik&display=swap');
  2. @import url('https://fonts.googleapis.com/css2?family=Courgette&family=Secular+One&display=swap" rel="stylesheet');
  3. :root{
  4.     --secular-font: 'Secular One', sans-serif;
  5.     --satisfy-font: 'Satisfy', cursive;
  6. }
  7. *{
  8.     box-sizing: border-box;
  9. }
  10. body *{
  11.     font-family: 'Rubik', sans-serif;
  12. }
  13. /**
  14. Page Design
  15. */
  16. body,
  17. html{
  18.     height: 100%;
  19.     width: 100%;
  20.     margin: 0;
  21.     padding: 0;
  22. }
  23. body{
  24.     background-color: #789395;
  25. }
  26. /* Page Wrapper */
  27. #wrapper{
  28.     width: 100%;
  29.     height: 100%;
  30.     display: flex;
  31.     flex-direction: column;
  32.     align-items: center;
  33.     justify-content: center;
  34. }
  35. .page-title{
  36.     font-size: 35px;
  37.     font-family: var(--secular-font);
  38.     letter-spacing: 2px;
  39.     text-align: center;
  40.     color:#fff;
  41.     text-shadow: 0px 0px 5px #7070709c;
  42. }
  43. /* Content Wrapper */
  44. #content-wrapper{
  45.     width: 550px;
  46.     min-height: 200px;
  47.     background: #fff;
  48.     border: 1px solid #cfcfcf;
  49.     box-shadow: 1px 1px 5px #282828c4;
  50.     padding:2em 1.5em;
  51. }
  52. @media (max-width:550px){
  53.     #content-wrapper{
  54.         width: 100%;
  55.     }
  56. }
  57. label {
  58.     display: flex;
  59.     align-items: center;
  60.     margin-bottom:.5em;
  61. }    

Tag Input Fields Stylesheet

The script below is the CSS code that contains the styles of the Tag Input Field elements. This file is known as tagInput.css which is also loaded on the index page file script.

  1. /* Tag Input Field */
  2. .tag-input-field {
  3.     margin-bottom:.5em;
  4. }
  5.  
  6. /* Text Field/Area of the keywords */
  7. .tag-input-field .tag-input{
  8.     width:100%;
  9.     min-height: 50px;
  10.     max-height: 100px;
  11.     overflow-x: hidden;
  12.     display: flex;
  13.     flex-wrap: wrap;
  14.     border:1px solid #b4b4b4;
  15.     padding: .5em .5em;
  16. }
  17. /* Text Field */
  18. .tag-input-field .text-field{
  19.     outline: none;
  20.     padding: .35em;
  21. }
  22. .tag-input .tag-item span[contenteditable="true"]{
  23.     outline: none;
  24. }
  25. /* Text Field Placeholder*/
  26. .tag-input-field:not(:has(.tag-item)) .text-field:empty:before{
  27.     content:var(--inputPlaceHolder);
  28.     font-size: 15px;
  29.     font-style: italic;
  30.     color:#dbdbdb;
  31. }
  32.  
  33. /* Keyword items */
  34. .tag-input-field .tag-item{
  35.     padding: .35em;
  36.     display: flex;
  37.     align-items:center;
  38.     font-size:.9rem;
  39.     background-color: #ededed;
  40.     color:#3c3c3c;
  41.     margin-right:.35em;
  42.     margin-bottom:.35em;
  43. }
  44. /* Item Remove Element */
  45. .tag-input-field .tag-item .tag-item-remove{
  46.     text-decoration:none;
  47.     display: flex;
  48.     align-items: center;
  49.     justify-content: center;
  50.     padding-left:.35em;
  51.     color:#222222;
  52.     cursor: pointer;
  53. }
  54. .tag-input-field .tag-item .tag-item-remove:before{
  55.     content: "\00D7";
  56. }
  57. /*Keywords Hidden inputs*/
  58. .tag-input-field .tag-input-added{
  59.     visibility: none;
  60.     display: none;
  61. }
  62.  
  63. /*Clear All Keywords Element*/
  64. .tag-input-field div:has(.clear-tag-input){
  65.     display: flex;
  66.     flex-wrap: wrap;
  67.     justify-content: end;
  68. }
  69. .tag-input-field .clear-tag-input{
  70.     text-decoration: none;
  71.     color:#504f4f;
  72.     font-size: .8rem;
  73. }

Tag Input Fields JavaScript

Lastly, the below script is the JS file script that contains the code for initializing and making the Tags Field functional. The script is written using the JS OOP Approach or JS Class Object. The file is known as tagInput.js and it is loaded also at the index page.

  1. /**
  2. * Tag Input Field Class Object
  3. * Description: Creates an Input Field where user can dynamically, update, and remove element.
  4. * Purpose: This was built for educational purposes only but can be also used in an actual project.
  5. * Developer: Carlo Montero ([email protected])
  6. */
  7.  
  8. /**
  9. * Syntax
  10. * let myDiv = new TagInput('ElementId', optionsObject);
  11. *      myDiv.init();
  12. */
  13.  
  14. /**
  15. * Option Objects
  16. *  placeholder (optional)- the text to be shown when the field is empty or not filled yet.
  17. *  inputName (optional)- name of the input array for submitting the keywords (default: ElementID)
  18. *  containerClass (optional)- additional class name of the tag field element
  19. *  values (optional)[array] - Default Keywords
  20. */
  21. class TagInput {
  22.     TagField;
  23.     // Creating the Tag Input Field container
  24.     tagFieldHTML = document.createElement('div');
  25.     // Creating the Tag Input Field Item container
  26.     tagItem = document.createElement('div');
  27.     ItemConfirmKeyCodes = [13, 44];
  28.     options;
  29.     constructor(ElementID, options = {}){
  30.         // Element Selector where to place the tag input
  31.         this.TagField = document.getElementById(ElementID)
  32.  
  33.         // Tag Field HTML's properties
  34.         this.tagFieldHTML.classList.add('tag-input-field')
  35.         this.tagFieldHTML.innerHTML = `
  36.                         <div>
  37.                             <a class="clear-tag-input" href="#" title="Remove All Keywords" tabindex="-1">Clear</a>
  38.                         </div>
  39.                         <div class="tag-input">
  40.                             <div class="text-field" contenteditable="true"></div>
  41.                         </div>
  42.                         <div><small><em>Press Enter or add Comma (,) to confirm the keyword</em></small></div>
  43.                         <div class="tag-input-added">
  44.                         </div>`;
  45.         // Tag Field Items properties
  46.         this.tagItem.classList.add('tag-item')
  47.         this.tagItem.innerHTML += `<span contenteditable="true">Sample keyword</span><a href="#" class="tag-item-remove" tabindex="-1"></a>`
  48.  
  49.         //Class options
  50.         this.options = options
  51.         this.options.inputName = this.options.inputName || ElementID
  52.         this.options.placeholder = this.options.placeholder || "Enter keywords here..."
  53.     }
  54.     /** Initialize Tag Field */
  55.     init(){
  56.         // Insert Tag Field Elements inside the given parent Element
  57.         this.TagField.innerHTML = this.tagFieldHTML.outerHTML
  58.  
  59.         //Adding the addional Class Name if given
  60.         if(!!this.options.containerClass){
  61.             this.TagField.classList.add(this.options.containerClass)
  62.         }
  63.  
  64.         //Setting the placeholder text's CSS Variable
  65.         this.TagField.querySelector('.text-field').style = `--inputPlaceHolder:'${this.options.placeholder}'`
  66.        
  67.         // Trigger focus to text field
  68.         this.TagField.querySelector('.tag-input').addEventListener('click', (e) =>{
  69.             e.preventDefault()
  70.             if(e.target == this.TagField.querySelector('.tag-input') )
  71.             this.TagField.querySelector('.text-field').focus()
  72.         })
  73.  
  74.         // Event Listener when keypress
  75.         this.TagField.querySelector('.text-field').addEventListener('keypress', e=>{
  76.             var code = e.keyCode || e.which
  77.    
  78.             if(this.ItemConfirmKeyCodes.includes(code)){
  79.                 e.preventDefault()
  80.                 var textValue = this.TagField.querySelector('.text-field').innerText
  81.                 this.InsertKeyword(textValue)
  82.             }
  83.         })
  84.         //Clear/Remove All Keywords
  85.         this.TagField.querySelector('.clear-tag-input').addEventListener('click', e =>{
  86.             e.preventDefault()
  87.             this.removeAllKeywords()
  88.         })
  89.  
  90.         /** Insert Default Values */
  91.         if(!!this.options.values){
  92.             if(!Array.isArray(this.options.values)){
  93.                 throw Error('Tag Element Default Value requires an Array Value');
  94.             }else{
  95.                 this.options.values.forEach(textValue => {
  96.                     this.InsertKeyword(textValue)
  97.                 })
  98.             }
  99.         }
  100.     }
  101.     /** Insert Keyword as an Item */
  102.     InsertKeyword(TextValue=""){
  103.         var item = this.tagItem.cloneNode(true)
  104.         var textValue = String(TextValue).trim()
  105.         if(textValue === ""){
  106.             return false;
  107.         }
  108.         // List Current keyword iputs
  109.         var currentInputs = [...this.TagField.querySelectorAll('.tag-input-added input')]
  110.         // Check if Text Value already Exists
  111.         var has_duplicate = currentInputs.filter(input => ((input.value).trim()).toLowerCase() == textValue.toLowerCase())
  112.         if(has_duplicate.length <= 0){
  113.             /** Insert If Not Existing Yet */
  114.             var id = Math.floor(Math.random() * (1000 - 1) + 1)
  115.             while(true){
  116.                 if(this.TagField.querySelector(`.tag-item[data-id='${id}']`) !== null){
  117.                     id = Math.floor(Math.random() * (1000 - 1) + 1)
  118.                 }else{
  119.                     break;
  120.                 }
  121.             }
  122.             item.dataset.id = id
  123.             var input = document.createElement('input')
  124.             input.dataset.id= id;
  125.             input.name = `${this.options.inputName}[]`;
  126.             input.value = textValue
  127.             item.querySelector('span[contenteditable="true"]').innerText = textValue
  128.             //insert Keyword input
  129.             this.TagField.querySelector('.tag-input-added').appendChild(input)
  130.             //Insert Keyword Item
  131.             if(this.TagField.querySelectorAll('.tag-item').length > 0){
  132.                 this.TagField.querySelectorAll('.tag-item')[this.TagField.querySelectorAll('.tag-item').length - 1].after(item)
  133.             }else{
  134.                 this.TagField.querySelector('.tag-input').insertBefore(item, this.TagField.querySelector('.text-field'))
  135.             }
  136.             //result text field
  137.             this.TagField.querySelector('.text-field').innerText = ''
  138.  
  139.             //Add event listner to item for updating the value
  140.             item.querySelector('span[contenteditable="true"]').addEventListener('input', (e) => {
  141.                 this.updateTagElement(item.querySelector('span[contenteditable="true"]'))
  142.             })
  143.             item.querySelector('.tag-item-remove').addEventListener('click', (e) => {
  144.                 e.preventDefault()
  145.                 this.TagInputItemRemove(item)
  146.             })
  147.         }else{
  148.             //show dialog if keyword is already listed
  149.             alert("Keyword Already Exists!")
  150.         }
  151.     }
  152.     TagInputItemRemove(el){
  153.         // Function for removing the Item
  154.         var item_id = el.dataset.id
  155.         if(item_id !== undefined){
  156.             if(this.TagField.querySelector(`.tag-input-added [data-id="${item_id}"]`) !== null){
  157.                 this.TagField.querySelector(`.tag-input-added [data-id="${item_id}"]`).remove()
  158.             }
  159.         }
  160.         el.remove();
  161.         this.TagField.querySelector('.tag-input').click()
  162.     }
  163.    
  164.     updateTagElement(el){
  165.         //Function for updating the Keyword input
  166.         var item_id = el.parentElement.dataset.id
  167.         var textValue = (el.innerText).trim()
  168.         if(textValue !== ""){
  169.             if(item_id !== undefined){
  170.                 if(this.TagField.querySelector(`.tag-input-added [data-id="${item_id}"]`) !== null){
  171.                     this.TagField.querySelector(`.tag-input-added [data-id="${item_id}"]`).value = textValue
  172.                 }
  173.             }
  174.         }else{
  175.             this.TagInputItemRemove(el.parentElement)
  176.         }
  177.     }
  178.     removeAllKeywords(){
  179.         //Clear/Remove Items function
  180.         this.TagField.querySelectorAll('.tag-item').forEach(item =>{
  181.             item.remove()
  182.         })
  183.         this.TagField.querySelector('.tag-input-added').innerHTML = ''
  184.         this.TagField.click()
  185.     }
  186. }

Result

The following images are the snapshots of the results using the scripts I have provided above.

Page Layout

Tags Input Field using CSS and JS

Tags Input Field

Tags Input Field using CSS and JS

I have also provided the complete source code's zip file on this website and it is free to download. The download button is located below this tutorial's content.

In addition, the CSS and JS script is ready to use in an actual project or for your current and future projects. To implement it, follow the instruction below.

Steps for using the Tags Input Field Library

  1. Copy and paste the tagInput.css and tagInput.js into your project directory.
  2. Load the files inside your web page file scripts.
    Example
    1. <link rel="stylesheet" href="./tagInput.css">
    2. <script src="./tagInput.js"></script>
    3.    
  3. Add a new HTML div tag in your form page script with an id attribute. This element will serve as the parent container of the Tag Input Field.
    Example
    1. <div id="tagField"></div>
    2.    
  4. Lastly, initiate the Tag Input Field like the following syntax:
    1. /*
    2. * Initialize Tag Input to selected Element
    3. * options = (object)
    4. *   - placeholder (string) [optional]
    5. *   - inputName (string) [optional]
    6. *   - containerClass (string) [optional]
    7. *   - values (Array) [optional]
    8. */
    9. let tagField = new TagInput('tagField',{
    10.     placeholder:"Enter Keywords Here...",
    11.     inputName:'tags',
    12.     containerClass:'MyAdditionalClassName',
    13.     values: ['Sample Keyword 1', 'Sample Keyword 2']
    14. })
    15. tagField.init()
    16.    

There you go! I hope this Creating a Tags Input Field using CSS and JavaScript Tutorial and the free library will help you with what you are looking for and will be useful for your current and future web application projects.

Explore more on this website for more Tutorials and Free Source Codes.

Happy Coding =)

Add new comment