Is there a way to apply a CSS style on HTML5 datalist options?
Like select elements, the datalist element has very little flexibility in styling. You cannot style any of the suggested terms if that's what your question was asking.
Browsers define their own styles for these elements.
Styling is not Working on option of datalist
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>
Select intelligently from a drop down list
Suppose you have a datalist like below :
<datalist id="locations">
<option value="India taj mahal">
<option value="India Qutub Minar">
<option value="China gate">
</datalist>
Now you can select all option values and put them in an array like below :
var options = document.getElementById('locations').options;
var values = [];
for(var i=0; i<options.length; i++)
{
values.push(options[i].value);
}
Now let's suppose your search term is India Minar, so you can build a search logic something like below :
var searchTerm = "India Minar";
var searchSplit = searchTerm.split(" ");
var availableSearches = [];
for(var i=0; i<values.length; i++) {
for(var j=0; j<searchSplit.length; j++) {
if(values[i].indexOf(searchSplit[j]) >= 0 &&
availableSearches.indexOf(values[i]) < 0){
availableSearches.push(values[i]);
}
}
}
console.log(availableSearches);
//["India taj mahal", "India Qutub Minar"]
This logic will search text with both India and Minar in the collection. If this is not exactly you are looking for, you can easily tweak logic.
Show datalist labels but submit the actual value
Note that datalist
is not the same as a select
. It allows users to enter a custom value that is not in the list, and it would be impossible to fetch an alternate value for such input without defining it first.
Possible ways to handle user input are to submit the entered value as is, submit a blank value, or prevent submitting. This answer handles only the first two options.
If you want to disallow user input entirely, maybe select
would be a better choice.
To show only the text value of the option
in the dropdown, we use the inner text for it and leave out the value
attribute. The actual value that we want to send along is stored in a custom data-value
attribute:
To submit this data-value
we have to use an <input type="hidden">
. In this case we leave out the name="answer"
on the regular input and move it to the hidden copy.
<input list="suggestionList" id="answerInput">
<datalist id="suggestionList">
<option data-value="42">The answer</option>
</datalist>
<input type="hidden" name="answer" id="answerInput-hidden">
This way, when the text in the original input changes we can use javascript to check if the text also present in the datalist
and fetch its data-value
. That value is inserted into the hidden input and submitted.
document.querySelector('input[list]').addEventListener('input', function(e) {
var input = e.target,
list = input.getAttribute('list'),
options = document.querySelectorAll('#' + list + ' option'),
hiddenInput = document.getElementById(input.getAttribute('id') + '-hidden'),
inputValue = input.value;
hiddenInput.value = inputValue;
for(var i = 0; i < options.length; i++) {
var option = options[i];
if(option.innerText === inputValue) {
hiddenInput.value = option.getAttribute('data-value');
break;
}
}
});
The id answer
and answer-hidden
on the regular and hidden input are needed for the script to know which input belongs to which hidden version. This way it's possible to have multiple input
s on the same page with one or more datalist
s providing suggestions.
Any user input is submitted as is. To submit an empty value when the user input is not present in the datalist, change hiddenInput.value = inputValue
to hiddenInput.value = ""
Working jsFiddle examples: plain javascript and jQuery
Related Topics
Create a Complex CSS Shape (Speaking Bubble)
How to Horizontally Center-Crop Div Inside Other Div
Using @Font-Face CSS Stylewith an Arabic Font
Change Div Order on Responsive Design
Change Cursor Over HTML5 Canvas When Dragging The Mouse
Simple Two Column HTML Layout Without Using Tables
Media Query Works on Mobile Firefox But Doesn't Work on Mobile Chrome
Where Should I Use CSS Vendor Prefixes
How Debug Placeholder Pseudo Element in Firefox
CSS How to Properly Use Ems Instead of Pixels
Divs Appearing Different on Different Browsers
Jekyll Liquid Variables as Inline CSS Values
Video Player Shows Black Border
Will Whitespace or Wrap Be Ignored Between Two Block Elements in HTML
HTML 5 Autofocus Messes Up CSS Loading