CSS: Class of first menu layer applied on submenu - html

I've got a navigation menu. But the menu get's wild.
The submenu class (this is the dropdown if you hover firstmenu). 'firstmenu' are the main areas of the site, hence the first level of the list.
Problem: Submenu get's the Firstmenus values. Even the tiny arrow background: url(images/nav-arrow.png) no-repeat center bottom; in - BUT WHY?!
We already looked into this, split up the code, removed typo3, all JavaScript and ended up with this css code:
#firstmenu {
list-style: none;
margin: 0;
padding: 0;
}
#firstmenu .firstLevel {
float: left;
}
#firstmenu .firstLevel a {
display: block;
font-size: 1.166em;
font-weight: 600;
line-height: normal;
color: #333;
padding: 41px 20px 26px;
margin-bottom: 4px;
}
#firstmenu .firstLevel .current a,
#firstmenu .firstLevel a:hover,
#firstmenu .firstLevel a.selected {
color: #fff;
background: url(images/nav-arrow.png) no-repeat center bottom;
}
#firstmenu .firstLevel a:hover,
#firstmenu .firstLevel a.selected {
background-color: #333;
}
/* Drop-Down Menus */
.submenu {
list-style: none;
margin: 0;
padding: 0;
position: absolute;
}
.submenu > ul {
top: 4px !important;
}
.submenu .secoundLevel {
width: 200px;
background: #fca500;
}
.submenu .secoundLevel a {
display: block;
color: #fff;
padding: 8px 15px;
border-top: 1px solid rgba(255,255,255,0.2);
}
.submenu .secoundLevel a:hover {
background-color: #333;
border-color: #1a1a1a;
}
.submenu .secoundLevel:first-child a {
border-top: none;
}
Anyone knows the fix?
EDIT, html:
<nav id="nav">
<ul id="firstmenu" class="clearfix">
<li class="firstLevel"><a href="index.php?id=99" >Startseite</a></li>
<li class="firstLevel current">Rootserver
<ul class="submenu">
<li class="secoundLevel"><a href="index.php?id=96" >Vergleich</a></li>
</ul>
</li>
<li class="firstLevel">Voiceserver
<ul class="submenu">
<li class="secoundLevel">Preisvergleich</li>
</ul>
</li>
</ul>
</nav>

I think the problem is a matter of understanding of CSS selectors. This selector:
#firstmenu .firstLevel a.selected {
color: #fff;
background: url(images/nav-arrow.png) no-repeat center bottom;
}
States the following: Match ALL <a> links that have a parent with class name firstLevel and it having a parent with ID firstmenu
That means this HTML bit matches:
<ul id="firstmenu" class="clearfix">
// snip
<li class="firstLevel current">Rootserver
<ul class="submenu">
<li class="secoundLevel">Vergleich</li>
</ul>
</li>
// snip
because the "secondLevel" menu has an anchor tag (<a>) that is a child (of any order, ie child, grandchild, great-grandchild, etc) of .firstLevel which is a child (of any order) of #firstmenu.
This is exactly how CSS is suppose to work but there ways to prevent what you're seeing.
The first option is to use the child selector (what I sometimes refer to as "direct descendent" selector) >
.firstLevel > a:hover{ /* code */ }
This selector specifically states: "all anchor tag that you hover which are directly descendent from .firstLevel, but no deeper.
Which means, it matches:
<li class="firstLevel">A</li>
but not the link with value "B" below
<li class="firstLevel">A
<ul>
<li><a href="#">B</b></li>
</ul>
</li>
because the second <a> tag is not directly descendant of .firstLevel, there's a <ul> and <li> between them.
The second option is to "overwrite" the previous style by having another rule with a higher CSS specificity.
#firstmenu .firstLevel .submenu a.selected {
background-image: none; /* remove the arrow from drop-down menus*/
}
There's reasons for doing one or the other.
Using the child selector is good when the styles are very specific to that element. You don't want ANY of the styles to carry over to further elements.
Use the "replacement" technique (for lack of a better term) when you're looking to modify only one specific style from another element. Ie. You want to keep the color, font, font-weight, but only want to remove the background image.
I hope that helps!
Here's some (bad) fiddles showing the base case:
http://jsfiddle.net/zTCbF/
with child selector
http://jsfiddle.net/zTCbF/1/
with the replacement technique
http://jsfiddle.net/zTCbF/2/

