Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HTML/CSS: what's a better option for layout of a tree of nested elements than nested tables?

Ok, I have a set of checkboxes for selecting criteria. For argument's sake, we'll say the data looks like this:

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

The []s represent checkboxes.

Ignoring the obviously contrived nature of this example, the idea is this:

  • To start with, only the Vehicle checkbox is visible;
  • If the user clicks on the Vehicle checkbox is opsn up the next level (Powered, Unpowered);
  • If the user selects Powered it opens up the next level (Two-wheeled, Four-wheeled);
  • If the user then unchecks Powered, that level disappears.

Now this is relatively easy to set up with onclick's toggling the display CSS attribute between block and none.

This is currently structured on the page as:

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

I should point out before someone asks: the reason the checkbox was put in table cell was to control formatting. It made it easy to effectively indent since everything in the next table cell would line up.

It all works fine but the table nesting gets pretty deep. I keep thinking there has to be a better way than this. It has to be able to be easily built dynamically and have good cross-browser support for formatting of the "tree".

I should also mention that jQuery is available. I'm using it for other things.

Suggestions?

Edit: Yes the checkbox styling is important as a couple of comments have noted. Also, I have posted a solution to this, based on the responses I've gotten, as an answer below (too big to add here), just for those curious to see an example.

like image 476
cletus Avatar asked Jan 27 '09 22:01

cletus


2 Answers

<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>

Edit: a little css & js to show & hide nested elements (no checkboxes)

li.opened ul {
display: block;
}

li.closed ul {
    display: none;
}

and js...

$(document).ready(function() {

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

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

edit, again, because Sparr wants some better styles (assuming that the checkboxes have a style of "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;
}
like image 192
davethegr8 Avatar answered Oct 25 '22 02:10

davethegr8


You could do this:

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

You'd then set the padding/margin of the UL's to 0 and 0. Then set the padding-left of the LI's to 10px.

ul {
  margin:0;
  padding:0;
}

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

For the javascript, attach an event to each checkbox that determines whether the sibling UL (if any exists) should be visible. If the box is checked, show it, else, hide it.

like image 30
Sampson Avatar answered Oct 25 '22 00:10

Sampson