有没有一种方法可以在HTML5的datalist选项上应用CSS样式?

135

我想修改datalist中不同选项的显示方式。是否可以应用一些CSS属性?

<input list="languages" id="language_id">
<datalist id="languages">
      <option value="html">HTML</option>
      <option value="java">Java</option>
      <option value="perl">Perl</option>
      <option value="php">PHP</option>
      <option value="ruby-on-rails">Ruby on Rails</option>
</datalist>

我尝试过

option {
    background: red;
}

但似乎它并不起作用。


7个回答

117

select 元素一样,datalist 元素在样式方面非常灵活。如果您的问题是要求可以样式化建议的任何术语,那么对不起,这个元素是不能被样式化的。

浏览器会为这些元素定义自己的样式。


4
相关内容:Firefox供应商特定的CSS扩展列表(其中包括占位符等,但没有类似数据列表的内容):https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Mozilla_Extensions - ANeves
8
我希望有一种方法可以始终更改原生元素的样式,例如datalists和selects。 - t3__rry
嗯,这在2013年可能是正确的,但现在你可以像这样做: datalist选项 { 字体大小:0.8em; 内边距:0.3em 1em; 背景颜色:#ccc; 光标:指针; } 完全可以正常工作。 - undefined
@RWC:你一定生活在一个与我们其他人不同的宇宙中。在我们的宇宙中,即使是一个简单的 datalist option {color:red;} 也会完全被忽略。 - undefined
特别为火星人玛莎准备的一个代码示例:https://codepen.io/r-w-c/pen/KKbYbxW 取消注释 datalist 选项,看看不可能的事情如何发生。唉! - undefined

7
我在这个Codepen上找到了实现的代码:https://codepen.io/sidd_dev/pen/qBRWNQQ?editors=1010 下图是它的效果: enter image description here 我已在以下浏览器中测试通过:
- Chrome 108.0.5359.99(官方版)(64位) - Firefox 107.0.1(64位)
更多关于浏览器支持的细节,请查看: https://caniuse.com/?search=datalist

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");
    }
  }
fieldset {
  border: 1px solid blue;
  width: 360px;
  border-radius: 5px;
}

legend, label{
  color: blue; 
  font-size: 24px;
  font-family: sans-serif;
}

input {
  font-size: 18px;
  padding: 5px;
  height: 35px;
  width: 350px;
  border: 1px solid blue;
  outline: none;
  border-radius: 5px;
  color: blue;
/*   border-bottom: none; */
}
datalist {
  position: absolute;
  background-color: white;
  border: 1px solid blue;
  border-radius: 0 0 5px 5px;
  border-top: none;
  font-family: sans-serif;
  width: 350px;
  padding: 5px;
  max-height: 10rem;
  overflow-y: auto
  
}

option {
  background-color: white;
  padding: 4px;
  color: blue;
  margin-bottom: 1px;
   font-size: 18px;
  cursor: pointer;
}

option:hover,  .active{
  background-color: lightblue;
}
  <fieldset>
    <legend>
      Datalist Form
    </legend>
    <label>Select Browser</label>
    <input  autocomplete="off" role="combobox" list="" id="input" name="browsers" placeholder="Select your fav browser">
  <!-- 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="Internet Explorer">Internet Explorer</option>
  <option value="Chrome">Chrome</option>
  <option value="Safari">Safari</option>
    <option value="Microsoft Edge">Microsoft Edge</option>
    <option value="Firefox">Firefox</option><option value="Microsoft Edge">Microsoft Edge</option>
    <option value="Firefox">Firefox</option><option value="Microsoft Edge">Microsoft Edge</option>
    <option value="Firefox">Firefox</option><option value="Microsoft Edge">Microsoft Edge</option>
    <option value="Firefox">Firefox</option><option value="Microsoft Edge">Microsoft Edge</option>
    <option value="Firefox">Firefox</option><option value="Microsoft Edge">Microsoft Edge</option>
    <option value="Firefox">Firefox</option><option value="Microsoft Edge">Microsoft Edge</option>
    <option value="Firefox">Firefox</option><option value="Microsoft Edge">Microsoft Edge</option>
    <option value="Firefox">Firefox</option><option value="Microsoft Edge">Microsoft Edge</option>
    <option value="Firefox">Firefox</option><option value="Microsoft Edge">Microsoft Edge</option>
    <option value="Firefox">Firefox</option>
  </datalist>
<!--     <br>
    <br>
    <label for="pwd"> Password </label>
    <input id="pwd" type="password">
     -->
  </fieldset>


