HTML / CSS:嵌套元素树的布局比嵌套表还有什么更好的选择?

问题描述 投票:8回答:11

确定,我有一组用于选择条件的复选框。为了论证,我们将说数据看起来像这样:

[] Vehicles
   [] Unpowered
      [] Bicycle
      [] Skateboard
   [] Powered
      [] Two-wheeled
         [] Motorcycle
         [] Scooter
      [] Four-wheeled
etc

[[s]代表复选框。

忽略此示例的明显作弊性质,其想法是这样的:

  • 首先,只有“车辆”复选框可见;
  • 如果用户单击“车辆”复选框,则弹出下一个级别(已供电,未供电);
  • 如果用户选择了Powered,则会打开下一个级别(两轮,四轮);
  • 如果用户然后取消选中已激活,则该级别消失。

现在,通过onclick的display CSS属性在block和none之间切换相对容易设置。

当前在页面上的结构为:

<table>
<tr>
  <td><input type="checkbox" onclick="toggle('__Vehicles');"></td>
  <td>Vehicles
    <table id="__Vehicles">
    <tr>
      <td><input type="checkbox"></td>
      <td>Unpowered
etc

我应该在有人问之前指出:将复选框放入表格单元格的原因是为了控制格式。由于下一个表单元格中的所有内容都将对齐,因此可以很容易地有效缩进。

一切正常,但是表嵌套变得很深。我一直认为必须有比这更好的方法。它必须能够轻松地动态构建,并具有良好的跨浏览器支持以格式化“树”。

我还应该提到jQuery是可用的。我将它用于其他用途。

建议?

编辑:是的,复选框样式很重要,因为有一些注释已指出。另外,我已经根据收到的答复发布了一个解决方案,作为下面的答案(在此处添加太大了),仅供那些想看示例的人使用。

javascript jquery html css cross-browser
11个回答
21
投票
<ul>
    <li><input type="checkbox" />Vehicles <ul>
        <li><input type="checkbox" />Unpowered</li>
        <li><input type="checkbox" />Bicycle</li>
        <li><input type="checkbox" />Skateboard</li>
    </ul></li>
    <li><input type="checkbox" />Powered <ul>
        <li><input type="checkbox" />Two-wheeled <ul>
            <li><input type="checkbox" />Motorcycle</li>
            <li><input type="checkbox" />Scooter</li>
        </ul></li>
        <li><input type="checkbox" />Four-wheeled</li>
     </ul></li>
</ul>

编辑:一些CSS和JS以显示和隐藏嵌套元素(无复选框)

li.opened ul {
display: block;
}

li.closed ul {
    display: none;
}

和js ...

$(document).ready(function() {

$('li input:checkbox').click(function () {
    $(this).parent().toggleClass('opened');
    $(this).parent().toggleClass('closed');
});

$('li').addClass('closed');
});

再次编辑,因为Sparr需要一些更好的样式(假设复选框的样式为“ checkbox”]

li input.checkbox { /* input:checkbox is not 100% compatible */
    width: 6px;
    margin: 0 2px;
    /* This makes 10px be the total "width" ofh the checkbox */
}

ul {
    margin: 0 0 0 10px; /* Or whatever your total checkbox width is */
    padding: 0;
}

li {
    padding: 0;
}

0
投票

如果复选框的宽度仍然是一个问题(在所有先前的答案之后……),您可以:

  • 将所有复选框置于固定的带框,以便您确切地知道文本的开始位置(以及下一级复选框)
  • 使用一些jquery计算来获取宽度并动态设置其他元素的边距(虽然看起来有点多...]

显然使用建议的嵌套列表结构。


0
投票

这是我创建的最佳示例,您应该参考它:

打开GithuB

CodePen上的实时演示

ScreenShot


10
投票

您可以这样做:

<ul>
  <li>
    <input type="checkbox" /> Option 1
    <ul>
      <li><input type="checkbox" /> Option 1 Sub Option A</li>
    </ul>
  </li>
</ul>

然后您将UL的填充/边距设置为0和0。然后将LI的填充左方设置为10px。

ul {
  margin:0;
  padding:0;
}

li {
  margin:0;
  padding:0 0 0 20px; /* Each nested li will be padded incrementally */
}

对于javascript,将事件附加到每个复选框,以确定是否应该显示同级UL(如果存在)。如果选中此框,则显示它,否则将其隐藏。


4
投票

嵌套的无序列表是此类事情的最佳实践。

<ul>
   <li>Item 1</li>
   <li>Item 2
      <ul>
         <li>Sub Item 1</li>
         <li>Sub Item 2</li>
         <li>Sub Item 3</li>
      </ul>
   </li>
   <li>Item 3</li>
   <li>Item 4
      <ul>
         <li>Sub Item 1</li>
         <li>Sub Item 2</li>
         <li>Sub Item 3</li>
      </ul>
   </li>
</ul>

3
投票

想看一些jQuery的深奥魔术吗?

<ul class="tree">
  <li><input type="checkbox" name="Vehicles" checked>Vehicles
    <ul>
      <li<input type="checkbox" name="Unpowered">Unpowered
        <ul>
          <li><input type="checkbox" name="Bicycle">Bicycle</li>
          <li><input type="checkbox" name="Skateboard">Skateboard</li>
        </ul>
      </li>
      <li><input type="checkbox" name="Powered" checked>Powered
        <ul>
          <li><input type="checkbox" name="Two-wheeled">Two-wheeled
            <ul>
              <li><input type="checkbox" name="Motorcycle" checked>Motorcycle</li>
              <li><input type="checkbox" name="Scooter">Scooter</li>
            </ul>
          </li>
          <li><input type="checkbox" name="Two-Wheeled">Four-wheeled</li>
        </ul>
    </ul>
  </li>
</ul>

注:这里唯一的装饰是树类。

ul.tree {
    list-style-type: none;
    margin: 0 0 0 -22px;
    padding: 0;
}

ul.tree ul {
    list-style-type: none;
    margin: 0;
    padding: 0;
}

ul.tree input {
    margin-right: 6px;
}

ul.tree li {
    padding: 0 0 0 22px;
    margin: 1px;
}

.closed ul {
    display: none;
}

和魔术:

$(function() {
    $("ul.tree li:has(ul) > :checkbox").click(function() {
        jQuery(this).parent().toggleClass('closed');
    }).not(":checked").parent().addClass("closed");
});

当您单击复选框时,整个事情变成了一个有效的开始和结束树。太棒了。

感谢davethegr8,Jonathon Sampson和其他人的建议。


2
投票

除了上面的建议之外,我还建议您从标记中提取JavaScript。使用lowpro(我的最爱)之类的库,您可以创建1个对象来处理嵌套的复选框行为,并自动将其应用,且不会引起干扰。这样打包代码,使标记更易于维护,代码更易于编写,更快,更强大且更易于维护。


1
投票

表是表格数据。改用嵌套列表和CSS进行格式化。


如果您正在寻找一个完整的解决方案,以下是使用纯CSS的现代浏览器和JavaScript的IE:

<style>
ul.tree, ul.tree ul {
    position: relative;
    list-style: none;
    margin: 0 0 0 20px;
    padding: 0;
}
ul.tree input {
    position: absolute;
    margin-left: -20px;
}
ul.tree ul {
    display: none;
}
ul.tree input:checked ~ ul {
    display: block;
}
ul.tree label:hover {
    text-decoration: underline;
}
</style>
<ul class="tree">
  <li>
    <input type="checkbox" id="option1">
    <label for="option1">Option 1</label>
    <ul>
      <li>
       <input type="checkbox" id="option1a">
       <label for="option1a">Option 1 Sub Option A</label>
      </li>
      <li>
       <input type="checkbox" id="option1b">
       <label for="option1b">Option 1 Sub Option B</label>
      </li>
    </ul>
  </li>
  <li>
   <input type="checkbox" id="option2">
   <label for="option2">Option 2</label>
  </li>
</ul>
<!--[if lte IE 7]>
<script>
var tree = document.getElementsByTagName('ul')[0];
tree.attachEvent('onclick', function() {
    var src = event.srcElement;

    if(src.nodeName.toLowerCase() === 'label')
        var box = document.getElementById(src.htmlFor);
    else if(src.nodeName.toLowerCase() === 'input')
        var box = src;
    else return;

    for(var current = src.nextSibling;
        current && current.nodeName.toLowerCase() !== 'ul';
        current = current.nextSibling);

    if(current)
        current.style.display = box.checked ? 'block' : 'none';
});
</script>
<![endif]-->

假设复选框没有比20px宽。


1
投票

虽然jQuery插件mcDropdown以不同的方式解决了嵌套列表问题(没有复选框),但它可能适合您的需求。


0
投票

创建cb时,根据级别给他们css类

<input class="LevelXcb" type="checkbox" />

CSS:

.Level0cb{left:4px;}
.Level1cb{left:16px;}
.Level2cb{left:28px;}

如果“ left”不起作用,请尝试设置“ margin-left”。


0
投票

我知道这与问题没有多大关系,因此请不要投票只是一种建议。

在此示例中,来自davethegr8:

<ul>
    <li>Vehicles <ul>
        <li>Unpowered</li>
        <li>Bicycle</li>
        <li>Skateboard</li>
    </ul></li>
    <li>Powered <ul>
        <li>Two-wheeled <ul>
            <li>Motorcycle</li>
            <li>Scooter</li>
        </ul></li>
        <li>Four-wheeled</li>
     </ul></li>
</ul>

如果给每个步骤一个类,则可以使用jquery在单击时做出一些很酷的下拉效果:

$("li.Two-wheeled").click(function(event){
   $("div.main_wrapper ul.Moto_or_scooter:hidden").slideDown("slow");
}

虽然只是个小建议:)

© www.soinside.com 2019 - 2024. All rights reserved.