monitorjbl
monitorjbl

Reputation: 4350

HTML unordered list with columns

I want to format my unordered list into two sections of text. I've been trying to find out how to do this with Google. but everyone seems interested in making their lists flow left to right, which is not what I want to do. What I'm looking for is a way to make the following:

 Food                Calories

 Fruit
    -Apple            90
    -Grape            5
    -Berries          
       -Strawberry    16
       -Blueberry     9
 Vegetable
    -Cucumber         12
    -Onions            
       -Red           29
       -White         34
       -Vidalia       47

Is this possible with an unordered list and CSS? I'd prefer not to use a table for this, since I'd like to make the <li> expand and contract.

EDIT: Hopefully it looks more like an expand/contract hierarchy now than strictly tabular data. I understand that it's possible to do this with a table, it just seems less natural to present a hierarchy that way.

Upvotes: 1

Views: 3453

Answers (6)

Berto
Berto

Reputation: 712

One JavaScript-free solution you could try using is the new column-count CSS property. Watch out for IE though, it's not going to be supported unless they're at IE10+: http://caniuse.com/multicolumn

ul {
     -webkit-column-count: 3; /* Beware of IE Problems */
}

This might not perfectly "split" your data, but it's worth exploring for others coming to this page.

Upvotes: 0

DidoSaidi
DidoSaidi

Reputation: 131

Try to do like this. I've used the same technique to do a fluid restaurant menu.

ul { width:20em;} 
ul:first-child {font-weight: 700}
ul ul {font-weight: 400}

ul span:first-child { padding-left:1em;}
ul span + span { float:right;}

<ul>
    <li>fruit</li>
    <ul>
        <li><span>apple</span><span>90</span></li>
        <li><span>grappe</span><span>5</span></li>
        <li><span>strawberry</span><span>16</span></li>
        <li><span>etc</span><span>5.25</span></li>        
    </ul>
    <li>vegetable</li>
    <ul>
        <li><span>cucumber</span><span>12</span></li>
        <li><span>Onion</span><span>29</span></li>   
    </ul>    
</ul>

see it here : DEMO

Upvotes: 2

David Thomas
David Thomas

Reputation: 253308

With the following HTML you can do this (and, frankly, with other HTML you could do this...) but you should use tables.

Anyway, that said, the HTML I'm working with:

<ul>
    <li class="head">
        <span class="col1">Food</span>
        <span class="col2">Calories</span>
    </li>
    <li>Fruits
        <ul>
            <li>
                <span class="col1">Apple</span>
                <span class="col2">90</span>
            </li>
            <li>
                <span class="col1">Grape</span>
                <span class="col2">5</span>
            </li>
            <li>
                <span class="col1">strawberry</span>
                <span class="col2">16</span>
            </li>
        </ul></li>
    <li>Vegetable
        <ul>
            <li>
                <span class="col1">Cucumber</span>
                <span class="col2">12</span>
            </li>
            <li>
                <span class="col1">Onion</span>
                <span class="col2">29</span>
            </li>
        </ul></li>
</ul>​

And the CSS:

li.head {
    font-weight: bold;
}
span.col1,
span.col2 {
    display: inline-block;
    width: 48%;
}

ul > li > ul > li {
    padding-left: 10%;
    height: 0;
    line-height: 0;
    overflow: hidden;
    -webkit-transition: all 1s linear;
}

ul > li:hover > ul > li {
    height: 2em;
    line-height: 2em;
    -webkit-transition: all 1s linear;
}

ul > li > ul > li span:first-child::before {
    content: '-';
    width: 40%;
}

li li:nth-child(odd) span {
    background-color: #aaf;
}
​

JS Fiddle demo.

To allow for keyboard navigation, and showing the nested foods/calorie values in response to tab-events, I've amended the HTML a little to wrap the fruits and vegetable text with an a element:

<ul>
    <li class="head">
        <span class="col1">Food</span>
        <span class="col2">Calories</span>
    </li>
    <li><a href="#">Fruits</a>
        <ul>
            <li>
                <span class="col1">Apple</span>
                <span class="col2">90</span>
            </li>
            <li>
                <span class="col1">Grape</span>
                <span class="col2">5</span>
            </li>
            <li>
                <span class="col1">strawberry</span>
                <span class="col2">16</span>
            </li>
        </ul></li>
    <li><a href="#">Vegetable</a>
        <ul>
            <li>
                <span class="col1">Cucumber</span>
                <span class="col2">12</span>
            </li>
            <li>
                <span class="col1">Onion</span>
                <span class="col2">29</span>
            </li>
        </ul></li>
</ul>​

With the following CSS:

li.head {
    font-weight: bold;
}

li a {
    color: inherit;
    text-decoration: none;
}

span.col1,
span.col2 {
    display: inline-block;
    width: 48%;
}

ul > li > ul > li {
    padding-left: 10%;
    height: 0;
    line-height: 0;
    overflow: hidden;
    -moz-transition: all 1s linear;
    -ms-transition: all 1s linear;
    -o-transition: all 1s linear;
    -webkit-transition: all 1s linear;
    transition: all 1s linear;
}

ul > li a:focus + ul > li,
ul > li:hover > ul > li {
    height: 2em;
    line-height: 2em;
    -moz-transition: all 1s linear;
    -ms-transition: all 1s linear;
    -o-transition: all 1s linear;
    -webkit-transition: all 1s linear;
    transition: all 1s linear;
}

ul > li > ul > li span:first-child::before {
    content: '-';
    width: 40%;
}

