I have a menu with sub menus. I used nested uls to achive this. Now I'm facing this situation: I want all the items and subitems to be displayed horizontally at their respective level. The problem is that when an parent list has a children list, it's width grows so the next item at the same level goes far to the right.
To have things more clear here's a fiddle of what I'm taking about: http://jsfiddle.net/matias/n8gFT/
As you can see I would like to have the items B and C placed where the green dashed spaces are.
Is it possible to do this?
I would like to keep using nested uls and display: inline-block for itemes instead of float: left
SAMPLE HTML:
<ul>
<li>ITEM A
<ul>
<li>sub item A1</li>
<li>sub item A2</li>
</ul>
</li>
<li>ITEM B</li>
<li>ITEM C</li>
</ul>
SAMPLE CSS:
ul{border: 1px solid red; padding: 10px;}
li{display: inline-block; border: 1px solid blue; margin: 5px; padding: 10px; vertical-align: top;}
span{border: 1px dashed lime; margin: 0 10px; padding: 5px;}
EDIT 1: I forgot to tell you this: A, B and C have children. If I click on B, it's children are shown and A's and C's are hidden...and so on....
We will start off with a little CSS
#menu > li.sub ul {
list-style: none;
position: absolute;
top: -1000em;
left: 0px;
}
#menu li.sub ul li a {
display: inline;
}
#menu > li.sub:hover ul {
top: 3em;
}
#menu{
text-align:left;
}
li{
display:inline-block;
}
Finish with some HTML
<ul id="menu" >
<li class="sub">
ITEM A
<ul>
<li>sub A1</li>
<li>sub A2</li>
</ul>
</li>
<li class="sub">
ITEM B
<ul>
<li>sub B1</li>
<li>sub B2</li>
</ul>
</li>
<li class="sub">
ITEM C
<ul>
<li>sub C1</li>
<li>sub C2</li>
</ul>
</li>
</ul>
and a JSFIDDLE http://jsfiddle.net/ShADm/28/
You could style the lists that are being pushed over of margin-left: -20px; here is a working fiddle
http://jsfiddle.net/n8gFT/1/
Of course the amount it is pushed over can be edited by changing the margin-left
I achieved what I was looking for using display: table-cell to the li's and reducing ul's width.
See demo
Add a class to the sub lists and style them like this:
.sub { position: absolute; margin-left: -27px; }
Related
Why is the dropdown ul in 'Menu Item 2' not being aligned absolutely to the top of its parent li element?
With the dropdown ul CSS set as:
position:absolute;
top:0;
left:0;
I would expect it to be covering from the top left of the parent element, i.e. covering it completely.
Some confusing symptoms:
I want the parent menu to be clickable AND have a dropdown in some cases. So where there is a dropdown, the parent menu <li> has an <a> that is padded to increase the clickable area. This also increases the containing <li>, since the li:hover shows the same padded area. This works as desired.
However, when the dropdown is shown and aligned to <li>, <li> seems to be in the position before it was expanded by <a>. When I check in a browser (Chrome and Firefox) the <li> element is not actually filling the same space as the <a> and so the dropdown appears some amount below the where I want it.
I understand that I can use top:SOME_NEGATIVE_OFFSET in the absolutely positioned dropdown but this feels hacky and I'd like to understand what's going on?
It's my first post, please go easy on me :)
<!DOCTYPE html>
<html>
<head>
<title>DropDownTest</title>
<style>
ul{
list-style:none;
margin:0;
padding:0;
}
li{
display:block;
position:relative;
}
li>a{
padding:1rem;
background-color:grey;
}
li>a:hover{
background-color:lightgray;
}
.mainbar>li{
float:left;
}
li.hasDrop:hover>ul{
display:block;
}
.dropContent{
display:none;
position:absolute;
top:0; /*not working as expected*/
left:0;
margin:0;/*thought this might have helped but no*/
padding:0;
z-index:1;
list-style:none;
min-width:100%;
}
.dropContent>li>a{
display:block;
}
</style>
</head>
<body>
<div>
<ul class="mainbar">
<li>Menu Item 1</li>
<li class="hasDrop">
Menu Item 2
<ul class="dropContent">
<li>Sub 1</li>
<li>Sub 2</li>
<li>Sub 3</li>
</ul>
</li>
<li>Menu Item 3</li>
</ul>
</div>
</body>
</html>
It happens beacuse your a element is getting padding as inline element.
Modify this rule:
li>a {
padding: 1rem;
background-color: grey;
display: block; /* this*/
}
ul {
list-style: none;
margin: 0;
padding: 0;
}
li {
display: block;
position: relative;
}
li>a {
padding: 1rem;
background-color: grey;
display: block; /* this*/
}
li>a:hover {
background-color: lightgray;
}
.mainbar>li {
float: left;
}
li.hasDrop:hover>ul {
display: block;
}
.dropContent {
display: none;
position: absolute;
top: 0;
/*not working as expected*/
left: 0;
margin: 0;
/*thought this might have helped but no*/
padding: 0;
z-index: 1;
list-style: none;
min-width: 100%;
}
.dropContent>li>a {
display: block;
}
<div>
<ul class="mainbar">
<li>Menu Item 1</li>
<li class="hasDrop">
Menu Item 2
<ul class="dropContent">
<li>Sub 1</li>
<li>Sub 2</li>
<li>Sub 3</li>
</ul>
</li>
<li>Menu Item 3</li>
</ul>
</div>
I have a fiddle here http://jsfiddle.net/13v2fcjf/
It has a basic html document with lists and sublists
<ul>
<li>Item 1
<ul>
<li>Sub Item 1</li>
<li>Sub Item 2</li>
<li>Sub Item 3</li>
</ul>
</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4
<ul>
<li>Child 1</li>
<li>Child 2</li>
<li>Child 3</li>
</ul>
</li>
</ul>
And I'm using the following css -
li:hover {
background: #f7f7f7;
}
When I hover on an li item with a subitem(s), all the subitems also get highlighted. This is not desirable. I want only the list item on which the user's hovering to be highlighted. How can I achieve this ?
Also, I tried using the :not selector but it doesn't work.
I think you just need to set the background on the nested <ul> tag. Something like this:
li:hover > ul {
background: #fff;
}
Edit: this is assuming you only want the parent <li> highlighted, which as #j08691 points out in the comments, might not be entirely what you're after. If you want each <li> to be highlighted, you might have to modify your HTML slightly to make this easier:
<ul>
<li><a>Item 1</a>
<ul>
<li><a>Sub Item 1</a></li>
<li><a>Sub Item 2</a></li>
<li><a>Sub Item 3</a></li>
</ul>
</li>
<li><a>Item 2</a></li>
<li><a>Item 3</a></li>
<li><a>Item 4</a>
<ul>
<li><a>Child 1</a></li>
<li><a>Child 2</a></li>
<li><a>Child 3</a></li>
</ul>
</li>
</ul>
By wrapping the items and sub-items in another tag - here I've just used an <a> tag for the sake of argument - you can target that tag to be highlighted on :hover without the nested tags being affected in the same way as in your original code:
a {
display: inline-block;
padding: 4px;
}
a:hover {
background: #f7f7f7;
cursor: pointer;
}
See http://jsfiddle.net/13v2fcjf/3/
If Ian's option doesn't work for you, a second opotion is to wrap the <li> contents in a span and apply the hover to that, like this example fiddle:
HTML:
<ul>
<li><span>Item 1</span>
<ul>
<li><span>Sub Item 1</span></li>
<li><span>Sub Item 2</span></li>
<li><span>Sub Item 3</span></li>
</ul>
</li>
....
CSS
li span:hover {
background: #f7f7f7;
cursor: pointer;
}
HTH,
-Ted
This effect is just natural because the sub items are inside of the main items.
There are two options that come to my mind:
1.) Resetting the background color of the sub lists with
li:hover > ul {
background-color: white;
}
2.) Using the li items as a container:
<li><span class="highlighted">Item</span></li>
.highlighted:hover {
background-color: red;
}
This was a challenge, but the following CSS works with your existing markup. It highlights only a hovered li, without highlighting its parent.
The main trick is to have the CSS create new content when hovering over a nested li. You can do this using the :before pseudo element:
li li:hover:before {
content: '';
position: absolute;
top: 0; bottom: 0; right: 0; left: 0;
z-index: -1;
background: white;
}
(If you're targeting CSS3 browsers only, you can use ::before instead of :before.)
This causes a nested li to cover up its parent li. The negative z-index prevents the background from covering up any text.
Parent li's need relative positioning with a z-index, and nested li's need static positioning for this to work:
li {
position: relative;
z-index: 0;
}
li li {
position: static;
}
The other trick has been mentioned in other posts:
li:hover ul {
background: white;
}
Full CSS:
li {
line-height: 1.65em;
cursor: pointer;
}
li {
position: relative;
z-index: 0;
}
li li {
position: static;
}
li:hover {
background: #def;
}
li:hover ul {
background: white;
}
li li:hover:before {
content: '';
position: absolute;
top: 0; bottom: 0; right: 0; left: 0;
z-index: -1;
background: white;
}
Working fiddle
I am trying to create a dropdown menu in CSS, however it will have about 21 sub-items. I would therefore like to display them in 3 columns of 7, however I cannot figure out how to do so.
I have created a jsFiddle with a simple example, how can I ammend the CSS so that sub 6-10 are displayed to the right of sub 1-5, as opposed to below?
It should look like the image below, which was created in MS Paint.
EDIT :
jsFiddle
<nav>
<ul>
<li>
Top Level Group
<div>
<ul>
<li>Sub One</li>
<li>Sub Two</li>
<li>Sub Three</li>
<li>Sub Four</li>
<li>Sub Five</li>
</ul>
<ul>
<li>Sub Six</li>
<li>Sub Seven</li>
<li>Sub Eight</li>
<li>Sub Nine</li>
<li>Sub Ten</li>
</ul>
</div>
</li>
</ul>
</nav>
Use can use float: left to make them stack
Working sample: http://jsfiddle.net/07spd07b/2/
#top-level-group{
width: 200px;
}
#top-level-group ul{
float: left;
}
In the sample I changed the original position from -9999px left so you can see it right when you open the jsfiddle. Set the width depending on the content you want to put inside. If you want more columns give it more width.
UPDATE
Here is the working sample with 3 columns and the clearfix included:
http://jsfiddle.net/07spd07b/10/
I added class clearfix:
.clearfix:before,
.clearfix:after {
content: '\0020';
display: block;
overflow: hidden;
visibility: hidden;
width: 0;
height: 0; }
.clearfix:after {
clear: both; }
.clearfix {
zoom: 1; }
Which clears floating elements and set the width: 250px; to fit the 3 columns. Hope it helps.
It can be done quite easily by using display:inline-block;:
nav ul li ul{
display:inline-block;
margin: 0;
padding: 0;
}
Then you just need to give the div a width:
nav ul li div {
position: absolute;
left: -9999px;
width:300px;
}
JSFiddle Demo
To add more columns, just make more <ul>'s and set the width wider.
please now check this link .. I've added two class in <ul> tags and styles.
http://jsfiddle.net/07spd07b/
I created a navigation bar at for my website using an in-line list and then it has been styled. Each <li> is exactly the same but I want the last one to have a different size as i wish to change the width and padding of it.
I have no idea how I am able to do this, I've tried multiple ways but experienced lots of problems along the way. I tried adding styling in the <li> tag on the HTML page, but it changed absolutely nothing, I then tried using the last-child selector which worked to an extent. It allowed me to change the padding of it but not width. But it didn't just change it for the last one but also the first one.
CSS:
.dropdown{
position: relative;
margin: 0 auto;
float: right;
top: 20px;
font-size: 13px;
}
.dropdown li {
float: left;
width: 155px;
background-color:#373737;
position: relative;
border-bottom:1px solid #575757;
border-top:1px solid #797979;
}
.dropdown li a {
display: block;
padding: 10px 8px;
color: #fff;
position: relative;
z-index: 2000;
text-align:center;
}
.dropdown li a:hover,
.dropdown li a.hover{
background: #CF5C3F;
position: relative;
}
.dropdown :last-child li a{
padding: 0px;
width: 40px;
}
HTML
<ul class="dropdown">
<li><a id="page1" href="index.html">Home</a></li>
<li>Internet Architecture
<ul class="sub_menu">
<li>Item Two</li>
<li>Item Three</li>
<li>Item Four</li>
<li>Item Four</li>
</ul>
</li>
<li>Internet Security
<ul class="sub_menu">
<li>Laws</li>
<li>Security Risks</li>
</ul>
<li>Internet Security
<ul class="sub_menu">
<li>Laws</li>
<li>Security Risks</li>
</ul>
</li>
<li>Item One
<ul class="sub_menu">
<li>Item Two</li>
<li>Item Three</li>
<li>Item Four</li>
</ul>
</li>
<li><img src="images/contact_white.png" width="30px" height="auto"></li>
</ul>
Does anyone have any idea on how to fix this?
I want the last one to have a different size as i wish to change the width and padding of it.
So if you meant last child of level 1 than use
ul.dropdown > li:last-child {
/* Target */
}
And if you meant each last child of li on 2nd level ul, than use
ul.dropdown > li > ul > li:last-child {
/* Target */
}
Demo
Demo (Just more elements, nothing fancy)
I may be missing something here, but if I understand your question right it's as simple as giving the <li> you want to be the odd one out an id, and then using css to change li#myId..
I have 2 separate menu's. I want to display the links within menu #2 when hovering over certain buttons on Menu #1. I want to try and do this with CSS if possible. Some of the css I am using is below.
HTML:
<nav>
<ul>
<li>HOME</li>
<li>NEWS</li>
<li>FORUMS</li>
<li>GAMES</li>
<li>XECOM</li>
</ul>
</nav>
<div id="sub-menu-items">
<ul>
<li>Test 1</li>
<li>Test 2</li>
</ul>
</div>
CSS:
#sub-menu-items ul li {
list-style-type: none;
z-index: 99999;
margin-right: 15px;
padding-bottom: 8px;
padding-top: 8px;
display: none;
text-shadow: 2px 3px 3px #080808;
}
nav ul li:first-child:hover #sub-menu-items ul li {
display: inline;
}
how is this not working?
The sub-menu-items need to be a child of the li you are hovering. Thats what this selector means:
nav ul li:first-child:hover #sub-menu-items ul li
CSS drop down menus are done like this:
HTML
<ul>
<li>Parent Item
<ul>
<li>Sub item</li>
<li>Sub item</li>
</ul>
</li>
<li>Parent Item
<ul>
<li>Sub item</li>
<li>Sub item</li>
</ul>
</li>
</ul>
CSS
ul ul {
display: none;
}
ul > li:hover ul {
display: block;
}
You will need to nest the sub-menus within parent 'li'
Your code will be something like this:
<nav>
<ul class="parent-menu">
<li>HOME</li>
<li>NEWS
<ul class="sub-menu">
<li>Test 1</li>
<li>Test 2</li>
</ul>
</li>
<li>FORUMS</li>
<li>GAMES</li>
<li>XECOM</li>
</ul>
</nav>
Then you can style sub-menu ul & li (preferably position:absolute) and css can be:
.parent-menu li:hover .sub-menu { display:block}
The ':hover' state of an element can only affect its child elements. To make use of :hover to affect external elements you can make use of javascript.
The CSS in this line
nav ul li:first-child:hover #sub-menu-items ul li {display: inline;}
is looking for "#sub-menu-items ul li" inside the first "li" of "nav".
Depending on your layout you can achieve the desired effect only if you move the second menu inside the first menu.