I have a menu structure
<ul class="menu">
<li>
menu item
<ul class="menu">
<li>menu item</li>
</ul>
</li>
</ul>
If I set the outer menu item display: grid by default the cells will be just the top 'li'. How can I flatten the structure making all the 'li' items grid cells?
You can declare intermediate elements as "not even there" with display: contents (see article on bitsofco.de) which visually flatten sublists because if child li and grandchild ul aren't grid items anymore, then text node and grand-grand-child li are now the grid items BUT it causes huge problems related to semantics and accessibility as it's implemented in browsers for now.
E.g. you shouldn't in the first place flatten visually something that is hierarchical in your HTML code.
CSS solution: codepen
.menu_outer {
display: grid;
max-width: 20rem;
border: 1px solid darkblue;
padding-left: 0;
}
.menu_outer > li,
.menu_outer .menu {
display: contents;
}
.menu > li {
background-color: lightblue;
}
/* styling */
li {
list-style-type: none;
}
<ul class="menu_outer">
<li>
menu item
<ul class="menu">
<li>menu item</li>
</ul>
</li>
</ul>
Support of display: contents is partial: Firefox (accessible in incoming versions), Chrome and Safari (buggy under the hood) but not Edge and lol#IE
How about this?
.menu li { display: grid; }
Related
How can I make the <li> item width fit the text length in Bootstrap 3? My menu item is shorter than the text which causes my class="active" to look ugly.
This is the navbar in which it occurs:
<div id="menu" class="col-md-1">
<ul class="nav nav-pills nav-stacked">
<li class="active">Startseite</li>
<li>Kontakt</li>
</ul>
</div>
make a .custom_li class and give
.custom_li{
display:inline-block;
}
EDIT
To force same size, i'll suggest using max-width and place it under some media-query
li{
display: inline-block;
max-width:50%; /* limit width */
word-break:break-all; /* wrap extended text*/
border:1px solid red /* demo */
}
demo here
some optional things
some optional things
When I tried display: inline-block; it removes the bullet.
Instead, I use float:left; to have them only as wide as text, while preserving the bullet. Optionally, add clear:both; to keep it as a vertical list with each item on a new line.
CSS
.my-list > li {
float: left;
clear: both; /* remove this if you want them flowing inline */
}
HTML
<ul class="my-list">
<li>First Item</li>
<li>Second Item</li>
<li>Third Item</li>
<li>Fourth Item</li>
</ul>
If the display: inline-block; or display: block; is messing up the alignment.
Then just use width: fit-content;
Prevent it becoming a block by adding display: inline-block; to the proper element.
Post more code and preferably CSS if you want details.
I got it to work with the following css:
ul {
margin: 0 auto;
width: fit-content;
}
li{
display:flex;
margin: 0.5rem auto;
}
Basically what I did was make the container width to fit content. Used the CSS hack to make sure it would center using the margin. In the li tag I wanted the contents to be centered so I set it that way
How can I make this work as in the image below:
<ul style="width:16em;list-style:none;padding-left:0">
<li><label>name:</label><span>whatever</span></li>
<li><label>categories:</label>
<ul class="flat"><li>item 1</li>
<li>item 2</li>
<li>item 3</li>
<li>item 4</li>
</ul>
</li>
</ul>
.flat {list-style:none}
.flat li {display:inline; padding-left:0}
label {float:left;width:7em;}
I mean, I want the second line of li items left aligned by the first line of li items. "item 1" is fine, the others should align by it. (revised upon comments)
Remove width:11em;, they just don't fit in.
This is a definition list, so use the proper <DL> element (definition list) instead of a <UL>. Then, you can accomplish everything you would like to in two short lines of CSS.
http://jsfiddle.net/smclark89/tkUjc/
<dl>
<dt>name:</dt>
<dd>
<ul>
<li>Whatever</li>
</ul>
</dd>
<dt>categories:</dt>
<dd>
<ul>
<li><span>item 1</span></li>
<li><span>item 2</span></li>
<li><span>item 3</span></li>
<li><span>item 4</span></li>
</ul>
</dd>
dt { float:left; }
dd li { list-style-type:none; }
Your markup seems totally fine, and I'm not quite sure why there seems to be issues achieving what you want. It's pretty straightforward stuff unless I am missing something:
http://jsfiddle.net/ryanwheale/UhQ9W/9/
My solution positions the label and whatever is next to it right next to each other. Since your outer element is 16em, we make the width equal 16 (note, you could also use percentages):
label:first-child {
float: left;
width: 7em; /* magic number: 9 + 7 = 16 (7 / 16 = 43.75%) */
}
label:first-child + * {
float: left;
width: 9em; /* magic number: 9 + 7 = 16 (9 / 16 = 56.25%) */
}
Then, for the "flat" items, we simply float them next to each other and give them a width of 50%:
.flat li {
float: left;
width: 50%;
}
Note: if you want to add padding to anything, I suggest adding box-sizing: border-box; to anything which is being floated.
Also, floats might give you issues when things start to expand and wrap... so there is another solution with inline-block which will solve this. Let me know how this works and I can provide a better solution if you have issues with things not lining up properly once real content is in there.
Add padding-left: 7em; to .flat: fiddle
Or add float: left; width: 9em; padding: 0; to .flat: fiddle
Remove the float, the display:inline (unless you want them to display next to eachother) and just use text-align and then use list-style-position:inside; to fix the bullets:
<ul style="width:13em; border:1px">
<li><label style="text-align:left; width:7em">test</label>
<ul style="text-align:right;list-style-position:inside;">
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
<li>item 4</li>
</ul>
</li>
</ul>
Also, you shouldn't use inline CSS (style attribute) that is bad practice.
Without display:inline jsFiddle
With display:inline jsFiddle
here is a way of doing it, in case you can restructure the html as well. See it on JSFiddle
<ul>
<li><label>name:</label>
<ul class="flat">
<li>whatever</li>
</ul></li>
<li><label>categories:</label>
<ul class="flat">
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
<li>item 4</li>
</ul>
</li>
</ul>
ul {
list-style: none;
padding: 0;
}
label {
display: inline-block;
width: 4.5em;
}
.flat {
display: inline-block;
vertical-align: top;
width: 6em;
margin-bottom: .5em;
}
.flat li {
display: inline-block;
}
Additional styles are need to make this work. Switching to floats and using percentages for the widths makes it possible to aligned the label and content on the right properly.
Here's the updated styles
.flat {
list-style:none;
float: left;
width: 64%;
padding: 0;
margin-left: -0.75em;
overflow: hidden;
}
.flat li {
float: left;
width: 38%;
padding-left: 0.75em;
}
label {
float:left;
width:35%;
}
http://jsfiddle.net/QhSC9/
If you are able to update the markup, I'd recommend you look into dl.
#smclark89: agree, I'd say a <dl> seems more appropriate here too. The cleanest I can come up with is this jsfiddle
Slight modifications to your CSS file:
notes:
-using a clear after every odd <li> sets the beginning of the next <li>to the far end of the next line.
-adding float:left; to .flat sets the first <li> inline with the label.
CSS
.flat {list-style:none;float:left;}
.flat li {display:inline; padding-left:0;}
label {float:left;width:7em;}
ul {padding:0px;}
li {float:left;}
ul .flat li:nth-child(odd) {clear:both;}
EXAMPLE
http://jsfiddle.net/UhQ9W/19/
I have set the list items floating and clearing the floated elements every third one in order to create the layout you have attached above.
Keep in mind that this demo is width agnostic. All the tricks lays in this line of code
.flat li:nth-of-type(3n) {
background:#ff0000;
clear:left;
}
http://jsfiddle.net/QhSC9/
Use overflow: hidden on the ul
http://jsfiddle.net/HerrSerker/UhQ9W/8/
.flat {
list-style:none;
overflow:hidden;
padding:0
}
The overflow: hidden changes the block formatting context of the .flat element as described here
Check this out. I know that this isn't the proper way to do it but based on the other answers you cannot change major elements/tags also styles.
Fiddle
CSS
label {
clear:left;
float:left;
width:7em;
height:22px;
}
I just added height:22px and clear:left to create your desired output.
I'm trying to use jQuery UI to create a dropdown menu on a site that I'm working on. It looks okay at first glance, but the starting position of the nested ul elements seem to be blocking the next link in the menu. The blue box is what appears when I hover over the nested ul in Firebug and prevents hovering over "Link 2" How can I move this align this with the actual menu? Thank you!
The sub-links in grey work fine.
<div id="nav">
<ul>
<li>Link 1
<ul>
...
</ul>
</li>
<li>Link 2</li>
<li>Link 3</li>
</ul>
</div>
#nav ul {
list-style-type: none;
float:right;
}
#nav ul li ul {
position:absolute;
width: 200px;
}
#nav ul li ul li {
display: block;
position:relative;
top:40px;
left:-165px;
}
Turns out jQuery UI was generating some inline styles in an attempt to correctly position the dropdown menu.
<ul ... style="display: none; top: 84px; left: 913px;" aria-hidden="true">
I found this question with a similar issue. I added the following style to my stylesheet and it works now:
.ui-menu { top: auto !important; left:auto !important; }
I have a navigation menu and I wanted to have a dropdown menu for subpages. I created it and everything is ok except that the pages links in the top menu slide over to the right when the dropdown shows when I hover the page link with subpages.
What is it that I am missing here?
Thanks for the help in advance.
Here is the jsfiddle:
jsfiddle.net/AC8XK/
What I have is not 100% like that, since there is a lot missing, but it shows exactly the problem I mentioned.
I managed to get the menu working properly. The solution to the initial problem was, as mike said, changing the dropdown ul position from relative to absolute.
As for the positioning of the dropdown, I solved the problem by using padding-top instead of top or margin-top.
Thanks to everyone that tried to help.
The code you supplied in jsfiddle was..well...a bit of a mess. I had to strip a lot of it down and generate some base formatting for the dropdown. I will comment the important bits, but it should be more or less copy & paste. The code is solely the layout text for the menu - no visual or positional styling stuff.
Key Concepts: 1 - Set your LIs to width:auto and the li>ul to position: absolute;width:100%. This allows positioning and makes sure the individual ul ul lis are on separate lines.
2- You had the display:none and display:block correct. Alternatively, you can use off-the-screen positioning for the same purpose.
3- Remember to do ul ul {position:absolute;} to allow positioning of the submenus relative to the parent li!
HTML:
<div class="greenbar">
<nav>
<ul id="menu-navigation-menu" class="navigation">
<li id="menu-item-107" class="menu-item">About
<ul class="sub-menu">
<li id="menu-item-116" class="menu-item">Terms of Use</li>
<li id="menu-item-119" class="menu-item">Just another link</li>
</ul>
</li>
<li id="menu-item-106" class="menu-item">Services
<ul class="sub-menu">
<li id="menu-item-120" class="menu-item">Another link again</li>
</ul>
</li>
<li id="menu-item-105" class="menu-item">Clients</li>
<li id="menu-item-104" class="menu-item">Resources</li>
</ul>
</nav>
</div>
CSS:
nav ul {
list-style-type: none;
position: relative;
display: inline-table;
}
nav ul li {float: left;}
nav ul li a { display: block; text-decoration: none;}
nav ul ul {
display: none;
position: absolute;
width: auto;
}
nav ul li:hover > ul { display: block;}
nav ul ul li { width: 100%;}
I am learning to create CSS menus WITHOUT floats. I got a partially "working" menu so far. However, the main menu's borders are separated. Also the submenu's borders are sized in half and the hover's background color is not working. At the same time, the sub-sub menu is not working
I am also trying to simplify the CSS code with a .menu .submenu .sub-submenu classes.
jsFiddle:
http://jsfiddle.net/vn64H/1/
HTML
<!DOCTYPE html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Title: Navigation menu</title>
<link rel="stylesheet" type="text/css" href="menu.css">
</head>
<body>
<!-- START: menu -->
<ul id="nav">
<li class="menu">Home</li>
<li class="menu">Main Menu 2
<ul class="submenu">
<li>Sub Menu 2.1</li>
<li>Sub Menu 2.2</li>
<li>Sub Menu 2.3
<ul>
<li>Sub-Sub Menu 2.3.1</li>
<li>Sub Menu 2.3.2</li>
<li>Sub Menu 2.3.</li>
</ul>
</li>
<li>Sub Menu 2.4</li>
<li>Sub Menu 2.5</li>
<li>Sub Menu, Some Sample Text 2.6</li>
<li>Sub Menu, Sample Text 2.7</li>
</ul>
</li>
<li class="menu">Main Menu 3
<ul class="submenu">
<li>Sub Menu 3.1</li>
<li>Sub Menu 3.2</li>
<li>Sub Menu 3.3</li>
<li>Sub Menu 3.5</li>
<li>Sub Menu 3.6</li>
<li>Sub Menu 3.7</li>
</ul>
</li>
<li class="menu">Main Menu 4
<ul class="submenu">
<li>Sub Menu 4.1</li>
<li>Sub Menu 4.2</li>
<li>Sub Menu Sample Text 4.3</li>
<li>Sub Menu 4.4</li>
<li>Sub Menu 4.5</li>
<li>Sub Menu 4.6</li>
<li>Sub Menu 4.7</li>
<li>Sub Menu 4.8</li>
</ul>
</li>
<li class="menu">Menu 5</li>
<li class="menu">Menu 6</li>
<li class="menu">Contact</li>
</ul> <!-- /#menu -->
<!-- END: menu -->
</body>
</html>
CSS
#charset "utf-8";
#nav {
background-color: #000;
position: relative;
font-family: Arial, Helvetica, sans-serif;
font-size: 0.975em;
text-align: left;
display: block;
border: 1px dotted #cccccc;
padding: 0;
margin: 0;
}
#nav a {
color: #fff;
text-decoration: none;
}
#nav li {
color: #fff;
text-align: left;
width: 110px;
border: 1px solid #CCCCCC;
list-style-type: none;
padding: 0;
margin: 0;
display: inline-block;
}
/*Sub menu */
#nav li ul {
color: navy;
text-align: left;
list-style-type: none;
width: 200px;
border: 1px solid #000;
padding: 0;
margin: 0;
display: none;
position: absolute;
background-color: #990000;
}
#nav li ul a {
display: inline-block;
}
#nav li:hover ul {
visibility: visible;
display: block;
background-color: #E6B800;
}
#nav li:hover ul li {
background-color: #E6B800;
}
/*Sub-sub menu */
#nav li ul li ul li a {
display: none;
}
#nav li ul li ul li:hover {
visibility: visible;
display: block;
background-color: #E6B800;
}
#nav li ul li ul li:hover ul li {
background-color: #E6B800;
}
The main-menu borders are separated because the <li>s are inline-blocks with white-space in between them. Inline-blocks work like words in a text stream, so any white space, such as the line breaks you have in there, will be interpreted as text-space characters. The only way around that while keeping them inline-blocks is to put all the <li>'s on one line with zero white-space in between. Why do you want to avoid floats? That would be your best option.
The sub-menu items are half-spaced because the container has width of 200px, but each item is an inline-block with no width specified. Make them display:block isntead and they will expand out to the edges of the container.
Do apply your sub- and sub-sub-menu classes, that will be easier to see and work with than so many nested selectors.
Also: use teh the child selector syntax, e.g.: ul#nav > li it will apply the relevant styles only to the child items, and not to the grand-children, etc.
UPDATE
In asnwer to mcknz' question, I would place float:left on #nav li instead of display:inline-block. This solves 2 problems:
The unintended spacing between the menu items will disappear, regardless of white-space in the HTML. You can now control their spacing precisely with margins.
IE7 will not apply inline-block to list-items -- or any elements that are not natively inline (see: http://fourwhitefeet.com/2009/02/css-display-inline-block-in-ie7/)
Important note: You will need to specify the height of the #nav explicitly now, because non-floating parents of floating elements collapse (see: Why do non-floating parents of floating elements collapse?).
...also: you can safely remove subsequent text-align: left; declarations once you've applied it to #nav, this property inherits down to all nested elements, unless, of course, you have an intervening layer with text aligned left or center. Properties that inherit are listed here: http://www.communitymx.com/content/article.cfm?cid=2795d
The newline after each list item in your menu acts as a space. You can change to make all of them on one line, or you can use comments if you still want them visually separated in markup:
<li class="menu">Home</li><!--
--><li class="menu">Main Menu 2