Search code examples
javascripthtmlcssreactjsdropdown

Styling is not Working on option of datalist


I am trying to change background color of option on hover but I am not able to do that in datalist. Is there any way to achieve this? I tried by giving inline css, external css, by events (onmouseover, onmouseenter, onmouseleave)

/*  React Js Code */
<input  type="text" list="browsers" />

<datalist id="browsers">
/* iterating values from array and showing in option */
<option style={{backgroundColor:'red'}} onMouseOver={e=>e.target.style.color = 'green'}  onMouseEnter={(e)=>e.target.style.background = 'red'} 
onMouseLeave={(e)=>e.target.style.background = 'black'} >{d}</option>
</datalist>

Solution

  • you can customise the datalist using CSS but you'll have to disable/ignore the OOB datalist functionality and rewrite the functionality using JavaScript and the result is below:

    input.onfocus = function() {
      browsers.style.display = 'block';
      input.style.borderRadius = "5px 5px 0 0";
    };
    for (let option of browsers.options) {
      option.onclick = function() {
        input.value = option.value;
        browsers.style.display = 'none';
        input.style.borderRadius = "5px";
      }
    };
    
    input.oninput = function() {
      currentFocus = -1;
      var text = input.value.toUpperCase();
      for (let option of browsers.options) {
        if (option.value.toUpperCase().indexOf(text) > -1) {
          option.style.display = "block";
        } else {
          option.style.display = "none";
        }
      };
    }
    var currentFocus = -1;
    input.onkeydown = function(e) {
      if (e.keyCode == 40) {
        currentFocus++
        addActive(browsers.options);
      } else if (e.keyCode == 38) {
        currentFocus--
        addActive(browsers.options);
      } else if (e.keyCode == 13) {
        e.preventDefault();
        if (currentFocus > -1) {
          /*and simulate a click on the "active" item:*/
          if (browsers.options) browsers.options[currentFocus].click();
        }
      }
    }
    
    function addActive(x) {
      if (!x) return false;
      removeActive(x);
      if (currentFocus >= x.length) currentFocus = 0;
      if (currentFocus < 0) currentFocus = (x.length - 1);
      x[currentFocus].classList.add("active");
    }
    
    function removeActive(x) {
      for (var i = 0; i < x.length; i++) {
        x[i].classList.remove("active");
      }
    }
    input {
      font-size: 18px;
      padding: 5px;
      height: 35px;
      width: 350px;
      border: 1px solid #000;
      outline: none;
      border-radius: 5px;
      color: #000;
      /*   border-bottom: none; */
    }
    
    datalist {
      position: absolute;
      background-color: white;
      border: 1px solid #000;
      border-radius: 0 0 5px 5px;
      border-top: none;
      width: 350px;
      padding: 5px;
    }
    
    option {
      background-color: white;
      padding: 4px;
      color: #000;
      margin-bottom: 1px;
      font-size: 18px;
      cursor: pointer;
      background: #eeeeee
    }
    
    option:hover,
    .active {
      background-color: red;
    }
    <input autocomplete="off" role="combobox" list="" id="input" name="browsers">
    <!-- Its important that you keep list attribute empty to hide the default dropdown icon and the browser's default datalist -->
    
    <datalist id="browsers" role="listbox">
      <option value="Chrome">Chrome</option>
      <option value="Safari">Safari</option>
      <option value="Microsoft Edge">Microsoft Edge</option>
    </datalist>

    from DEV