Inherit width from indirect ancestor - css

I have the following HTML
<ul id="nav">
<li>
Menu Item 1
<ul class="sub_menu">
<!-- full of <li> sub menu items -->
</ul>
</li>
<li>
Menu Item 2
<ul class="sub_menu">
<!-- full of <li> sub menu items -->
</ul>
</li>
<li>
Menu Item 3
</li>
</ul>
The #nav is 100% the width of the browser window.
Using only CSS I want to float the Menu Items side by side inside a container that has similar CSS:
{ width: 1000px; margin: 0 auto; }
But I want the .sub_menus to be the same width as #nav.
How can this be done without changing the HTML?

You can position: relative the #nav, do your thing with the li and then position: absolute; left: 0; right: 0 the .sub_menu.
This way .sub_menu is the same width as #nav regardless of the width of li. You'll have to add and adjust some more styles to make it look pretty and in position but I'll leave that to you.
An additional requirement is that li will stay position: static as the position of .sub_menu must be relative to #nav.
EDIT: #simon's answer is pretty much an implementation of mine, but OP has left a comment there indicating that it isn't adequate. We're still unsure of what the problem is.

Try the following (jsbin):
* { margin: 0; padding: 0 }
#nav, .sub_menu {
width: 100%;
height: 30px;
position: relative;
background: green;
}
#nav > li > a {
z-index: 1;
position: relative;
}
#nav > li {
float: left;
list-style-type: none;
}
.sub_menu {
position: absolute;
left: 0;
background: red;
top: 30px
}
This puts all the buttons one after another and keeps the submenu 100% width

here you go:
http://codepen.io/anon/pen/YXZQMo
The Subnav UL has now the same width as the parent li
#nav { width: 1000px; margin: 0 auto; }
ul{
margin:0;
padding:0;
list-style:none;
}
ul li{
display:block;
float:left;
padding: 5px 10px;
width:auto;
}
ul li:hover ul{
display:block;
}
ul li ul{
display:none;
width:100%;
background-color:red;
min-height:20px;
transition:all 0.3s;
}
ul li ul li{
display:block;
float:none;
}

Related

Make menu items and submenu items display vertically without covering each other up