2
有趣的是,对于那个说这是不可能的答案,有100个投票,而只有2个投票支持那个说“这里有一个字面上的例子,说明它是如何可能的”的答案。我知道这里有微妙之处,但还是这样。 - Brian Davis
6
“这里有一个字面上的例子,说明它是如何实现的”,主要是通过使用JavaScript重新创建了选择/ 下拉框行为-此时datalist和option元素也可以很容易地变成span或div ...您可以看到示例缺少原生功能,例如点击外部处理等。” - kano
1
@kano 欢迎随时添加您的建议。 - Orhan
6
我只是想强调为什么其他100个得票答案声称没有简单或本地解决方案。我认为我没有提供自己的解决方案并不会无效化我的陈述背后的真相。这就像要求拳击评论员或教练在你听取他们的批评或建议之前展示他们的拳击生涯统计数据一样。选择这种解决方案的人应该意识到它的缺点,仅此而已。 - kano
3
我只是试图强调为什么其他100票答案声称没有简单或本地解决方案是可能的。我认为我不提供自己的解决方案并不以任何方式否定了我的陈述背后的真实性。这就像要求拳击评论员或教练在你听他们的批评或建议之前先展示他们的拳击生涯统计数据一样。选择这种解决方案的人应该意识到它的缺点,仅此而已。 - kano

2

我们可以尝试使用 datalist-css 这个包,链接如下: enter link description here

这里是 StackBlitz 示例:

https://angular-datalist-option-hvvgcz.stackblitz.io

css应该是:--

datalist {
  position: absolute;
  max-height: 20em;
  border: 0 none;
  overflow-x: hidden;
  overflow-y: auto;
}

datalist option {
  font-size: 0.8em;
  padding: 0.3em 1em;
  background-color: #ccc;
  cursor: pointer;
}

/* option active styles */
datalist option:hover,
datalist option:focus {
  color: #fff;
  background-color: #036;
  outline: 0 none;
}

#browserdata option {
  font-size: 1.8em;
  padding: 0.3em 1em;
  background-color: #ccc;
  cursor: pointer;
}

HTML将是:

--

<label for="browser">browser:</label>

<input
  list="browserdata"
  id="browser"
  name="browser"
  size="50"
  autocomplete="off"
/>

<datalist id="browserdata">
  <option>Brave</option>
  <option>Chrome</option>
  <option>Edge</option>
  <option>Firefox</option>
  <option>Internet Explorer</option>
  <option>Opera</option>
  <option>Safari</option>
  <option>Vivaldi</option>
  <option>other</option>
</datalist>

2
@Orhan发布的Codepen还有一些改进的空间,我想到了一个基于该代码的解决方案,并决定分享出来。当下拉菜单失去焦点或没有可用选项时,它会正确地隐藏下拉菜单。本来想将其整理得更好并制作成jQuery插件,但我觉得先发布原始代码比较好。此外,该代码还具有响应式宽度,以匹配输入字段的长度,但保持最小宽度,如果需要显示完整的选项文本,则会扩展超出输入框的宽度。

function fancyDropdown(inputId){
    id = document.getElementById(inputId);
    datalist = id.nextElementSibling;
  var minWidth = datalist.offsetWidth;
    

  function outputsize(){
    if (id.offsetWidth < minWidth ){
      datalist.style.minwidth = id.offsetWidth+'px';
    }else{
      datalist.style.width = id.offsetWidth+'px';
    }
  }

  new ResizeObserver(outputsize).observe(id);


  id.addEventListener("input", function(e){
    datalist.style.display = "block";
    var text = id.value.toUpperCase();
    let hide = 1;
    for (let option of datalist.options) {
      if(option.value.toUpperCase().indexOf(text) > -1){
        option.style.display = "block";
        hide = 0;
      }else{
        option.style.display = "none";
      }
    }
    if (hide){
        datalist.style.display = "none";
    }
  });



  id.addEventListener("click", function(e){
  
    let hide = 1;
    for (let option of datalist.options) {
        if (window.getComputedStyle(option, null).display == "block") hide = 0;
    }
  
    if (datalist.style.display == "block" || hide == 1){
      datalist.style.display = "none";
    }else{
      datalist.style.display = "block";
    }
  });
  

  document.addEventListener("click", function(e){

    if (e.target.tagName == "OPTION"){
      id.value = e.target.value;
    }
    if (e.target.tagName !== "DATALIST" && e.target.tagName !== "INPUT"){
      datalist.style.display = "none";
    }

  });

    datalist.style.display = "none";

}


