Assume the following HTML5 document:
<!doctype html>
<html>
<head><title>try</title>
</head>
<body>
<h1>testing</h1>
<ul id='ul_id'>
<li id='li1_id'>one</li>
<li id='li2_id'>somelongertwo</li>
</ul>
</body></html>
what would be the CSS3 stylesheet so that the width of <ul id='ul_id'> element would be the smallest to fit, so would be here the width of <li id='li2_id'> plus its bullet, since the second list item is the widest item of the <ul id='ul_id'> element?
I don't want the width of my <ul id='ul_id'> to be as wide as the containing <body>
The context and motivation of this question is my optimizing (nearly minimizing) width of jqueryui menu question.
What would be the CSS3 stylesheet so that the width of <ul id='ul_id'> element would be the smallest to fit
You could change the display of the ul element to inline-block.
In doing so, it will have a "shrink-to-fit" width based on the size of the children elements.
Based on section 10.3.9 of the relevant spec for inline-block elements in normal flow:
If width is auto, the used value is the shrink-to-fit width as for floating elements.
#ul_id {
display: inline-block;
background-color: #f00;
}
<ul id='ul_id'>
<li id='li1_id'>one</li>
<li id='li2_id'>somelongertwo</li>
</ul>
Alternatively, setting the display to table would result in similar behavior.
#ul_id {
display: inline-block;
}
or
#ul_id {
float: left;
}
#ul_id:after {
clear: both;
}
One of these two should work as expected.
Width resize to fit container is caused by display: block behaviour which is default for ul element.
Related
I have a main menu #navi. It's items have different width. The submenus should have the same width, as their parents. I made a JsBin to demonstrate it: http://jsbin.com/yusunohage/1
A very very very long submenu should not wider then its parent A longer menu.
Here is the HTML:
<ul id="navi">
<li class="menu1">Menu </li>
<li class="menu2">A longer menu
<ul class="children">
<li>A very very very long submenu</li>
<li>Submenu</li>
</ul>
</li>
<li class="menu3">Menu item</li>
</ul>
And the css
ol, ul {
list-style: none;
padding: 0;
}
#navi > li {
padding: 0 10px;
}
li {
float: left;
}
ul.children{
background: gold;
}
#navi li ul li {
float:none;
}
PROBLEM:
Having the parent element limit the children element without fixing the css width parameter.
SOLUTION
Setting the child width to 0px for the purpose of measurement the native parent width.
Setting the child width with parent width after measurement.
jQuery:
$('.children li').css('width', 0);
$('.children li').css('width', $('.menu2').width());
Solution here : http://jsfiddle.net/urahara/4m5vkkk2/2/
First set the height for parent elements. Then care about the width of child elements.
Just put this in your css code
.menu2{
max-width:140px;
}
Here is the Jsfiddle http://jsfiddle.net/nwL1hku4/
Edited
As you stated above that you don't know about the width of parent element. You may give max-width to child elements, to restrict their width.
Like this http://jsfiddle.net/nwL1hku4/1/
I'm trying to work with grids which are whole numbers, that perfectly match up, e.g 20% for 5 menu items would fill 100%.
I have the following code:
#menu-primary-navigation li{display:inline-block;font-size:0;width:20%;}
#menu-primary-navigation li a{font-size:22px;}
I understand the issue of whitespace between ul li elements that means 20% elements will not fit into 100% due to the white space in between each element. However I thought I had got around this issue by making font-size:0; where the elements sit and then only setting the font size inside the element.
Yet you can see in my JSFiddle that the five menu items still do not fit perfectly to 100% of the container.
In my example, the width is 600px and each element is 20%. I can see from inspecting the elements that they are all equal to 120px. Well 120 x 5 = 600, so why does the last element always fall to the next line?
<div class="wrapper">
<ul id="menu-primary-navigation" class="menu">
<li class="menu-item">
Home
</li>
<li class="menu-item">
Tutorials
</li>
<li class="menu-item">
<a>Logo</a>
</li>
<li class="menu-item">
Projects
</li>
<li class="menu-item">
Articles
</li>
</ul>
</div>
http://jsfiddle.net/franhaselden/kq9o4t0v/
Using display: inline-block; is notoriously problematic in this situation. You could consider using display: table-cell; achieve the same result with less hassle.
HTML can remain the same, but try this CSS:
.wrapper{width:600px;}
ul,li{padding:0;margin:0;}
/* needed for use with display: table-cell; */
.menu{ display: table; width: 100%; }
/* changed to table-cell */
#menu-primary-navigation li{display:table-cell; text-align: center;}
#menu-primary-navigation li a{font-size:22px;}
However as I am supposed to be answering the question the part you went wrong is you need to set the font size on the parent i.e the ul in order to effect the white-space. Do note however, I think certain versions of IE will not like font-size: 0;
CSS:
.wrapper{width:600px;}
/* you need it set on the parent */
ul,li{padding:0;margin:0; font-size: 0; }
#menu-primary-navigation li{display: inline-block; width: 20%; text-align: center;}
#menu-primary-navigation li a{font-size:22px;}
You are setting font-size:0 on the li tag to remove whitespace. However the li's are contained in the ul, so you need to set the font-size there.
In your jsfiddle the issue is resolved by setting
.wrapper{width:600px;}
ul,li{padding:0;margin:0;font-size:0}
I've been trying to create a navigation bar that meets the following criteria:
Spans 15% height.
Spans 100% width.
Navigation bar is aligned to the top of the site.
Elements within the navigation bar are vertically centered within it.
The last menu option is aligned to the far right of the navigation bar.
I've been playing with <div> and <ul> to implement the elements. I've spent a lot of time on it and researched it. I can't seem to find a way to vertically center the elements, which are images, if I use a percentage height. I assume this issue is because the <header> and <nav> elements are block elements, as is the div element, being that "vertical-align" only works on inline elements.
Questions, for those wise enough to provide what are probably easy answers:
Can I use "vertical-align" on block elements if I override the "display" element to the "inline" value? It seems like the answer is negative.
Can I right-align one <li> within a <ul> while the other <li> are left-aligned?
The only way I can get it to work is to use fixed height values on the navigation bar as well as padding around the elements. Is that my only option or does anyone know of a way I can make it work with a percentage height?
Basic code to express what I'd like to do (assuming all the <html> and other foundational tags are there, too; and I am aware the code below doesn't work but it shows the basic idea):
<style>
html, body {
height: 100%;
width: 100%;
}
.menu_bar {
display: inline; /* This element seems to mess things up pretty bad so I assume I can't do it
that way. I was only using it so my <ul> would be within an inline element which would allow me
to use vertical-align. */
height: 15%;
width: 100%;
background-color: #000000;
}
.menu_items {
height: 100%;
width: 100%;
}
.menu_logo {
vertical-align: middle;
text-align: left;
}
.menu_option1 {
vertical-align: middle;
text-align: left;
}
.menu_option2 {
vertical-align: middle;
text-align: left;
}
.menu_option3 {
vertical-align: middle;
text-align: right;
}
</style>
<body>
<header>
<nav>
<div class="menu_bar">
<ul class="menu_items">
<li class="menu_logo"><img src="images/logo.gif"></li>
<li class="menu_option1"><img src="images/option1.gif"></li>
<li class="menu_option2"><img src="images/option2.gif"></li>
<li class="menu_option3"><img src="images/option3.gif"></li>
</ul>
</div>
</nav>
</header>
</body>
<nav>
<ul id="navUl">
<li>
<div class="settingsDiv">
hey
</div>
</li>
</ul>
</nav>
What I want to do is set the div's height to 100% so that it'll be whatever height the nav is.
I can't say what you've done wrong - because you didn't supply your CSS code.
But here is a working copy of what you're asking: http://jsfiddle.net/WDAXp/2/
You need to set <nav>'s height, then set #navUl, #navUl li, and settingsDiv height to 100%.
edit
oops, didn't read the question properly. fixed it.
You have to give the nav some fixed height, and the others inherit from the parent.
nav {
height: 100px;
}
ul, li, .settingsDiv {
height: inherit;
}
jsFiddle
I have the following html:
<div id="container">
<ul>
<li>element 1</li>
<li>element 2</li>
</ul>
</div>
applied with a css as follows:
#container { width:100%; overflow:auto; }
#container ul { width: 100%; }
#container li { width: 100%; }
So now I would like to have an indeterminate number of elements (<li>) all with 100% width (so they can adjust accordingly to the browser's window size) but all side by side, displaying the horizontal scroll bar in the container.
I have tried putting "display:inline" on ul's css, and "float:left" on li's css, but with no success.
Any suggestions?
Also, try to consider I'm trying to make this as "cross-browser compatible" as possible.
Thanks in advance.
Like the others I'm struggling to understand what you're looking for exactly but does this do what you want?
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<title>Horizontal 100% LIs</title>
<style type="text/css">
#container { width:100%; overflow:auto;}
#container ul { padding:0; margin:0; white-space:nowrap; }
#container li { width: 100%; list-style-type:none; display:inline-block; }
* html #container li { display:inline; } /* IE6 hack */
* html #container { padding-bottom:17px;} /* IE6 hack */
*:first-child+html #container li { display:inline; } /* IE7 hack */
*:first-child+html #container { padding-bottom:17px; overflow-y:hidden; } /* IE7 hack */
</style>
</head>
<body>
<div id="container">
<ul>
<li style="background-color:red">element 1</li><li style="background-color:green">element 2</li><li style="background-color:blue">element 3</li>
</ul>
</div>
</body>
</html>
Getting the LIs on to one line has two parts. The white-space:nowrap on the ul stops any automatic wrapping and the display:inline-block on the LIs allows them to run one after another, but have widths, paddings and margins set on them. For standards compliant browsers that's sufficient.
However IE6 and IE7 need special treatment. They don't support the display:inline-block properly, but fortunately display:inline on elements with hasLayout set gives a behaviour very like display:inline-block. The width:100% has already forced hasLayout to be set on the LIs so all we have to do is to direct the display:inline to IE6 and IE7 only. There are a number of ways of doing this (conditional comments are popular on StackOverflow) but here I've chosen the * html and *:first-child+html hacks to do the job.
Additionally, IE6 and IE7 have another bug where the scroll bar overlays the content, so the container is given a padding-bottom to make space for the scroll bar. The scroll bar is a platform control, so its height cannot be known exactly, but 17 pixels seems to work for most cases.
Finally, IE7 also wants to put in a vertical scroll bar, so the overflow-y:hidden directed at IE7 stops this from happening.
(The padding:0, margin:0, list-style:none, and the styles on the individual LIs are just there to show more clearly what's happening.)
You want it to act like a good old fashioned table:
<ul class="menu">
<li>one</li>
<li>two</li>
<li>three</li>
</ul>
.menu {
display: table;
width: 100%;
}
.menu li {
display: table-cell;
padding: 2px;
background: #900990;
border: 1px solid yellow;
color: white;
}
then you can also collapse it nicely when the page is small:
/* responsive smaller screen turn into a vertical stacked menu */
#media (max-width: 480px) {
.menu, .menu li {
display: normal;
}
}
What you're trying to do resembles what table cells do and is impossible otherwise, without using JavaScript (I don't suggest using tables or JavaScript for this, however). Your best bet is to set a certain amount of horizontal padding on the <li> tags and float them so that they are auto-width based on their content's width instead of the window's width:
<div id="container">
<ul>
<li>element 1</li>
<li>element 2</li>
</ul>
</div>
<style type="text/css">
#container, #container ul {
width: 100%;
float: left;
}
#container ul li {
margin: 0 10px 0 0;
padding: 5px 10px;
float: left;
}
</style>
The other method is to use display: inline-block; to achieve what you want, but it's kind of a hack (not cross-browser compatible).
using jquery to space your li's after your page has
var ul = $('#yourListId');
var numChildren = ul.children().length;
if(numChildren <= 0){
return;
}
ul.css({'list-style':'none','margin':0,'padding':0});
var parentWidth = ul.width();
var childWidth = parentWidth/numChildren;
ul.children().each(function(index, value){
$(this).css({'width':childWidth,'margin':0,'float':'left','display':'inline-block'});
});
ul.after('<div style="clear:both">');
With the exception of the "childWidth" css... you can, of course, replace the other css with something from a style sheet.
Generally to show li's horizontally you would float them all left. The part that confuses me is the 100% width. How can each li have 100% width when they can only be as wide as their container? It seems like the li's need to be fixed width or autosized with no width at all.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Untitled Document</title>
<style type="text/css">
#container { width:100%; overflow:auto; }
#container ul { width: 100%; }
#container li { float:left; }
</style>
</head>
<body>
<div id="container">
<ul>
<li>element 1</li>
<li>element 2</li>
</ul>
</div>
</body>
</html>
I think that what you want to do is not possible in cross-browser css and html; if you set the width of the li to 100%, you set it to the width of its parent element and what you really need is for the parent element (the ul) to have the width of all li's combined. And you cannot set the width to x-times the screen width using just css.
And even if you could, it would also grow the li's as the are told to be 100% of its parent element. Sort of a chicken and egg problem for the browser.
In javascript is's easy though, just calculate the number of li's, set their width to the screen width and set the ul width to (the number of li's) x (screen width).
Try this
<div id="container">
<ul>
<li>element 1</li>
<li>element 2</li>
</ul>
</div>
#container { width:100%; }
#container ul { text-align:center; }
#container li { display:inline; text-align:center;padding-left:20px; padding-right:20px; }