As the first step in making my menu responsive, I want to add a media query in css to change the way the menu displays so that each list item is displayed vertically below the previous item, with it's own submenu items displayed below it before the next list item is displayed. Hope that makes sense. Here are the HTML and CSS that make the menu work in the desktop version of the site:
HTML
<nav>
<img id="logo" src="#logoUrl">
<ul>
<li class="#(CurrentPage.Url == "/" ? "current" : null)">Home</li>
#foreach (var item in menuItems)
{
<li class="#(CurrentPage.Id == item.Id ? "current" : null)">
#item.Name
#if (item.Children.Where("Visible").Any())
{
var subMenuItems = item.Children.Where("Visible");
<ul>
#foreach (var sub in subMenuItems)
{
<li>#sub.Name</li>
}
</ul>
}
</li>
}
</ul>
<br class="clear">
</nav>
(This is on Umbraco, so forgive all the Razor bits)
CSS
#logo {
float: left;
margin-right: 25px;
}
nav {
width: 100%;
height: auto;
background-color: #354a49;
}
nav > ul > li {
display: block;
position: relative;
width: auto;
height: 50px;
float: left;
font-size: 1.1em;
margin: 0px 20px 0px 20px;
padding: 15px 8px 13px 8px;
text-align: center;
}
nav ul li a {
color: #fefce9;
margin-left: auto;
margin-right: auto;
}
nav ul li a:hover {
font-style: italic;
}
nav ul ul {
display: none;
position: absolute;
top: 100%;
left: 0;
z-index: 99;
width: 200px;
}
nav ul li:hover {
border-bottom: 2px solid #fefce9;
background-color: #a1b0af;
}
nav ul li:hover > ul {
display: block;
margin-top: 2px;
}
nav ul li ul li {
display: block;
float: none;
padding: 20px 3px;
background-color: #a1b0af;
border-bottom: 2px solid #fefce9;
}
nav ul li ul li a {
color: #fefce9;
}
nav li.current {
background-color: #a1b0af;
border-bottom: 2px solid #fefce9;
}
nav li.current > a {
color: #fefce9;
font-style: italic;
}
And here is the CSS I have in my media query at the moment:
#logo {
margin-right: -50px;
}
nav > ul > li {
float: none;
margin: 0px;
}
nav ul ul {
width: 100%;
}
nav li.current {
background-color: inherit;
}
That displays the main menu items one below the other OK, but when I try to change things so that the submenu items appear between the menu items I just end up with the submenu items appearing over the top of the menu items and each other.
EDIT
Here's the rendered HTML as requested:
</nav>
<img id="logo" src="/media/1042/wshalogo.png">
<ul>
<li class="current">Home</li>
<li>
About us
<ul>
<li>Our People</li>
<li>Who we were and are</li>
<li>Our Houses</li>
<li>Annual Reports</li>
</ul>
</li>
<li>
Being a Tenant
<ul>
<li>Asbestos</li>
<li>Being Safe & Secure</li>
</ul>
</li>
<li>
News
<ul>
<li>Community Garden</li>
<li>Football Team</li>
<li>Health Centre</li>
</ul>
</li>
</ul>
<br class="clear">
</nav>
Your second level ul is position: absolute; which means it's taken out of the normal document flow and won't take up space in relation to any other elements. Try changing absolute to relative. That should keep the items correctly positioned in the menu.
nav ul ul {
display: none;
position: absolute; /* <--- Try changing this to relative. */
top: 100%;
left: 0;
z-index: 99;
width: 200px;
}
Also, the fixed height on your top-level li doesn't let the element grow past 50px. Try setting that instead to a min-height:
nav > ul > li {
display: block;
position: relative;
width: auto;
height: 50px; /* <-- min-height: 50px */
float: left;
font-size: 1.1em;
margin: 0px 20px 0px 20px;
padding: 15px 8px 13px 8px;
text-align: center;
}
That worked in this fiddle but led to awkward jumping when the sub-menu was hovered and then un-hovered.
Also, consider your use-case - if you're doing this to support tablet/mobile devices the :hover state won't work the same way it doesn't when you're using a mouse. Users would have to know to press to the side of the "About Us" link text to see the dropdown, otherwise they'll get taken directly to the "About Us" page without seeing the :hover state. It might be necessary to either show all the items in a tree structure or use JavaScript to add additional functionality for the submenus.
Here's a decent solution to a responsive sub-menu without JavaScript, but it also doesn't use links for top-level menu items that have sub-items.

How to make an on-hover bottom border overlap div below?

I have a horizontal navigation menu using unordered lists. Under the menu there is a straight gray line which has to have 100% width of the parent container. When hovering the list elements, the part of the line has to be colored blue right under the list element. I can't find any suitable way of doing this. I got it working with position:relative and adding top:14px but it isn't really satisfying me since any changes to the font size or font face will destroy everything. I also thought about changing margins between elements to padding, increasing li's height and giving each one the same gray border and just changing it's color on hover, but I need the line to go all along the parent div's width.
How it has to look:
expected result
My current code:
#container {
width: 80%;
margin: auto;
background-color: white;
}
#container ul {
list-style-type: none;
display: inline-block;
margin: 0;
padding: 0;
margin-top: 5px;
margin-bottom: 10px;
}
#container ul li {
float: left;
margin-left: 20px;
}
#container ul li:first-child {
margin-left: 0;
}
#container ul li a {
text-decoration: none;
color: black;
}
#container ul li a:hover {
color: grey;
}
#container #slider {
display: inline-block;
height: 5px;
background-color: #f1f1f1;
width: 100%;
}
<div id="container">
<ul>
<li>INDEX</li>
<li>HELP</li>
<li>LONG LINK TEXT</li>
</ul>
<span id="slider"></span>
</div>
JSFiddle: https://jsfiddle.net/9fhvyk76/3/
You'll want to use a pseudo element so you have more control over the size/position without really needing to change much. Just add position: relative to the link itself so the pseudo's scale and positioning are associated with it. Let me know if this is what you were looking for!
https://jsfiddle.net/g00jrsqf/
#container ul li a{
position: relative;
}
#container ul li a:after{
content: '';
position: absolute;
display: block;
width: 100%;
height: 4px;
background: #01a2e8;
opacity: 0;
left: 0;
bottom: -29px;
}
#container ul li:hover a:after{
opacity: 1;
}

CSS menu bar centered with dropdown

