I'm new to css and want to have a simple and clear understand about the css style inheritance. Thanks for help.
The following is a horizontal navigation bar I'm trying to create.
First I did this to reset the global padding and margin (I read some tutorial and believe this is a good practice.
*{
padding: 0px;
margin: 0px;
}
Then I added some padding to my li to add some gap between menu items.
.navi ul li {
float: left;
padding: 0px 10px;
border-right: 1px dashed #770;
position: relative;
}
The following is a sub-menu item. I noticed that a padding-left of 10px was added automatically, which I think I need to add manually.
.navi ul li ul li {
border-right: none;
border-top: 1px dashed #789;
width: 200px;
}
The html:
<!DOCTYPE html>
<html>
<head>
<title><?php echo $app_name ?></title>
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="container">
<div class="header">
<div class="page_title">
<?php
echo "<h1>$app_name</h1>";
?>
</div>
<div class="navi">
<ul>
<li>Home</li>
<li>Sign up</li>
<li>
Menu1
<ul>
<li>Sub-menu1</li>
<li>Sub-menu2</li>
</ul>
</li>
<li>Log in</li>
</ul>
</div>
</div>
<div class="contents">
</div></div></body></html>
Here is a some Explanation. Build a DEMO also.
/*Will remove margin and padding from all the HTML element used in page As you are using `*` Universal Selector*/
*{
padding: 0px;
margin: 0px;
}
/*only affect the first level li*/
.navi ul li {
float: left;
padding: 0px 10px; /*As the padding given to parent `li` so the padding applied to second level `li` as well */
border-right: 1px dashed #770;
position: relative;
color:green;
}
/*only affect the Second Level li*/
.navi ul li ul li {
border-right: none;
border-top: 1px dashed #789;
width: 200px;
color:red;
}
.navi ul li {
float: left;
padding: 0px 10px;
border-right: 1px dashed #770;
position: relative;
}
The above class will apply all the li tag under the navi class div. When you use space between your selector means it will target all the child selectors. Suppose If you want to target only first level child then you need to use > between your selector like below.
.navi > ul > li {
float: left;
padding: 0px 10px;
border-right: 1px dashed #770;
position: relative;
}
So the above code will find first level child of UL from .navi, from that it will check first level child of LI. If you declare like above in your CSS, then you need to explicitly mentioned the padding for second level child as you expected.
Read for Better Understanding of Child Selector
By writing
*{
padding: 0px;
margin: 0px;
}
you are removing margin and padding from all the elements.
Following code
.navi ul li {
float: left;
padding: 0px 10px;
border-right: 1px dashed #770;
position: relative;
}
adds styling to all the lis that have parent ul, which has parent .navi.
Please note, this includes all the lis, irrespective of the level, means it could be .navi ul li, or .navi ul li ul li, or .navi ul li ul li ul li and so on.
Following code
.navi ul li ul li {
border-right: none;
border-top: 1px dashed #789;
width: 200px;
}
adds styling to .navi ul li ul li or .navi ul li ul li ul li and so on.
Probable solution of what you are asking:
Change
.navi ul li
to
.navi > ul > li
This will style only direct children of ul of .navi. i.e first level lis.
And,
Change
.navi ul li ul li
to
.navi li > ul > li
This code will affect to only direct lis of ul of lis in .navi. i.e. second level of lis.
DEMO here.
Related
I have a dropdown menu on my site's top navigation bar. I'd like the items in this menu to expand horizontally to fit their contents. For some reason they won't expand to be wider than their parent.
I've recreated the issue in CodePen here: http://codepen.io/YM_Industries/pen/GgJBQv
In my actual website I don't have control over this section of the DOM, so I'm a little constrained there.
Here's the code for my recreation in case CodePen is unavailable:
HTML:
<ul class="nav">
<li>
Home
</li>
<li>
v Test1 v
<ul class="submenu">
<li>
Submenu 1
</li>
<li>
Long text wraps and is ugly :/
</li>
</ul>
</li>
<li>
Test2
</li>
</ul>
CSS:
* {
font-family: sans-serif;
}
ul.nav,
ul.nav li,
ul.nav ul {
display: block;
padding: 0;
}
ul.nav li {
position: relative;
}
/* Style each link */
ul.nav li > a {
display: block;
padding: 10px 15px;
line-height: 20px;
height: 20px;
background: rgba(254, 197, 46, 1);
border: none;
}
/* Bring back the first level links */
ul.nav > li {
float: left;
margin-right: 1px;
}
/* Selected/Hover effect */
ul.nav li > a:hover {
color: #004d85;
background: rgb(255, 213, 102);
}
/* Display dropdown in the correct location */
ul.nav li ul.submenu {
position: absolute;
top: 40px !important;
left: 0px !important;
display: none;
}
ul.nav li:hover ul.submenu {
display: block;
}
/* Set font+colour for site links */
ul.nav li a,
ul.nav li a:link,
ul.nav li a:visited {
color: black;
font-size: medium;
text-decoration: none;
}
ul.nav li a:hover,
ul.nav li a:active {
color: blue;
}
If I explicitly set a width on my submenu items (400px for example) they will expand correctly, but for some reason the content isn't making them get wider. I'd really rather not have to hardcode the width.
Thanks,
YM
The solution is rather easy. You just have to add
ul.submenu a {
white-space: nowrap;
}
which prevents the text from wrapping and therefore doesn't stick to the parent container size.
You can check it out here http://codepen.io/anon/pen/QwbYvG
just fixed your pen - upgrade your css classes:
ul.nav li ul.submenu
{
position: absolute;
top: 40px !important;
left: 0px !important;
width:auto;
display: none;
background: rgb(254, 197, 4);
}
ul.nav li ul.submenu > li
{
display:inline-block;
white-space: nowrap;
}
AND IT USES CSS 2 :)
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
Hello I'm new to html & css and I have a problem. I made a navbar and wanted to show the user on wich page he was by changing the background-color in the navbar. But for some reason this doens't work very well. Please help me.
This is the css code I use for the navbar:
#nav{
width: 60%;
display: inline-block;
text-align: right;
float: right;
}
/* unorded list */
#nav ul{}
#nav ul li{
display: inline-block;
height: 62px;
}
/* text in blokken */
#nav ul li a{
padding: 20px;
background: orange;
color: white;
}
#nav ul li a:hover{
background-color: #ff1e42;
box-shadow: 0px 1px 1px #666;
text-decoration: underline;
}
#nav ul li #inuse {
background-color: #ff1e42;
}
my html code looks like this:
<div id="nav">
<ul>
<li><a class="inuse" href="../html/index.html" >Home</a></li>
<li><a href="../html/kleding.html" >Kleding</a></li>
<li><a href="../html/bestel.html" >Bestellen</a></li>
<li>Contact</li>
<li><a href="../html/vragen.html" >Vragen</a></li>
</ul>
</div>
Thanks in advance.
try:
#nav ul li a.inuse{/* in use css */}
instead of:
#nav ul li #inuse{}
hope that helps
I've always heard that when you use absolute positioning that the element you want to act as its parent needs to have a position of relative.
I was trying to build a CSS dropdown menu and I was struggling to get the dropdown menu items stretch beyond the width of the main menu item when I had its parent element I wanted it to use set as relative; the text in the drop down menu items would just wrap.
So I looked around at other example menus to see how they did it and one I found wasn't even using any parent elements with a position of relative even though they were using absolute positioning like I was.
That example is here: http://purecssmenu.com/
So I tried removing my relative positioning and bingo - my problem went away. However now I am using absolute positioning with none of it's parents using relative positioning, they are all set to static.
So I'm wondering how that makes sense - with no relative parents wouldn't it fall back to the browser window?
If need be, here is my HTML:
<div class="navWrapper">
<div class="left"></div>
<div class="nav">
<ul>
<li class="home">Home</li>
<li class="spacer"></li>
<li class="about">About Us</li>
<li class="spacer"></li>
<li class="trademark">Free Trademark Search</li>
<li class="spacer"></li>
<li class="services">
Services
<ul class="sub">
<li>Trademark Search</li>
<li>Prepare & File Trademark</li>
<li>Trademark Infringement</li>
</ul>
</li>
<li class="spacer"></li>
<li class="testimonials">Testimonials</li>
<li class="spacer"></li>
<li class="more">More Information</li>
<li class="spacer"></li>
<li class="contact">Contact Us</li>
</ul>
<div class="contentClear"></div>
</div>
<!-- Nav Ends -->
<div class="right"></div>
</div>
<!-- Nav Wrapper Ends -->
CSS:
#header .navWrapper {
width: 1004px;
}
#header .navWrapper .left {
float: left;
width: 4px;
min-width: 4px;
height: 47px;
min-height: 47px;
background: url('../images/nav-left-bg.png') left top no-repeat;
}
#header .navWrapper .nav {
float: left;
width: 994px;
border-top: 1px solid #e0d0b4;
border-left: 1px solid #e0d0b4;
border-right: 1px solid #e0d0b4;
border-bottom: 1px solid #e8dcc8;
background: url('../images/nav-button-bg.png') left top repeat-x;
}
#header .navWrapper .nav ul {
margin: 0 1px;
display: block;
}
#header .navWrapper .nav li {
float: left;
display: block;
height: 45px;
font-family: OpenSansBold, Arial;
font-size: 16px;
line-height: 2.9;
text-align: center;
color: #646464;
}
#header .navWrapper .nav li.spacer {
width: 2px;
min-width: 2px;
height: 45px;
min-height: 45px;
background: url('../images/nav-button-spacer-bg.png') left top no-repeat;
}
#header .navWrapper .nav li a,
#header .navWrapper .nav li a:visited
{
display: block;
height: 45px;
padding: 0 20px;
color: #646464;
text-decoration: none;
}
#header .navWrapper .nav li a:hover,
#header .navWrapper .nav li a:active,
#header .navWrapper .nav li a:focus
{
color: #fff;
background: url('../images/nav-button-bg.png') left bottom repeat-x;
}
#header .navWrapper .nav li.home {
max-width: 86px;
text-indent: -1px;
}
#header .navWrapper .nav li ul.sub {
position: absolute;
}
#header .navWrapper .nav li ul.sub li {
float: none;
display: block;
font-family: OpenSansSemibold, Arial;
font-size: 14px;
line-height: 2.3;
height: auto;
text-align: center;
background-color: #f4771d;
color: #fff;
}
#header .navWrapper .nav li ul.sub li a,
#header .navWrapper .nav li ul.sub li a
{
color: #fff;
height: auto;
}
#header .navWrapper .nav li ul.sub li a:hover,
#header .navWrapper .nav li ul.sub li a:focus,
#header .navWrapper .nav li ul.sub li a:active
{
background: #d66627;
}
#header .navWrapper .right {
float: right;
width: 4px;
min-width: 4px;
height: 47px;
min-height: 47px;
background: url('../images/nav-right-bg.png') left top no-repeat;
}
It falls back to the nearest ancestor element that has position defined as relative, absolute, or fixed -- not just relative, but any value other than static (the default).
Generally, you'd want to position the item absolutely according to a grid established by its parent. However, sometimes it makes sense to have it positioned to a grid established by a higher up element.
For example:
HTML
<body>
<div id="div1">
<div id="div2-A">[some content]</div>
<div id="div2-B">
<div id="div3">[more content]</div>
</div>
</div>
</div>
CSS
#div1{
width:1024px;margin:auto;
position:relative
}
#div3{
position:absolute;
bottom:0px; left:0px;
}
In this case, div3 will be positioned all the way to the left & bottom of div1 -- its grandfather -- because its immediate parent (div2) has the default position:static, and so does not establish as an absolute positioning context/grid for its children. But div3 will not (necessarily) go all the way to the left of the viewport or the page body because the next higher up element (div1) has position defined as relative.
UPDATE
In the case you provided (http://purecssmenu.com/), the position:relative declaration is being applied on the :hover pseudo-class, so you won't see it immediately in the styles listed for Google Developer Tools or Firebug.
You can inspect this in Google developer tools by inspecting the parent element, then in the right-hand side of the "Styles" panel, click the "Toggle Element State" button, (looks like a box with dotted border and an arrow pointing in it), then check the box next to ":hover". I'm sure Firebug has something similar.
You'll see this declaration added to the list:
ul.cssMenu li:hover { position: relative; }
This works because when you're not hovering on the parent <li>, the sub-menu <ul> is hidden with display:none, so it doesn't matter where it's positioned.
Another note on the nearest ancestor when an element is being positioned.
Three years later after the OP, CSS3 properties like transform are more widely being used, which implicitly creates a new containing block, forcing the element to have position: relative/absolute;
So to make sure intermediary parent elements have no effect in the positioning of a child element, you need check it has position: static and no transforms set.
Example
<div id="one">
<div id="two">
<div id="three"></div>
</div>
</div>
#one {
position: relative;
}
#two {
position: static;
transform: none;
}
#three {
position:absolute;
}
Ref this tutorial: https://www.servage.net/blog/2009/03/20/create-a-cool-css-based-drop-down-menu/
I used an external stylesheet, and simply put #menu before each CSS item, like this:
#menu ul{
font-family: Arial, Verdana;
font-size: 14px;
margin: 0;
padding: 0;
list-style: none;}
or:
#menu ul li{
display: block;
position: relative;
float: left;}
But, when i reference with #menu, the menu doesn't render properly. It leaves the parent 'li' untouched by CSS.
http://jsfiddle.net/UGW2L/
Any ideas?
Thx,
Dave
Your HTML is this:
<ul id="menu">
Which means your CSS needs to be this:
ul#menu
Your current CSS is looking for an 'LI inside of a UL that is inside of some other element with an ID of MENU'
#menu ul targets this (any ul inside of an element with id='menu')...
<div id="menu">
<ul> <!-- <<-- this element is the target -->
...
</ul>
</div>
(div is just an example, any element with id="menu" can be used above)
ul#menu targets this (the ul with id='menu')...
<ul id="menu"> <!-- <<-- this element is the target -->
...
</ul>
Edit as per comments:
Quote: "...i am missing the 'box' around the parent node."
I think the node to which you refer is the <li>, just inside the parent <ul id='menu'>, and you have not targeted it anyplace at all.
Just add ul#menu li a to your box styling. (Note the comma. It separates two totally unique selectors sharing the same styling.)
ul#menu li a,
ul#menu ul li a {
display: block;
text-decoration: none;
color: #ffffff;
border-top: 1px solid #ffffff;
padding: 5px 15px 5px 15px;
background: #2C5463;
margin-left: 1px;
white-space: nowrap;
}
http://jsfiddle.net/cWpEg/1/
See the difference?
ul#menu is the parent.
ul#menu li is the first item inside the parent.
ul#menu li a is the link inside the first child of the parent.
Since ul#menu li targets any & all <li>'s that are children of the ul#menu parent, you would only need the one selector...
ul#menu li a {
display: block;
text-decoration: none;
color: #ffffff;
border-top: 1px solid #ffffff;
padding: 5px 15px 5px 15px;
background: #2C5463;
margin-left: 1px;
white-space: nowrap;
}
http://jsfiddle.net/cWpEg/2/
Also note how it's the full width of the screen.
To target & style just the parent, add something like this.
ul#menu {
display: block;
position: relative;
float: left;
list-style: none;
}
http://jsfiddle.net/cWpEg/6/