Deleet Deleet - 2 months ago 8
CSS Question

Collapseble list with columns?

I need to have a hierarchical, collapsible list that has 3 columns. I have the first two parts working, but I can't seem to get the CSS quite right for the third. The picture shows the current code:

enter image description here
(The slightly duplicated text to the left of col3 is a visual error with the fiddle.)

The goal is to have a three col pseudo-table within a collapsible list such that col1 has the standard list indenting, and col2 is centered for all levels and col3 is at the right for all levels. It should look like this:

enter image description here

I tried to accomplish this by having them both float right and then adding a margin/padding to either col2 or col3 so as to move col2 towards the middle where I want it to be. However, somehow col2 ends up on the outside of col3. Seems impossible to me, but with CSS no bug is impossible.

I have tried various other combinations of

margin
s and
padding
s and
float: left
s without luck.

Here's an almost working fiddle.

HTML:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

<body>
<div id="listContainer">
<div class="listControl">
<a id="expandList"><button>Expand All</button></a>
<a id="collapseList"><button>Collapse All</button></a>
</div>
<ul id="expList">
<li>
<div class="col1">Non-parent</div>
<div class="col2">Col2</div>
<div class="col3">Col3</div>
</li>
<li>
<div class="col1">Parent</div>
<div class="col2">Col2</div>
<div class="col3">Col3</div>
<ul>
<li>
<div class="col1">Child</div>
<div class="col2">Col2</div>
<div class="col3">Col3</div>
</li>
</ul>
</li>
<li>
<div class="col1">Grandparent</div>
<div class="col2">Col2</div>
<div class="col3">Col3</div>
<ul>
<li>
<div class="col1">Parent</div>
<div class="col2">Col2</div>
<div class="col3">Col3</div>
<ul>
<li>
<div class="col1">Child</div>
<div class="col2">Col2</div>
<div class="col3">Col3</div>
</li>
</ul>
</li>
<li>
<div class="col1">Parent</div>
<div class="col2">Col2</div>
<div class="col3">Col3</div>
<ul>
<li>
<div class="col1">Child</div>
<div class="col2">Col2</div>
<div class="col3">Col3</div>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>

</body>


CSS:

/********************/


/* EXPANDABLE LIST */


/********************/

#listContainer {
margin-top: 15px;
}

#expList ul,
#expList li {
list-style: none;
margin: 0;
padding: 0;
cursor: pointer;
}

#expList p {
margin: 0;
display: block;
}

#expList p:hover {
background-color: #121212;
}

#expList li {
line-height: 140%;
text-indent: 0px;
background-position: 1px 8px;
padding-left: 20px;
background-repeat: no-repeat;
}


/*This works in Firefox following W3C standards, but not in other browsers!*/


/*https://drafts.csswg.org/css-lists/#marker-content*/


/* Collapsed state for list element */

#expList .collapsed {
/* list-style-type: "+";*/
list-style: none;
/*padding: 0px;*/
}


/* Expanded state for list element
/* NOTE: This class must be located UNDER the collapsed one */

#expList .expanded {
/*list-style-type: "-";*/
list-style: none;
/*padding: 0px;*/
}


/*code that works for non-Firefox*/

#expList .collapsed:before {
content: "+";
width: 1em !important;
margin-left: -1.2em;
display: inline-block;
}

#expList .expanded:before {
content: "-";
width: 1em !important;
margin-left: -1.2em;
display: inline-block;
}

#expList {
clear: both;
}

.col1 {
display: inline;
/*padding-right: 100px;*/
}

.col2 {
display: inline;
float: right;
}

.col3 {
display: inline;
float: right;
}


JS:

/**************************************************************/
/* Prepares the cv to be dynamically expandable/collapsible */
/**************************************************************/
function prepareList() {
$('#expList').find('li:has(ul)')
.click(function(event) {
if (this == event.target) {
$(this).toggleClass('expanded');
$(this).children('ul').toggle('medium');
}
return false;
})
.addClass('collapsed')
.children('ul').hide();

//Hack to add links inside the cv
$('#expList a').unbind('click').click(function() {
window.location($(this).attr('href'));
return false;
});

//Create the button funtionality
$('#expandList')
.unbind('click')
.click(function() {
$('.collapsed').addClass('expanded');
$('.collapsed').children('ul').show('medium');
})
$('#collapseList')
.unbind('click')
.click(function() {
$('.collapsed').removeClass('expanded');
$('.collapsed').children('ul').hide('medium');
})

};

/**************************************************************/
/* Functions to execute on loading the document */
/**************************************************************/
$(document).ready(function() {
prepareList()
});

Answer

The solution to this was to realize that float: right apparently also makes the blocks align right, so that they appear in reverse order. With this in mind, one can just switch the order of the blocks to get the normal order back.

E.g.:

<div class="col1">Non-parent</div>
<div class="col4">Col4</div>
<div class="col3">Col3</div>
<div class="col2">Col2</div>

Working fiddle.