Working on a menu bar that has counter active css classes. I need the menu bar centered and the drop downs to be under the proper list item. I can get one or the other but not both to work at the same time. The menu bar changes sizes, so putting a static margin left on it will not work. This is what the menu bar should look like but it's not centered.
And this is what happens when i remove the float: left from #mainmenu ul li{}. It's now centered, but the items that belong under the user name are all shifted left.
Why does this happen? and how do i get around it?
html:
<div id="mainmenu">
<?php
if(Yii::app()->user->name)
$display_name = Yii::app()->user->name;
if(strlen($display_name) > 11){
$display_name = substr($display_name,0,9);
$display_name =$display_name.'...';
}
?>
<?php $this->widget('zii.widgets.CMenu',array(
'items'=>array(
array('label'=>'Home', 'url'=>array('/site/index')),
array('label'=>'My Tickets', 'url'=>array('/ticket/mytickets'), 'visible'=>!Yii::app()->user->isGuest),
array('label'=>'About', 'url'=>array('/site/page', 'view'=>'about')),
array('label'=>'Contact', 'url'=>array('/site/contact')),
array('label'=>'Schools', 'url'=>array('/school'), 'visible'=>Yii::app()->user->id == 'admin'),
array('label'=>'Teams', 'url'=>array('/team'), 'visible'=>Yii::app()->user->id == 'admin'),
array('label'=>'Login', 'url'=>array('/site/login'), 'visible'=>Yii::app()->user->isGuest),
array('label'=>'Games', 'url'=>array('/game'), 'visible'=>Yii::app()->user->id == 'admin'),
array('label'=>'Users', 'url'=>array('/user'), 'visible'=>Yii::app()->user->id == 'admin'),
array('label'=>'Tickets', 'url'=>array('/ticket'), 'visible'=>Yii::app()->user->id == 'admin'),
array('label'=>'Team Placement', 'url'=>array('/tournamentresults'), 'visible'=>Yii::app()->user->id == 'admin'),
array('label'=>$display_name, 'url'=>array('#'), 'visible'=>!Yii::app()->user->isGuest,
'items' => array(
array('label'=>'Edit User', 'url'=>array('/company/index')),
array('label'=>'Log-out', 'url'=>array('/site/logout'))
),
),
),
)); ?>
</div><!-- mainmenu -->
Generated HTML code:
<div id="mainmenu">
<ul id="yw0">
<li class="active">Home</li>
<li>My Tickets</li>
<li>About</li>
<li>Contact</li>
<li>SirRahal
<ul>
<li>Edit User</li>
<li>Log-out</li>
</ul>
</li>
</ul>
</div>
CSS code:
#mainmenu
{
height:33px;
margin: auto;
text-align:center;
}
#mainmenu ul li
{
display: inline;
float: left;
margin: auto;
}
#mainmenu ul li a
{
color: #fbf3e1;
font-size:14px;
padding-top:5px;
padding-bottom:5px;
width:217px;
background: #33332c;
}
#mainmenu ul li ul {
display: none;
position: absolute;
margin-left: -20px;
}
#mainmenu ul li:hover > ul {
display: block;
}
#mainmenu ul li a:hover, #mainmenu ul li.active a
{
color: #f5921e;
border-bottom: solid 5px #f5921e;
text-decoration:none;
border-bottom-right-radius: 5px;
border-bottom-left-radius: 5px;
}
The biggest key, in my opinion, to building a CSS dropdown/flyout menu is using absolute positioned elements inside relative positioned elements and where to use them. What's even more important is to understand how these two positioning schemes relate to one another. Once you do, you can build all sorts of dropdown/flyout menus.
You will want to set position: relative to all of your menu li whether they contain a submenu or not. Doing so will not affect their position unless you start using top, right, bottom, left CSS properties.
.menu li {
position: relative;
}
Now you will want to set the position of all ul that are a child of an li in your menu to position: absolute. We also don't want them to show right away so hide them with display: none.
.menu li > ul {
display: none;
position: absolute;
}
Applying position relative to the containing element of an absolute positioned element helps contain the absolute positioned element. Not only that but the absolute positioned element will base it's positioning off of the relative positioned parent element, which is what we want. Setting top: 0 and left: 0 will cause a ul that is a child of an li to start in the same upper left hand location as it's parent elements upper left hand corner.
The two rules I have provided so far are the fundamental building blocks of a dropdown/flyout menu in CSS.
From this point forward it will all depend on your design goals as to what else you need to add to your CSS.
I'm going to (mostly) use generic code the rest of the way in the hopes that yourself and others can build off of the basic principles to obtain your own specific results. That said I will base the rest of the code off of what you have supplied. Some superficial styling like borders will be ignored, you can add that later.
HTML
Here is the HTML I'm going to use. Add in anchor elements as needed.
<ul class="menu">
<li>One</li>
<li>Two
<ul>
<li>Sub Two A</li>
<li>Sub Two B</li>
</ul>
</li>
<li>Three</li>
</ul>
Your top level menu is inline so let's use float: left to do that.
They're also fixed width. You're doing this through your anchor tags <a> which is fine, I'm going to use the li.
Your text is centered.
.menu li {
float: left;
position: relative;
text-align: center;
width: 100px;
}
**SEE EDIT BELOW FOR VARIABLE LI ANSWER**
Since you are using fixed width navigation elements you can center your navigation with margin: 0 auto. Using auto for margin left and right to center an element requires a width to be set! Just add up the full width of your top level li and you'll have your width you'll need to center the navigation. Don't forget to include any padding, margin, border etc. in the width calculation.
My example uses three li at 100px width.
.menu {
width: 300px; /* width of the 3 li */
margin: 0 auto; /* centers ul when width is specified */
}
Now we will position the submenu ul.
For top you need to push the submenu ul down the height of the containing li. I'm going to assume 25px is the height of the li.
For left you want it to start at the same edge as the containing li so use 0.
.menu li > ul {
display: none;
left: 0;
position: absolute;
top: 25px;
}
Now let's display the submenu ul when the parent li is hovered.
.menu li:hover > ul {
display: block;
}
CSS
The final CSS.
.menu {
width: 300px; /* width of the 3 li */
margin: 0 auto; /* centers ul when width is specified */
}
.menu li {
float: left;
line-height: 25px; /* assumed height of li */
position: relative;
text-align: center;
width: 100px;
}
.menu li > ul {
display: none;
left: 0;
position: absolute;
top: 25px;
}
.menu li:hover > ul {
display: block;
}
Here is a jsFiddle with some basic styling that wraps it all together.
There you go! A primer to CSS dropdown/flyout menus. As usual your needs will require some modifications or additions to what I have supplied. If you understand the fundamentals you'll go a long way in developing more in-depth and robust solutions.
**EDIT**
Just noticed you have variable number of li in your navigation. Make the changes where appropriate. It is a combination of relative positioning with percentage positions.
.menu {
float: left;
position: relative;
left: 50%;
}
.menu li {
float: left;
line-height: 25px; /* assumed height of li */
position: relative;
right: 50%;
text-align: center;
width: 100px;
}
/* undo the right positioning for submenu li so it aligns properly */
.menu li > ul li {
right: auto;
}
Here is an updated jsFiddle.
Replace your CSS like this, using your LI elements for styling rather than your A elements:
body {
width:100%;
}
#mainmenu {
display: block;
width:100%;
}
#mainmenu ul {
width:100%;
}
#mainmenu ul li {
display: inline-block;
position:relative;
margin: auto;
width:19%;
background: #33332c;
padding-top:5px;
padding-bottom:5px;
}
#mainmenu ul li a {
color: #fbf3e1;
font-size:14px;
}
#mainmenu ul li ul {
display: none;
position: absolute;
}
#mainmenu ul li:hover > ul {
display: block;
width:auto;
position:absolute;
top:30px;
left:0;
background: #33332c;
padding:10px;
}
#mainmenu ul li:hover > ul li {
display: block;
width:150px;
height:auto;
}
#mainmenu ul li a:hover, #mainmenu ul li.active a {
color: #f5921e;
border-bottom: solid 5px #f5921e;
text-decoration:none;
border-bottom-right-radius: 5px;
border-bottom-left-radius: 5px;
}
You may need some additional adjustments, but there you have the basics
See fiddle here