#firstmenu .firstLevel a {
This will target any anchor tag under .firstLevel including those under .secondLevel
So when you say...
#firstmenu .firstLevel a:hover,
You are applying your hover styles to ALL anchor tags that are descendants of .firstLevel
You want to say ...
#firstmenu .firstLevel > a {
Which will target only anchor tags that are a direct descendant of .firstLevel

Related

Change Sorted List Background color

I am currently woking on a small navigation in HTML using CSS.
I have a sorted List with every li element Containing a link.
I want it to change the background color, when hovering over it. The problem is, that the number telling you the index of the list item won't get changed because "this" background is not part of the li element. Example
The ol element, which "owns" this background is the whole list, but I just want that the background of this specific list entry gets changed.
My code is:
.navig a:hover{
background-color: #555;
color: white;
}
and
<ol>
<li>
target
</li>
</ol>
The navig class is used to make clear that the link belongs to the navigation.
Is there a way to fix this without JScript, or belongs this to the missing "CSS support for parent selecting" thing?
Use list-style-position: inside; to move the numbers / bullet into the li element:
ol {
background: #ff9999;
padding: 0;
list-style-position: inside;
}
li {
padding: 5px;
}
li:hover {
background: #ffe5e5;
}
li > a {
display: block;
color: black;
text-decoration: none;
}
<ol>
<li>
Coffee
</li>
<li>
Tea
</li>
<li>
<a href="https://www.google.co.il/webhp?q=coca+cola">Coca Cola<a>
</li>
</ol>
Another solution as described here is to convert your list into a DL/DT list and explicitly generate the numbers using a CSS counter.
.navig {
counter-reset: navig-counter;
}
.navig dt:hover {
background-color: #555;
color: white;
}
.navig dt:before {
content: counter(navig-counter);
counter-increment: navig-counter;
margin-right: 5px;
}
<dl class="navig">
<dt>First item</dt>
<dt>Second item</dt>
<dt>Third item</dt>
</dl>

Allowing a sub-menu to be larger than its parent without sacrificing layout?

I have found this question, and this question. I tried to apply whitespace: nowrap; to my code, but had no luck. The second question I simply cannot discern what is relevant and what isn't.
I have this HTML:
<ul id="main-menu-list">
<li><a class="box-link" href="#/home">Home</a></li>
<li><a class="box-link" id="shop-link" href="#/shop">Shop</a>
<ul>
<li>
Test
</li>
<li>
Test 2
</li>
</ul>
</li>
<li ng-repeat="linkData in coreCtrl.mainMenuData"><a class="box-link" href="#/{{ linkData.linkUrl }}">{{ linkData.value }}</a></li>
</ul>
In that last bit I'm using Angular to create some links from JSON which don't have sub-menus.
I also have this CSS:
#main-menu-list, #main-menu-list ul {
padding: 0;
margin: 0;
list-style: none;
}
#main-menu-list > li {
float: left;
margin-right: 20px;
line-height: 65px;
}
#main-menu-list > li > a {
font-weight: bold;
font-size: 20px;
color: #6e6e6e;
border: 2px solid #6e6e6e;
padding-top: 5px;
padding-bottom: 5px;
}
#main-menu-list > li > a:hover {
border: 2px solid #a1b489;
color: #a1b489;
text-decoration: none;
}
#main-menu-list > li > ul > li {
background-color: #fff;
position: relative;
z-index: 5;
margin: 0;
}
#main-menu ul a {
white-space: nowrap;
}
The end goal here is to create a sub-menu for the "Shop" link which contains the shop's categories. However, the drop-down needs to be wider that the parent list item. I can increase the width of the sub-menu, but at the cost of increasing the width of the parent <li> element, which throws off the layout of the main menu.
Is there any way to make the sub-menu larger than the parent element without sacrificing the parent's layout?
i would make the parent li relative positioned and the sub-nav absolute positioned, this should sort out your problem.
#main-menu-list li {position: relative;}
#main-menu-list li > ul {position: absolute; top: 100%; left: 0;}
Use css property position : absolute for the drop-down ul and position : relative for the parent ul
After that define top and width of the drop-down ul and it will work

CSS selector applying style to only parent link

