在“SELECT”标签中呈现一个“OPTION”层次结构

26

我遇到了HTML和CSS相关的问题。我有一个层次结构,其中包含我想要在列表中显示的国家、州和城市(它是三级深度)。

我想将该层次结构显示在选择列表中,每个项目类型(国家、州、城市)都必须可选。这些项应呈缩进形式显示:

United States
- Hawaii
-- Kauai
- Washington
-- Seattle
-- Chelan

问题出在缩进方面。我试图使用margin-left或padding-left来缩进<select>标签,这在FireFox中看起来正确,但在IE7中却不行。以下是生成的下拉列表的示例:

<select name="Something">
<option style="padding-left: 0">United States</option>
<option style="padding-left: 20px">Hawaii</option>
<option style="padding-left: 40px">Kauai</option>
<option style="padding-left: 20px">Washington</option>
<option style="padding-left: 40px">Seattle</option>
<option style="padding-left: 40px">Chelan</option>
</select>

我想在不使用CSS hack的情况下实现跨浏览器的一致缩进。


请参见https://dev59.com/M3NA5IYBdhLWcg3wPbWe。 - Matija Nalis
8个回答

51

SELECT元素的渲染很大程度上取决于浏览器,你几乎无法对它们的呈现产生太大影响。有些浏览器显然允许您更多的自定义,而IE却允许的很少(惊讶吧,谁想到呢?)。如果您需要非常自定义的SELECT元素,则需要使用JavaScript或重新创建类似于SELECT但由一堆DIV和复选框等组成的东西。

话虽如此,我认为您要找的是OPTGROUP

<select>
  <optgroup label="xxx">
    <option value="xxxx">xxxx</option>
    ....
  </optgroup>
  <optgroup label="yyy">
    ...
  </optgroup>
</select>

每个浏览器都会以一种独特的方式展示它们,但它们在某种程度上都会以一个独特的方式显示。请注意,在 HTML4 中,您不能嵌套OPTGROUP


1
作为备选方案,您始终可以像示例中那样显示它们,使用破折号进行缩进。 - deceze
1
@deceze 引用问题中的话:“每个项目类型(国家、州、城市)都必须可选择”。我怀疑optgroup是可选择的。 - o.k.w
没错。然后他要么需要将它们分组并使用分组标签作为标签,要么只需跳过我的答案的第二部分。 - deceze
3
嗯...我认为无法嵌套使用optgroup,我的意思是,我可以将optgroup用于国家级别,但我不能将它们用于州级别。 - Salman A

25

deceze 的方法更好,而且这也是我的第一个想法。如果那个方法行不通,你还可以在标签值中使用非断空格:

<select>
    <option>select me</option>
    <option>&nbsp;me indented</option>
    <option>&nbsp;&nbsp;even more indentation</option>
</select>

它并不美观,但如果optgroup不起作用,它可能适合您。


3
很抱歉,这确实是最可靠的解决方案。 - Ms2ger
11
这不是一个好的解决方案,因为按字母搜索不起作用。 - MicTech
如果你所说的“按字母搜索”是指通过键入来获取结果,那么我认为这不应该是一个非常大的动力因素。该功能在浏览器中的工作方式非常特定,并且在我看来,普通用户并没有广泛使用它。 如果这不是你所指的,那么恐怕我不知道你在说什么。 - MacAnthony
2
似乎Chrome会忠实地呈现“ ”,所以我不得不使用连字符。 - Anentropic
3
Chrome浏览器中,&nbsp;的缩进很小,并且还会被渲染为选定值。如果这不是您想要的效果,请尝试使用&emsp; - evilkos

14

基于访问者考虑,我觉得应该分享一下我想出的解决方案:http://jsfiddle.net/n9qpN/

使用 level 类修饰选项

<select name="hierarchiacal">
<option class="level_1">United States</option>
    <option class="level_2">Hawaii</option>
        <option class="level_3">Kauai</option>
    <option class="level_2">Washington</option>
        <option class="level_3">Seattle</option>
        <option class="level_3">Chelan</option>
</select>

我们现在可以使用jQuery重新格式化select元素的内容

$(document).ready(
function(){
   $('.level_2').each(
        function(){
            $(this).text('----'+$(this).text());
        }
   );

   $('.level_3').each(
        function(){
            $(this).text('---------'+$(this).text());
        }
   );

 }
);

这可以扩展到任何级别


这是最优雅的解决方案。 - alas
有没有办法调整JS,以便可以使用空格来缩进,而不是使用----字符?我尝试过使用&nbsp;,但它会原样插入到<option>值中,而不被解释为不换行空格。例如:&nbsp;&nbsp;夏威夷 - undefined
通过使用@Skywalker的答案的一部分,我自己找到了问题的答案,并将其添加到答案中。 - undefined

6

尝试使用&#160;

<select name="Something">
  <option>United States</option>
  <option>&#160;Hawaii</option>
  <option>&#160;&#160;Kauai</option>
  <option>&#160;Washington</option>
  <option>&#160;&#160;Seattle</option>
  <option>&#160;&#160;Chelan</option>
</select>


2

这种分组方法是否会带来更多问题而不是解决问题?作为用户,我应该选择哪个呢?选择比国家更具体的选项有什么好处吗?

如果问题在于只有一个数据库字段可用于存储它们,为什么不使用三个单独的选择框(使2或3个可选),并仅存储最具体的内容:

<select name="country">
    <option>Choose a country</option>
    <option>United States</option>
</select>
<select name="state">
    <option>Choose a state</option>
    <option>Hawaii</option>
</select>
<select name="city">
    <option>Choose a city</option>
    <option>Kauai</option>
</select>

我需要为此目的进行级联的“onchange=populate_next_select();”。此外,我想要以一种全面的方式呈现整个列表。 - Salman A
@Salman A:为什么?反正您已经完全填充了一个选择框,那为什么不把所有三个都填满呢?不过,您提供整个列表的观点是合理的。 - Simon Scarfe
7
为什么?客户是这么说的 :( - Salman A
4
你好,我来自2017年。客户仍然是“永远正确”的。 - a20

1

1
Prepending Non-breaking space (&nbsp) did not work for me.
我尝试在前面添加了以下内容:

String.fromCharCode(8194);


1
我喜欢上面@codingbiz提出的解决方案: https://dev59.com/W3M_5IYBdhLWcg3w9oaG#11600605 我稍微修改了一下jquery代码,使其更通用。 因此,不再需要在脚本中手动定义每个可能的层级,而是使用data-level属性来定义层次结构中的位置。 注意:您有责任提供有意义的值,以便层次结构有意义。
请查看代码片段。

$('select.hierarchy').each(function() {

        $(this).children('option').each(function(){

            attr = $(this).attr('data-level');

            multiplier = 1;   // increase the value, if you want larger indents, i.e. 3
            indent = (typeof attr !== 'undefined' && attr !== false) ? parseInt(attr) * multiplier : 0;

            $(this).html("&nbsp;".repeat(indent) + $(this).text());
        });
        
    });
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<select class="hierarchy" id="select" name="select">
<option value="NULL"></option>
<option value="1" data-level="0">Option 1</option>
<option value="2" data-level="1">Option 1.1</option>
<option value="3" data-level="2">Option 1.1.1</option>
<option value="4" data-level="1">Option 1.2</option>
<option value="5" data-level="0">Option 2</option>
<option value="6" data-level="1">Option 2.1</option>
<option value="7" data-level="1">Option 2.2</option>
<option value="8" data-level="2">Option 2.2.1</option>
</select>


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