Drop down menu with CSS

I tried solving this using some tips from this site but it doesn't seem to work for me. I have a website http://apartmanimikzaton.com/paintball/index.php, and I want to create a drop down menu like from the navigation.
EDIT: I didn't add it right now, but the thing I want to get is drop down menu text on hover.
This is my navigaton:
<ul class="navigation">
<li id="navigation-1"> O nama </li>
<li id="navigation-2"> Oprema </li>
<li id="navigation-3"> Tereni
<ul>
<li> Lokacija 1 </li>
<li> Lokacija 2 </li>
</ul>
</li>
<li id="navigation-4"> Galerija </li>
<li id="navigation-5"> Cjenik </li>
<li id="navigation-6"> O Paintballu </li>
<li id="navigation-7"> Teamovi </li>
<li id="navigation-8"> Webshop </li>
</ul>
And this is my css:
.navigation {background: url(images/layout/navigation.jpg) no-repeat; width: 980px; height: 57px; margin: 0 0 10px 0; padding: 0;}
.navigation li, .navigation a {height: 57px; display: block;}
.navigation li {float: left; text-indent: -9999em; position: relative;}
.navigation ul ul{
position:absolute;
left: 0;
top: 100px; /* height of the parent list item */
display:none; /* hide it */
}
.navigation li:hover > ul{ /* show it when mouse is over the parent list item */
display:block;
}
I'm doing something wrong so any tips would be appreciated.
I took the time to analyze your code, and here's what I can help you with for now.
First of all, insert these styles into your CSS:
ul.navigation li ul{
background: none repeat scroll 0 0 #000000;
display:none;
padding: 0;
position: absolute;
top: 57px;
width: 117px;
z-index: 6;
}
On the following styles:
.navigation li {
float: left;
position: relative;
text-indent: -9999em;
width: 100%;
}
The text-indent: -9999em; is affecting the text of the drop down menu you want to insert. I suggest you remove it. If you don't wish to display the text over your menu icons, you can simply do it like this on your link:
I don't think this approach will work:
.navigation li:hover > ul{ /* show it when mouse is over the parent list item */
display:block;
}
Try this instead and see if it works:
.navigation li:hover ul{
display:block;
}
That should at least help you a bit, can't really tell if that's what you are intending to do. Give a response if you manage to accomplish what you wanted.
Cheers,
Artur Balestro
Remove this:
.navigation li:hover > ul{ /* show it when mouse is over the parent list item */
display:block;
}
And Add this
.navigation li:hover ul{ /* show it when mouse is over the parent list item */
display:block;
}
There are some unnecessary styles in there that need cleaning up, but if you're wanting a quick fix:
.navigation > li:hover > ul,
.navigation > li:hover > ul > li,
.navigation > li:hover > ul > li > a {
text-indent: 0;
display: block;
z-index: 999;
background: #fff;
}

