I'm creating a pure-CSS hover dropdown menu, based on a very basic idea idea.
The HTML:
<ul id="top">
<li>
Menu item 1</li>
<li>
This one has submenu
<div class="submenu">
<ul>...</ul>
<div>
</li>
</ul>
The CSS:
div.submenu {
display: none;
position: absolute;
}
ul#top > li:hover div.submenu { display:block; }
As far as I know, this is the bare minimum to get the idea working.
The problem is I want the submenu to be multi-column, without actually using CSS3 multiple columns.
So I decided to break my submenu into multiple lists and have them float: left like this:
<ul id="top">
<li>
Menu item 1</li>
<li>
This one has submenu
<div class="submenu">
<ul>...</ul>
<ul>...</ul>
<ul>...</ul>
<div>
</li>
</ul>
...and the CSS:
div.submenu ul { float:left; }
This worked well until the point when I got a pretty big submenu in the last main menu item, producing a result like this:
The problem is it is unacceptable to have the submenu fall outside the container. I decided to mark the second half of the main menu items as class="right", and align the submenu's right border to the parent item's right border.
li.right div.submenu { right: 0; }
/* this placed the submenu to the right of the entire page;
it needs a positioning context: */
ul#top li { position:relative; }
That last line causes the <ul>'s to stop floating and just get stacked on top of each other.
Is there a way to keep them floating without setting the <div class="submenu"> to a fixed width?
Interactive demo: http://codepen.io/oli-g-sk/pen/ociet
Edit: if this helps somehow, it is allowed to set the submenu list items .submenu > ul > li to a fixed width. In fact I'm already doing it in the demo.
Try removing float:left from div.submenu ul and add these two rules:
div.submenu {
white-space: nowrap;
}
div.submenu ul {
/* float:left; <-- remove this */
display: inline-block;
}
demo: http://codepen.io/anon/pen/ApxFd
Related
This question already has answers here:
Float:right reverses order of spans
(16 answers)
Closed 6 years ago.
So I've run into this problem a few times, how come my navigation menu is reversed?
.navigation li a {
display: inline-block;
text-decoration: none;
float: right;
margin-right: 10px;
}
ul {
list-style-type: none;
}
<div class="container-fluid">
<nav class="navigation">
<ul>
<li>About</li>
<li>Portfolio</li>
<li>Contact</li>
</ul>
</nav>
</div>
When put into action, the menu order is reversed, why is this happening?
You let the elements float to the right. Try to picture that..
The first element enters the document and floats all the way to the right, bumping into the side of the screen. The second enters and floats to the right as well, but bumps into the left side of the first, and stays there. And so on, and so on.
A better solution would be to use display: inline-block for the elements, and float-right for the parent (the ul).
But personally I'm not a big fan of floating at all, so I would use text-align on the ul. text-align keeps it a normal line of text, which can also include images or other inline and inline-block elements. By right-aligning the text, the order of the words is not changed, but any remaining white space is just added to the left instead of to the right of the line:
.navigation li a {
display: inline-block;
text-decoration: none;
float: right;
margin-right: 10px;
}
.navigation li {
display: inline-block;
}
.navigation ul {
text-align: right;
}
<div class="container-fluid">
<nav class="navigation">
<ul>
<li>About
</li>
<li>Portfolio
</li>
<li>Contact
</li>
</ul>
</nav>
This is happening because that's how float was designed. It will "float" the elements in the direction specified, in the order specified. If order is important, you can fix this in three ways:
Use the built-in Bootstrap alignment tools.
Apply float: right to the parent <ul> rather than each link.
Reverse the order of the elements.
In this case, you are floating elements to the right, in the order About > Portfolio > Contact. This is what happens:
About is floated right with no previous elements, so it sits against the farthest right wall of the parent container, <ul>.
Portfolio is floated right, but About is there already, so it gets as far right as it can, which puts it to the left of the previous element.
Contact is last to the party, so it ends up at the end of the line, farthest left.
I have an HTML5 page, which has a <header> element containing the <nav> section.
Due to the style and design of the overall header, the nav is absolutely positioned within the header, which is itself relatively positioned.
This works perfectly for anchors <a> for which it was originally intended. However, I now have need to add a drop-down menu and am using this one:
http://webdesignerhut.com/css-dropdown-menu/
and
How to get a drop-down menu to overlay other elements
But the issue with this and any other CSS dropdown menus that I have found is that they require the parent element to be relatively positioned, but I can't mark the parent <nav> as being both relative and absolute. I am also finding similar CSS requirements with my investigation of jQuery alternatives.
Markup:
<html>
<header>
<nav>
<ul>
<li>
<a>menu option</a>
</li>
<li>
<a>menu option</a>
<ul>
<li><a>submenu option</a></li>
</ul>
</li>
</ul>
</nav>
</header>
<main>
...
</main>
</html>
CSS (simplified, this works for non-dropdown selection)
header {
position: relative;
}
nav {
position: absolute;
}
CSS (required by dropdowns)
nav {
position: relative;
}
nav ul {
position: absolute;
}
So how can I make the nav element act as a position:relative to its children but act as a position:absolute to its parent?
EDIT
Here is a fiddle trying to outline what's going on.
https://jsfiddle.net/8j9z8wak/
It seems the original cause is that the header element (of which nav is a child) has overflow:hidden which helps with resizing on mobile devices and variable screen sizes with floating images on the top left corner of the header image.
I currently on the fiddle have tried to play with overflow-x and overflow-y but this results in scrollbars and not the intended overflow that works with removing overflow:hidden
re (just for your info.) : There are a lot of CSS / HTML parts to the fiddle, the issue is not the bare bones of the navigation but the way it fits with these other parts, so I've kept them in.
I have the nav as a child of header and I need the header to use overflow:hidden, but nav CSS menu works as intended without overflow:hidden.
I have retained media queries as the overflow:hidden is required for smaller screen size handling.
The navigation menu elements have a floating pair of parts that centre the float as found from https://stackoverflow.com/a/21508512/3536236 . This was applied just for today because all dropdown menu systems use floating elements, and they need to be centred.
Add another container element inside the <nav> and then use position: relative on the inner container:
<html>
<header>
<nav>
<div>
<ul>
<li>
<a>menu option</a>
</li>
<li>
<a>menu option</a>
<ul>
<li><a>submenu option</a></li>
</ul>
</li>
</ul>
<div>
</nav>
</header>
<main>
...
</main>
</html>
CSS:
header {
position: relative;
}
nav {
position: absolute;
}
nav div {
position: relative;
}
nav div ul {
position: absolute;
}
Check this code to clear the concept.
div{
border:1px solid #f00;
}
.gp{
position:relative;
height:100px;
width:100%;
display:block;
float:left;
overflow:hidden;
}
.p{
position:absolute;
top:30px;
left:5%;
z-index:1;
width:90%;
height:50px;
}
.c{
position:relative;
border:1px solid #0f0;
}
<div class="gp">
Grand Parents
<div class="p">
Parents
<div class="c"> childs </div>
</div>
</div>
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/
Is there a way to recognize, where the mouse moved on an element? I have a div, which I show or hide on onmouseover and onmouseout of a menu item (li).So when the user moves the mouse over the menu item, the div is shown. When the user moves the mouse left, right or top of the menu item, the div is hidden. Only when the user moves the mouse down, the div should not be hidden because the user should be able to click the content of the div.
Is there a standard way of solving those problems?
Thanks!
Wrap the elements inside any element you want, am using ul li and div which am setting to display: none; and on li:hover am setting it to display: block;
Demo
<div class="wrap">
<ul>
<li>A <div>Show A Content</div></li>
<li>B <div>Show B Content</div></li>
<li>C <div>Show C Content</div></li>
</ul>
</div>
.wrap ul li div {
display: none;
}
.wrap ul li:hover div {
display: block;
}
I have a div called NAV and inside of NAV I have an UL with 5 li which I float to the left, the li's that is but when I do that the NAV collapses. I know this because I put a border around NAV to see if it collapses and it does. Here is the example.
collapsed http://img401.imageshack.us/img401/8867/collapsedze4.png
no collapsed http://img71.imageshack.us/img71/879/nocollapsedkx7.png
as you can see in the first image, the links in the NAV div are floated left and that
black border ontop is the actual div called NAV.
in this image you can see how it has top and bottom border and it not collapsed.
here is some of the html and css I used.
alt text http://img301.imageshack.us/img301/5514/codejc8.png
#nav #ulListNavi a {
float: left;
}
Add any overflow value other than visible to your container:
div#nav { overflow:auto; }
Then add width to restore the width
div#nav { width: 100%; overflow:auto; }
One solution is to add a "clear:both" style to an element after the last floated anchor, for instance:
<div id="nav">
<ul id="ulListNavi">
<li>Home</li>
<li>Search</li>
<li>Flowers</li>
<li>My Account</li>
<li>Contact Us</li>
</ul>
<div style="clear:both;"></div>
</div>
This causes the containing element to clear all floating elements before closing the containing box.
A few other options for clearing floats here:
http://www.quirksmode.org/css/clearing.html
http://www.sitepoint.com/blogs/2005/02/26/simple-clearing-of-floats/
As to the best way of doing it, that's almost a holy war, the purists would freak about the extra div, if you are not fussed by a little extra markup, the addition of the cleared div as suggested by Joshua and AJ will work fine, and is a reliable technique, but there are at least 17 other ways of doing it...
add this code after your ul:
<div style="clear: both"></div>
Try floating the containing element to the left too.
Don't bother with clearing elements or overflow. Add this:
#nav {
float: left;
}
When you float the LI's, the #nav no longer "contains" anything so it collapses. But if the #nav is floated also, it contains anything floated inside it, so it expands again.
(Also consider removing the #nav div and just applying the same styles to the UL.)
Your problem is because you are floating the <A> elements, but each of them is inside an <LI> element. LIs display as blocks by default, so each <LI> is forcing it's child <A> to begin on a new line.
If you float the <LI>s, I think you'll solve your problem.
#nav #ulListNavi li {
float: left;
}
The quickest solution would be to add overflow:hidden to clear the float on the parent element:
#nav{overflow:hidden;}
Without changing your HTML:
#nav
{
width: 100%;
overflow: auto;
border: solid 1px red;
}
#ulListNavi
{
margin: 0;
padding: 0;
list-style: none;
}
#nav #ulListNavi li
{
float: left;
}
#nav #ulListNavi li a
{
margin-left: 5px;
}
Works in IE8 and FF 3.5