li li:nth-child(odd) span {
    background-color: #aaf;
}
​

JS Fiddle demo.

Both of these, however, assume that you want to hide automatically, and show based on user-interaction. If that assumption's incorrect then the transitions aren't necessary.

Incidentally, an accordion-like table solution:

<table>
    <colgroup>
        <col class="foods" />
        <col class="calories" />
    </colgroup>
    <thead>
        <tr>
            <th>Food</th>
            <th>Calories</th>
        </tr>
    </thead>
    <tbody>
        <tr class="header">
            <td colspan="2">Fruits</td>
        </tr>
        <tr>
            <td>Apple</td>
            <td>90</td>
        </tr>
        <tr>
            <td>Grape</td>
            <td>5</td>
        </tr>
        <tr>
            <td>Strawberry</td>
            <td>16</td>
        </tr>
    </tbody>
    <tbody>
        <tr class="header">
            <td colspan="2">Vegetable</td>
        </tr>
        <tr>
            <td>Cucumber</td>
            <td>12</td>
        </tr>
        <tr>
            <td>Onion</td>
            <td>29</td>
        </tr>
    </tbody>
</table>

CSS:

.foods,
.calories {
    width: 8em;
}

tbody tr.header {
    height: 2em;
    line-height: 2em;
}

tbody tr,
tbody tr td {
    max-height: 0;
    line-height: 0;
    overflow: hidden;
    -moz-transition: all 1s linear;
    -ms-transition: all 1s linear;
    -o-transition: all 1s linear;
    -webkit-transition: all 1s linear;
    transition: all 1s linear;
}

tbody tr td:first-child {
    padding-left: 2em;
}

tbody tr.header td {
    padding: 0;
}

tbody:hover tr {
    height: 2em;
    max-height: 2em;
    line-height: 2em;
    -moz-transition: all 1s linear;
    -ms-transition: all 1s linear;
    -o-transition: all 1s linear;
    -webkit-transition: all 1s linear;
    transition: all 1s linear;
}
​

JS Fiddle demo.

This makes the same assumptions as previously, that you want to control the visibility by hovering over the header to show the hidden content.

And, just for kicks, adding keyboard-navigation (with tab), using the tabindex attribute on the tr.header elements:

<table>
    <colgroup>
        <col class="foods" />
        <col class="calories" />
    </colgroup>
    <thead>
        <tr>
            <th>Food</th>
            <th>Calories</th>
        </tr>
    </thead>
    <tbody>
        <tr class="header" tabindex="1">
            <td colspan="2">Fruits</td>
        </tr>
        <!-- unchanged from the previously-posted table mark-up -->
    </tbody>
    <tbody>
        <tr class="header" tabindex="2">
            <td colspan="2">Vegetable</td>
        </tr>
        <!-- unchanged from the previously-posted table mark-up -->
    </tbody>
</table>

​And CSS:

/* Other CSS remains the same */
tr.header:focus ~ tr,
tbody:hover tr {
    height: 2em;
    max-height: 2em;
    line-height: 2em;
    -moz-transition: all 1s linear;
    -ms-transition: all 1s linear;
    -o-transition: all 1s linear;
    -webkit-transition: all 1s linear;
    transition: all 1s linear;
}

tr.header:focus {
    outline: none;
    font-style: italic;
    background-color: #ffa;
}
​

JS Fiddle demo.

Upvotes: 5

defau1t
defau1t

Reputation: 10619

I would do something like this:

CSS

  .foods{border:1px solid red;overflow: hidden;width:310px;}
        ul li{list-style: none;}
        ul li.dash:before{content:"-";}
            .fruit{float:left;width:150px;}
            .calories{float:left;width:150px;}

HTML

<div class="foods">
        <div class="fruit">
            <h3>Food</h3>

                <h3>Fruits</h3>
                <ul>
                    <li class="dash">Apple</li>
                    <li class="dash">Grape</li>
                    <li class="dash">Strawberry</li>
                </ul>
                <h3>Vegetable</h3>
                    <ul>
                    <li class="dash">Cucumber</li>
                    <li class="dash">Onion</li>

                </ul>


        </div>
        <div class="calories">
            <h3>Calories</h3>
            <div>
                <h3>&nbsp;</h3>
                <ul>
                    <li>90</li>
                    <li>15</li>
                    <li>16</li>
                </ul>
                <h3>&nbsp;</h3>
                <ul>
                    <li>12</li>
                    <li>29</li>

                </ul>
            </div>
        </div>
    </div>

DEMO

Upvotes: 1

Nick Green
Nick Green

Reputation: 428

I know what you are trying to achieve however you could implement jQuery to do this but it would be dependent on your usage. The answer from @BillyMoat would deal with showing the results in two columns, but if you want them to expand/collapse you could deploy jQuery Accordion: http://docs.jquery.com/UI/API/1.8/Accordion

Upvotes: 0

Billy Moat
Billy Moat

Reputation: 21050

This is really tabular data so a table would be okay to use.

However you could do this: http://jsfiddle.net/eFmtR/

ul {
 width:300px;
}
ul li {
 width:150px;
 float:left;
 text-align:center;
}

strong {
 font-weight:bold;
}


<ul>
 <li><strong>Food</strong></li>
 <li><strong>Calories</strong></li>
 <li>list item</li>
 <li>list item</li>
 <li>list item</li>
 <li>list item</li>
 <li>list item</li>
 <li>list item</li>
 <li>list item</li>
 <li>list item</li>
</ul>

Upvotes: 2

Related Questions