How do I force nested list items to be the same width as parent list item?

I have a horizontal parent list. Some of the list items display a nested vertical list when clicked. How do I force the items in the vertical sub list to be the same width as the parent list item?
See jsFiddle.
HTML:
<ul class="mainMenu horizontalMenu bulletless fullWidth bold">
<li class="showSubMenu">
<div>Resumes & Cover Letters ▾ </div>
<ul class="mainSubMenu bulletless">
<li><a>Resumes</a></li>
<li><a>Cover Letters</a></li>
<li><a>Interviews</a></li>
</ul>
</li><li><a>Other Link</a>
</li><li><a>Other Link</a></li>
</ul>​
CSS:
.horizontalMenu li{
display: inline-block;
}
.mainMenu > li{
border: 1px solid black;
}
.mainMenu a, .mainMenu div{
display: block;
padding: 10px 20px;
}
.mainSubMenu{
position: absolute;
}
I did the change on your fiddle. http://jsfiddle.net/BXnxc/2/
The parent li needs to have position:relative; and the nested submenu has to have width:100%; and position:absolute;
You can do this by specifying the parent LI as relative and child UL with width: 100%
Demo: http://jsfiddle.net/BXnxc/3/
.horizontalMenu li {
position: relative;
}
.horizontalMenu li ul {
width: 100%;
}
You can also do this by inheriting the width of the containing structures. I set your mainMenu div to width of 200px and then width:inherit for the mainSubMenu.
http://jsfiddle.net/BXnxc/4/
.mainMenu a, .mainMenu div{
display: block;
padding: 10px 20px;
width:200px;
}
.mainSubMenu{
position: absolute;
width:inherit;
}
.mainSubMenu li
{
display: block;
border: 1px solid grey;
width:inherit;
}

Resources