fancyDropdown('product');
body{background: #272b2f;color:white}
input{transition: 0.2s;width:50%;margin:0;box-sizing:border-box;padding:8px;border:1px solid #404449;outline:none;border-radius:4px;background:#212529;color:#e7e7e7}

input:focus{border: 1px solid #db9c2e; box-shadow: 0px 0px 3px 0px #db9c2e;border-radius:4px 4px 0 0;}

datalist {
  margin-top:-1px;
  overflow-y: auto;
  box-sizing: border-box;
  display: block;
  position: absolute;
  background-color: #212529;
  border: 1px solid #404449;
  border-radius: 0 0 4px 4px;
  font-family: sans-serif;
  padding: 5px;
  max-height: 10rem;
  border: 1px solid #db9c2e; box-shadow: 0px 0px 3px 0px #db9c2e;
}

option {
  padding: 4px;
  color: #e7e7e7;
  margin-bottom: 1px;
  font-size: 18px;
  cursor: pointer;
  display:block;
}

option:hover{background-color: #3f4348;}
<input type="text" id="product" name="product" list="" />
<datalist id="mylist">
  <option value="John Paul Jacobs">John Paul Jacobs</option>
  <option value="Dorothy Tornado">Dorothy Tornado</option>
  <option value="Inigo Montoya">Inigo Montoya asdf asdf asdfadfasdfs</option>
  <option value="John Paul Jacobs">John Paul Jacobs</option>
  <option value="Dorothy Tornado">Dorothy Tornado</option>
  <option value="Inigo Montoya">Inigo Montoya asdf asdf asdfadfasdfs</option>
  <option value="John Paul Jacobs">John Paul Jacobs</option>
  <option value="Dorothy Tornado">Dorothy Tornado</option>
  <option value="Inigo Montoya">Inigo Montoya asdf asdf asdfadfasdfs</option>
  <option value="John Paul Jacobs">John Paul Jacobs</option>
  <option value="Dorothy Tornado">Dorothy Tornado</option>
  <option value="Inigo Montoya">Inigo Montoya asdf asdf asdfadfasdfs</option>
  <option value="John Paul Jacobs">John Paul Jacobs</option>
  <option value="Dorothy Tornado">Dorothy Tornado</option>
  <option value="Inigo Montoya">Inigo Montoya asdf asdf asdfadfasdfs</option>
</datalist>

<div>
<p>
putting some stuff here for the big brown fox running over the river to get the turtle to feed to its pet frog.
</p>
</div>


0

编辑:
在查看了几个其他库之后,我发现react-datalist-input提供了最简单的与React交互的方式,无论是样式还是功能。

您可以通过以下方式访问样式

.datalist-input  

下面是一个简单的代码片段:
const DataListWrapper = styled.div`
    display: flex;
    justify-content: center;
    align-items: center;
    margin-top: 6px;

    .datalist-input {
        width: 50%;
        color: black;
    }
`;

const SomeComponent = () => {
    return (
        <DataListWrapper>
            <ReactDataList
                forcePoly
                placeholder="Search Something..."
                list="my_list"
                options={options}
                onOptionSelected={(e) => foo(e)}
            />
        </DataListWrapper>
    );
};

旧答案:
(注意:react-datalist未得到维护,其某些依赖项已被弃用)

在使用React时,您可以使用样式选项和数据列表本身:

react-datalist

https://www.npmjs.com/package/react-datalist

你可以使用CSS或styled-components来访问这些内容。
.react-datalist  
.react-datalist-option

这里是一个使用styled-components的简单代码片段:

    const DataListWrapper = styled.div`
          display: flex;
          justify-content: center;
          align-items: center;
          margin-top: 6px;
    
          .datalist-input {
              width: 50%;
              color: black;
          }
    `;
    
    const SomeComponent = () => {
        return (
            <>
                <DataListWrapper>
                    <DataListInput
                        placeholder="Search Something..."
                        items={items}
                        onSelect={DoSomething}
                    />
                </DataListWrapper>
            </>
        );
    };

-6

你可以使用Jquery创建一个替代的数据列表

$(document).on('dblclick', 'input[list]', function(event){
    event.preventDefault();
        var str = $(this).val();
    $('div[list='+$(this).attr('list')+'] span').each(function(k, obj){
            if($(this).html().toLowerCase().indexOf(str.toLowerCase()) < 0){
                $(this).hide();
            }
        })
    $('div[list='+$(this).attr('list')+']').toggle(100);
    $(this).focus();
})

$(document).on('blur', 'input[list]', function(event){
        event.preventDefault();
        var list = $(this).attr('list');
        setTimeout(function(){
            $('div[list='+list+']').hide(100);
        }, 100);
    })

    $(document).on('click', 'div[list] span', function(event){
        event.preventDefault();
        var list = $(this).parent().attr('list');
        var item = $(this).html();
        $('input[list='+list+']').val(item);
        $('div[list='+list+']').hide(100);
    })

$(document).on('keyup', 'input[list]', function(event){
        event.preventDefault();
        var list = $(this).attr('list');
    var divList =  $('div[list='+$(this).attr('list')+']');
    if(event.which == 27){ // esc
        $(divList).hide(200);
        $(this).focus();
    }
    else if(event.which == 13){ // enter
        if($('div[list='+list+'] span:visible').length == 1){
            var str = $('div[list='+list+'] span:visible').html();
            $('input[list='+list+']').val(str);
            $('div[list='+list+']').hide(100);
        }
    }
    else if(event.which == 9){ // tab
        $('div[list]').hide();
    }
    else {
        $('div[list='+list+']').show(100);
        var str  = $(this).val();
        $('div[list='+$(this).attr('list')+'] span').each(function(){
          if($(this).html().toLowerCase().indexOf(str.toLowerCase()) < 0){
            $(this).hide(200);
          }
          else {
            $(this).show(200);
          }
        })
      }
    })
* {
  scrollbar-width: thin;
    scrollbar-color: #BBB #EEE;
}

*::-webkit-scrollbar {
  width: 10px;
}

*::-webkit-scrollbar-track {
  background: #C0C3C6;
}

*::-webkit-scrollbar-thumb {
  background-color: #888;
  border-radius: 10px;
  border: 3px solid #C0C3C6;
}

table {
    width: 400px;
    margin: 0 auto;
    background: #EEE;
    font-family: Arial;
    padding: 10px 30px;
  border-radius: 5px;
  box-shadow: 0 5px 5px -5px #000;
    --border: 1px solid #ABC;
}
table td {
  padding-bottom: 10px;
}
table h4 {
  text-align: center;
  color: #567;
  border: 1px solid #567;
  border-radius: 3px;
  padding: 15px 0;
}
input {
    padding: 10px;
    font-size: 1em;
    width: calc(100% - 20px);
    border: var(--border);
    border-radius: 3px;
}
input[list]:focus {
    outline: none;
}
input[list] + div[list] {
    display: none;
    position: absolute;
    width: 100%;
    max-height: 164px;
    overflow-y: auto;
    max-width: 330px;
    background: #FFF;
    border: var(--border);
    border-top: none;
  border-radius: 0 0 5px 5px;
  box-shadow: 0 3px 3px -3px #333;
    z-index: 100;
}
input[list] + div[list] span {
    display: block;
    padding: 7px 5px 7px 20px;
    color: #069;
    text-decoration: none;
    cursor: pointer;
}
input[list] + div[list] span:not(:last-child) {
  border-bottom: 1px solid #EEE;
}
input[list] + div[list] span:hover {
    background: rgba(100, 120, 140, .2);
}

table .instructions {
  font-size: .9em;
  color: #900;
}
table .instructions b {
  color: #123;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<table width="400">
    <tr>
        <td> <h4>DATALIST STYLING ALTERNATIVE</h4> </td>
    </tr>
    <tr>
        <td>
            <div>Programming languages</div>
            <input type="text" name="language" list="list-language">
            <div list="list-language">
                <span>CSharp</span>
                <span>Delphi</span>
                <span>Flutter</span>
                <span>Java</span>
                <span>Java Script</span>
                <span>PHP</span>
                <span>Python</span>
                <span>Ruby</span>
                <span>SAP</span>
                <span>Visual Basic</span>
            </div>
        </td>
    </tr>
    <tr>
        <td>
            <div>Cities</div>
            <input type="text" name="cities" list="list-cities">
            <div list="list-cities">
                <span>Athens</span>
                <span>Beijing</span>
                <span>Berlin</span>
                <span>Cairo</span>
                <span>Lisbon</span>
        <span>London</span>
        <span>Mexico City</span>
                <span>Moscow</span>
                <span>New York</span>
                <span>Rio de Janeiro</span>
                <span>Rome</span>
                <span>Tokyo</span>
            </div>
        </td>
    </tr>
  <tr>
    <td>
      <div class='instructions'>
        <b>INSTRUCTIONS:</b><hr>
        <p><b>Double click on the input:</b><br>Show/hide the datalist.</p>
        <p><b>Press esc on the input:</b><br>Hides datalist if visible.</p>
        <p><b>Onkeypress in the input:</b><br>Displays the datalist filtering according to the entered string.</p>
        <p><b>On pressing enter:</b><br>Ff there is only 1 element in the datalist, this value will be loaded into the input.</p>
      </div>
    <td>
  </tr>
</table>


7
为什么您使用基于表格的布局? - haldo
3
原问题是如何应用样式,而不是有哪些替代方案。 - Sanan Ali
它能够运行,但不符合问题的要求。 - undefined

-16

尝试:

input[list]
{
  background: red;
}

6
在 Firefox 30 中,input[list] 样式会应用在文本框上,但不会应用在下拉列表上。而在 IE 11 中,它会同时应用在文本框和下拉列表上。 - Darren Griffith
这个方法不能用于改变数据列表的背景颜色,但可以用于改变输入框的背景颜色。 - Samz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接