Reputation: 15698
I'm having a bit of trouble with a couple of <ul>
list objects on one of my pages.
I have two <ul>
list containers that are populated from the client browser. Unrelated to this discussion, these two containers will allow for users to drag-and-drop <li>
options left<->right from each container, and will be used for a form of manual sorting.
My problem is that either of these lists may contain 0 to upwards of 60 items. When there are many list items in one of the list containers, the parent grows well past the size screen and scroll bars appear, while the <ul>
container grows as large as it needs to be.
I'd prefer for the scroll bars to be on the <ul>
objects only (and function properly.)
I've googled this, and I've found multiple answers regarding forcing content to the size of a parent container, but most examples usually involve <div>
objects and I'm not sure if there is something different with the <ul>
container which causes it to behave differently.
Below is my pertinent code.
...
<ul class="col_selector_container" id="ulUnusedColumns"></ul>
<ul class="col_selector_container" id="ulUsedColumns"></ul>
...
This content is contained in a third-party Telerik control. The content area of the Telerik control is a div that is sized to fit the available content area, with or without content provided by the developer. However, the content area does grow larger if the internal content doesn't fit and, thus, the automatic scroll bars appear when the <ul>
containers are populated and over-sized.
ul.col_selector_container
{
overflow-y: scroll;
list-style-type: none;
height: 100%;
width: 300px;
display:inline-block;
vertical-align:top;
padding-left: 0px;
}
Note that the height: 100%
doesn't appear to do anything. The list will grow or shrink to match the height of the internal content, not the height of the parent container. Also, overflow-y: scroll;
doesn't do anything other than show the scroll bars, which is pointless if the UI is just going to resize the list.
How can I fix this?
I am using jquery & jqueryui for for sortign and working with UI elements. A good answer can involve using one of these tools if there is an option within these tools that can fix my problem, but that's certainly not required. Pertaining to this questino, JQuery never touches the layout of these object, other than inserting <li>
objects, derived from my data list at runtime.
For those wanting an example, the best I can give is an example of the problem.
Here is a JSFiddle. Notice that the <ul>
list is populated so that the content region of the fiddle has a scroll bar. Also note the pointless scroll bar on the list? How can I make it so that the content area doesn't need a scroll bar because the <ul>
sizes itself to the content window (with more or less list items) and you can scroll through the list content when the list region is to large.
Upvotes: 1
Views: 5963
Reputation: 787
This can be achieved easy with jQuery:
jQuery:
$(document).ready(function(){
var list = $('ul.col_selector_container');
list.css({'min-height':list.parent().height(), 'max-height':list.parent().height()});
$(window).resize(function(){
list.css({'min-height':list.parent().height(), 'max-height':list.parent().height()});
});
});
Or use "closest('selector')" to get the height of the parent higher in the DOM tree.
Update in 2017:
This can be achieved with FLEX now:
<style>
.parent{
background:red;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
height:300px;
}
ul{
background:yellow;
}
</style>
<div class="parent">
<ul>
<li>Test1</li>
<li>Test2</li>
</ul>
</div>
https://css-tricks.com/snippets/css/a-guide-to-flexbox/
Upvotes: 1
Reputation: 1306
EDIT: I forgot a semicolon. Hah. Height works just fine on ul
s, I just committed the classic blunder. I've cleaned that chunk from this answer.
Note however that imposing a size via the ul
rather than the wrapper causes some weirdness in some browsers. My work's Firefox 31 has the green box overlapping with the bottom of the list. At this point you'd have to use a positioning trick to keep it kosher, hence why wrapping is still honestly easiest.
Easiest is to wrap the ul
in a div
, and size the div
- just remember to forward the drop events to the ul
.
Two samples: https://jsfiddle.net/b6zu3Lhy/6/
First is a dynamically-added-to list forced to stay within its parent
Second is a ul
with a height limit.... but not the right height limit.
If you're running into the issue of percentile sizes not quite liking you (ie: the percents do nothing), you'll need the html,body{ height:100%; }
trick. If you can't do that, you might be able to bs it with screen units (vw
/vh
) mirroring the parent's size.
Demo code (from the fiddle) provided below for completeness.
function $(a, b) { return (b || document).getElementById(a); }
$.bind = function (ele, o) { for (var event in o) ele.addEventListener(event, o[event]); };
$.init = function (init, args, me) { if (document.readyState !== "loading") { init.apply(me, args); } else { document.addEventListener("DOMContentLoaded", function () { init.apply(me, args); }); } }
$.hasClass = function (ele, cls) { return ele.classList.contains(cls); }
$.init(function(){
$.bind($("libtn"),{
click:function(){
var ul = $("ul");
var li = document.createElement("li");
li.innerHTML = "yo" + "oooooooooo".substr(Math.floor(10*Math.random()));
ul.appendChild(li);
}
});
$.bind($("szbtn"),{
click:function(){
var div = $("box");
if($.hasClass(div,"sz1")){
div.className="box sz2";
}else if($.hasClass(div,"sz2")){
div.className="box sz3";
}else{
div.className="box sz1";
}
}
});
});
ul{
margin-top:0; margin-bottom:0;
}
.box{
border:2px solid gray;
overflow-y:auto;
}
.sz1{ height:50px; }
.sz2{ height:100px; }
.sz3{ height:200px; }
.demo2{
height:75px;
overflow:visible;
border:1px solid green;
}
.demo2 ul{
font-style:italic;
height:100%;
overflow-y:auto;
}
<button type="button" id="libtn"> +li </button>
<button type="button" id="szbtn"> szTog </button>
<div id="box" class="box sz1">
<ul id="ul">
</ul>
</div>
<div class="demo2">
<ul>
<li>static list with size limit</li>
<li>static list with size limit</li>
<li>static list with size limit</li>
<li>static list with size limit</li>
<li>static list with size limit</li>
<li>static list with size limit</li>
<li>static list with size limit</li>
<li>static list with size limit</li>
<li>static list with size limit</li>
<li>static list with size limit</li>
<li>11 static list with size limit</li>
</ul>
</div>
Upvotes: 1
Reputation: 2321
If I'm understanding your question correctly, you have a few options.
Assuming you have one list per container, you can do something like this:
HTML
<div class="list-container">
<ul class="col_selector_container" id="ulUnusedColumns"></ul>
</div>
<div class="list-container">
<ul class="col_selector_container" id="ulUsedColumns"></ul>
</div>
CSS
.list-container { position: relative; }
.col_selector_container {
position: absolute;
overflow-y: scroll;
list-style-type: none;
height: 100%;
width: 300px;
display:inline-block;
vertical-align:top;
padding-left: 0px;
}
All of the quirks with position absolute apply here, but it should give you the effect you're looking for. If you're supporting IE10+, Flexbox is definitely the option to use here instead. You can also use css tables here as an alternative to child absolute/parent relative if you want.
If this isn't going to work, we'll probably need more of your HTML structure to see how things are laid out.
Hope this helps!
Upvotes: 1