I'm having some problems getting my CSS selector to pick the parent link only.
<style>
.sidebar .nav li a {
background-color: transparent;
border-right: 1px solid #563D7C;
color: #563D7C;
font-weight: bold;
}
</style>
<div class="sidebar">
<ul class="nav sidenav">
<li>
Menu1
<ul class="nav">
<li>Item1</li>
</ul>
</li>
<li>
Menu2
<ul class="nav">
<li>Item1</li>
</ul>
</li>
</ul>
Unfortunately.. the style applying to ALL links in the nav, my alternative is to put a class on all of the links I want styled, but rather not have to do that.
http://jsfiddle.net/bFxm4/
A child selector matches when an element is the child of some element.
A child selector is made up of two or more selectors separated by >.
CSS 2.0 Specifications - Selectors, 5.6 Child selectors
.sidebar .nav > li > a {
background-color: transparent;
border-right: 1px solid #563D7C;
color: #563D7C;
font-weight: bold;
}
Demo
this work DEMO :
.sidebar .nav.sidenav > li > a {
background-color: transparent;
border-right: 1px solid #563D7C;
color: #563D7C;
font-weight: bold;
}
The ">" means : picks the ones which are directly child
I think that putting a class on all of the parent links is fine. Especially is you are using some loop on the back end to generate the html, then adding a class to each one is simple.
If you're trying to get the style to apply to .sidebar .nav li a only, and not the links in the nested lists, you can change your selector to read like this: .sidebar .nav > li > a. This targets <a> tags that are direct descendants of <li> tags only, and only those that are in the top level list. It won't go any deeper.
try this:
.sidebar > .nav > li > a {
background-color: transparent;
border-right: 1px solid #563D7C;
color: #563D7C;
font-weight: bold;
}
hope this helps

Unordered list navbar elements have strange gaps

I'm trying to write a navigation bar using an <ul> with inline elements, but the elements all have a gap between them that seem to come from nowhere. That is when hovering a link, the shaded box should snap to the surrounding boxes. The page currently looks like this: http://wictorht.at.ifi.uio.no/. What is causing these gaps?
HTML:
<body>
<div id="main">
<ul class="header">
<li class="title">wictorht</li>
<li class="header">
<a class="header" href="https://bitbucket.org/htor/dwmst/src">dwms</a>
</li>
<li class="header">
<a class="header" href="https://bitbucket.org/htor/linux/src">linux</a>
</li>
<li class="header">
<a class="header" href="http://www.fsf.org/register_form?referrer=10397">fsf</a>
</li>
<li class="header">
<a class="header" href="http://stackexchange.com/users/1006063">stackexhange</a>
</li>
</ul>
</div>
</body>
CSS:
body {
background: #666666;
color: #c0c0c0;
margin: 0;
}
a.header {
text-decoration: none;
padding: 10px;
margin: 0;
}
a.header:hover, a.header:active {
background-color: #666666;
color: #c0c0c0;
}
ul.header {
background-color: #c1c1c1;
color: #666666;
list-style: none;
padding: 10px 10px 10px 0;
margin: 0 0 10px 0;
}
li.header {
display: inline;
}
li.title {
background-color: #000000;
color: #bada55;
display: inline;
padding: 10px;
}
This is because all white-space, including new-lines, between elements is collapsed down to a single space when rendered by the client's browser. To hide the spaces you can either:
Remove the spaces between li elements:
<li><!-- content --></li><li><!-- more content --></li>
Set the font-size of the parent ul to 0, and redefine the font-size of the li element:
ul {
font-size: 0;
}
ul li {
font-size: 14px;
}
Comment out the gaps between the li elements:
<li>Content</li><!--
--><li>Next li</li>
Float the li elements instead of using display: inline, which removes the spaces by taking the elements out of the normal flow:
ul {
overflow: hidden; /* to keep the li 'visibily' within the bounds of the ul */
}
ul li {
float: left;
}
Close the li tag on the next line, before the next li opening tag this feels slightly wrong to me, but it is valid:
<li>First li</li
><li>Second li</li>
(Or, obviously, place the next li opening-tag on the previous line, immediately after the previous element's closing tag:
<li>First li</li><
li>Second li</li>
)
The gaps are caused by the whitespace between the <li></li> tags.
Try <li>...</li><li>...</li> as a comparison.
Anyways, avoid this with display:block and using float:left
This is a great post explaining what is happening and the work arounds that have already been mentioned by the previous answers.
http://css-tricks.com/fighting-the-space-between-inline-block-elements/
You also have a little trouble with your css selector names, you actually only need one class and you can take advantage of the nature of CSS to do the rest.
.header {
background-color: #c1c1c1;
color: #666666;
list-style: none;
padding: 10px 10px 10px 0;
margin: 0 0 10px 0;
}
Now target all the 'li' tags that are children of the .header class
.header li {
display: inline;
}
Now target all the 'a' tags that are children of the .header class (these happen to be inside your 'li' tags)
.header a {
/* etc */
}

CSS cascading order within one stylesheet

I'm trying to figure out if I'm totally mis-understanding something here.
I have a menu and submenu (dropdown style using only CSS, no javascript) and for some reason the sub-menu styles (defined by .submenu li a) always shows up at the same style as the parent a (defined by #menu li a) even though the submenu CSS styles show up AFTER the top menu styles.
Am I mis-understanding CSS rules? I thought features defined LATER and at a lower level override the top level (for example, inline style will always override style.css styles). I'm attaching a screenshot off Firebug that shows crossing out the font sizes defined on line 275 in favour of styles defined at line 225, on the parent DOM objects.
My DOM looks like this to simplify it:
<ul id="menu">
<li>
about us
<ul class="submenu">
<li>
Testimonials
</li>
</ul>
</li>
<li>
listings
</li>
<li>
MLS® Search
</li>
<li>
City Guide
<ul class="submenu">
<li>
The West End
</li>
<li>
Coal Harbour
</li>
</ul>
</li>
<li>
blog
</li>
</ul>
And my CSS looks like this.
#menu li a:link, #menu li a:visited {
color:#333;
text-decoration:none;
font-size:16px;
font-weight: bold;
padding-bottom: 3px;
text-transform: uppercase;
}
#menu li a:hover {
color:#333;
background-image: url('../images/pink_dots.png');
background-position: bottom left;
background-repeat: repeat-x;
}
#menu li a:active {
position:relative;
color:#333;
}
.submenu {
position:absolute;
left: -9999px;
display: block;
background-color: #DD2D77;
padding:0px 0px 0px 0px;
margin: 0px;
top:16px;
z-index: 20;
}
#menu li:hover .submenu {
left: -5px;
}
.submenu li {
text-align: left !important;
margin:0px !important;
padding: 2px 0px 3px 0px !important;
position:relative;
display: block;
width: auto;
float: none;
text-align: left;
}
.submenu li:hover {
}
.submenu li a:link, .submenu li a:visited {
color:#fff;
text-align: left;
font-size:12px;
font-weight: normal;
margin: 0px;
white-space:nowrap;
display: block;
padding:3px 7px 5px 7px !important;
min-width: auto;
zoom: normal;
}
.submenu li a:hover, .submenu li a:active {
color:#fff !important;
background-image: none !important;
background-color: #73AA12;
}
The id selector has more specificity than your other selector.
Increase the specificity, which is favoured over !important.
Yes; you are misunderstanding how CSS works.
http://www.htmldog.com/guides/cssadvanced/specificity/
The order in which you define rules in the CSS file means nothing. The selector determines which rules apply and when.
The axiom behind CSS is - the more specific your selectors are, the more precedence they take over less specific ones.
This is how anchor styles work for instance. To show an underline only on hover:
a:hover
{
text-decoration: underline;
}
a
{
text-decoration: none;
}
Even though the less specific rule is defined later, the more specific rule (an anchor tag that is also mouse hovered) overrules the more general rule.
You're correct in saying that rules declared later in the cascade take precedence but only if they are at an equal or higher specificity.
Your first style #main li a uses an ID as the context whereas the second style .submenu li a uses a CLASS as the context. An ID holds more specificity than the CLASS, so it overrides the .submenu.
You need to read up a bit on CSS Specificity:
http://www.htmldog.com/guides/cssadvanced/specificity/
http://coding.smashingmagazine.com/2007/07/27/css-specificity-things-you-should-know/
http://coding.smashingmagazine.com/2010/04/07/css-specificity-and-inheritance/
http://css-tricks.com/specifics-on-css-specificity/
You could do a quick fix and declare #main > li a - which will only apply to anchors inside list items that are direct descendants of the #main element. Then, your .submenu li a rule will be applied to your submenu items.
Here is a specificity calculator that you can add as a bookmark in your browser: http://www.westciv.com/mri/
When you click it, it will open a window that you can either type a selector into, or you can click an element on the page and it will suggest the selector that you should use (showing you the path it took to get there).
It may help as a learning tool.