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.
Related
so I never formally learned how make a nav menu using specific names for the ul and the child li. I created a menu on codepen which is finished. Except I need to give all the css a specific name.
So right now for example I have.
<ul id="nav">
<li>
Small
<ul>
<li>link here</li>
</ul>
</li>
</ul>
example css
#nav {
text-align: left;
display: inline;
margin: 0;
text-align: center;
padding: 15px 0px 15px 0px;
list-style: none;
-webkit-box-shadow: 5px 2px 7px rgba(0, 0, 0, 0.15);
-moz-box-shadow: 5px 2px 7px rgba(0, 0, 0, 0.15);
box-shadow: 5px 2px 7px rgba(0, 0, 0, 0.15);
}
ul li {
width:72px;
font: bold 12px/18px sans-serif;
display: inline-block;
margin-right: -4px;
position: relative;
padding: 15px 0px 15px 0px;
background: #fff;
cursor: pointer;
}
How would I go about adding #nav before each css item. So if I put #nav li {code} in the css and put id="#nav" in the < li > then the code doesn't work anymore.
TLDT: I want each part of my css to have a specific id so the ul li code doesn't effect the other parts of my website.
An additional answer to MathiasaurusRex's answer. It seems to me like you are struggling with understanding how to write selectors properly. The below might help.
Assuming this HTML structure...
<ul id="nav">
<li class="home">Home</li>
<li>About</li>
<li>Contact</li>
</ul>
Then the following CSS Selectors ALL target the exact same element.
#nav { /*code*/ }
ul { /*code*/ }
ul#nav { /*code*/ }
All three of the above target the same element, but with different specificity. Especially when used in chain with other selectors... For example...
ul li { /* code */ }
The code in the above selector applies to ANY <li> element that is a descendant of ANY <ul> element.
#nav li { /* code */ }
The code in the above selector applies to ANY <li> element that is a descendant of ANY element that ALSO has an ID of "nav". In the above HTML sample, that also happens to be the <ul> element.
ul#nav li { /* code */ }
The above selector is essentially the same as the second selector above it, but it adds further specificity in that the ID HAS to be on a <ul> element. If the ID "nav" was on a different element the code would not apply.
Also note that ID's should really only be used ONCE per page. If you have something that may repeat, then use a class instead. class="name" and .name
Keep #nav on the ul, and use the CSS selector: #nav > li which will select any immediate li children of #nav and ignore anything beyond that.
http://codepen.io/anon/pen/jubJI
ids are used as unique selectors - that is, there can be only one of any given id per page. For this, you should instead use give them a class with class='className' and apply styling to them with .className {Code;}.
I have one CSS file which I found it in one website, but I have a confusion about it. The code is:
ul li a {
background-color: FFFFFF;
border: 1px solid 86B3E6;
color: 2F62AC;
display: block;
font-size: 17px;
font-weight: bold;
margin-bottom: -1px;
padding: 12px 10px;
text-decoration: none;
direction:rtl;
}
So, what I am styling here? as I know, it should be (( a )) tag, so if I add
display:inline-block;
to (( ul )) tag styling which I found here (( UL display: block )) it should work, but unfortunately I failed to make it.
Maybe I will have one more question later, but for timing i want to understand the code and correct my information.
Best regards and thanks in advance,
Gharib
edit:
I want to use both inline-block and block, and here is my full code:
ul.ablock {
display: block;
}
ul.aninline {
display: inline-block;
float: right;
width: 50%;
}
a {
background-color: FFFFFF;
border: 1px solid 86B3E6;
color: 2F62AC;
display: block;
font-size: 17px;
font-weight: bold;
margin-bottom: -1px;
padding: 12px 10px;
text-decoration: none;
direction:rtl;
-webkit-border-top-left-radius: 8px;
-webkit-border-top-right-radius: 8px;
-webkit-border-bottom-left-radius: 8px;
-webkit-border-bottom-right-radius: 8px;
}
a:active, a:hover {
background-color:2F62AC;
color:FFFFFF;
}
and the html is something like:
<ul class="ablock">
<li><div align="center">Find</div></li>
</ul>
<ul class="aninline">
<li><div align="center">Back</div></li>
<li><div align="center">Next</div></li>
</ul>
The above selector will target all a elements which are nested under li which is further nested under ul, that's a general element selector, which will target all the a element which falls in that pattern. It is better to be specific and use a class instead, like
ul.class_name li a {
/* Styles goes here */
}
The above selector will only target a elements which are nested under li which are further nested under an ul element having a class called .class_name
As you commented, it seems like you want to target a ul element, now instead of using something like
ul {
/* Styles goes here */
}
Will apply the styles to all the ul elements, instead, be specific, either assign a class to your ul element and use a selector like
ul.class_name {
/* Styles goes here */
}
Or you can also use a nested selector like
div.wrapper_div ul {
/* Styles goes here */
}
Here, in the above selector we are selecting all the ul which are nested under .wrapper_div.
Just a side note, you seem to be confused so don't wanna confuse you more, so don't read this, you can simply ignore, but if you want to learn, just make sure that, if you are targeting ul, make sure you use > selector which will select direct child, as users tend to nest a ul element under li, say for example dropdown menu, this is common, so it is better to use a selector like
div.class_name > ul { /* Selects first level ul elements */
/* Styles goes here */
}
ul > li > ul { /* Selects nested level ul elements */
/* Styles goes here */
}
You are targeting the <a> element here. The reason for the ul and li is that, you're targeting a specific nesting of a. Namely, you are targeting a <a> that is a descendant of <li> that is in turn, a descendant of a <ul>.
If you want to add dispay: inline-block to all <ul> elements then above the rule for ul li a you want to add:
ul { display: inline-block; }
I have a nested li and they have specific classes. I am having issues with the nested classes. Despite the specific class, the styling is that of the class of the parent:
<ul>
<li class="navtitle-current">ONE
<ul>
<li class="navtitle-current">TWO</li>
<li class="navtitle">THREE</li>
</ul>
</li>
</ul>
.navtitle {
font-weight: none;
}
.navtitle a{
background-color:white;
color: gray;
}
.navtitle a:hover,
.navtitle:hover{
background-color:white;
color: black;
}
.navtitle-current {
font-weight: none;
}
.navtitle-current a{
background-color:white;
color: black;
}
.navtitle-current a:hover,
.navtitle-current:hover{
background-color:white;
color: black;
}
What I want to happen is that ONE needs to be in black, TWO in black and THREE in gray. However, all the links are black.
I was under the impression that if I explicitly have a class, I should not have any such issues. Does anyone have any thoughts?
All help is appreciated.
Note: I realize the CSS blocks are not in . I just put the code on here for the sake of showing what I have.
Because .navtitle-current is higher level than .navtitle, the links are inheriting the .navtitle-current a styles. If you want to style links inside that, you need to be more specific with your tags. Change .navtitle a to .navtitle-current .navtitle a and it should work.
Yet another way to go about this:
jsFiddle
.navtitle-current .navtitle a {
background-color:white;
color: gray;
}
It may be just a personal preference, but when possible I try to avoid chaining ul li ul li etc. I find it a bit more readable to use the class names.
The problem is selector specificity - your second to last declaration has the same exact same weight and origin as the class defining the gray-colored text - .navtitle a - and due to the nature of the cascade, the latter rule specified will win
From the 2.1 Spec, Specificity:
Finally, sort by order specified: if two declarations have the same weight, origin and specificity, the latter specified wins. Declarations in imported style sheets are considered to be before any declarations in the style sheet itself.
To overcome this, just increase the specificity of .navtitle a by including li before the class, e.g.
li.navtitle a {
background-color: gray;
color: gray;
}
Example
You could do it more clever:
<div class="titles">
<ul>
<li class="current">ONE
<ul>
<li class="current">TWO</li>
<li>THREE</li>
</ul>
</li>
</ul>
</div>
.titles ul li {...}
.titles ul li.current {...}
.titles ul li.current ul li {...}
.titles ul li.current ul li.current {...}
regards,
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
I can't get my drop down menu (sub-menu) to stop overlapping the text. Below is my HTML + CSS.
<ul class="top-menu">
<li><a href="index.html" >Events </a></li>
<li>
Store
<ul>
<li><a href="index-2.html" >Imagination CD</a></li>
<li><a href="index-2.html" >Total Relax</a></li>
<li><a href="index-2.html" >Super Study</a></li>
</ul>
</li>
</li>
<li>About Us</li>
<li>Contact</li>
</ul>
.top-menu {
position: absolute;
padding: 32px 00 0 10px;
height: 85px;
}
.top-menu li{
padding:0 24px 0 0;
}
.top-menu li, .top-menu li a{
display:block;
float:left;
}
.top-menu ul, .top-menu ul a{
position: absolute;
display: none;
z-index:999px;
line-height: 30px;
top: 12px;
}
.top-menu li a{
padding:0 0 0 30px;
color:#4d3925;
font-size:25px;
line-height:26px;
text-decoration:none;
}
.top-menu a:hover, .top-menu .active {
color:#f29869;
}
.top-menu li:hover ul a, .top-menu li:hover ul {
position: abolute;
display: block;
padding: 32px 0 0 14px;
font-size: 16px;
line-height: 30px;
z-index: 999px;
}
reference menu: http://www.nicoheins.com/lux/
There are a number of issues with this dropdown. However, the one that's causing this particular problem is the attribute position:absolute; in your selector .top-menu ul, .top-menu ul a. Once you get rid of that, your links will no longer stack on top of eachother.
But you'll still need to do more work to get your menu looking fresh.
Not to plug my own work, but I've got a pretty decent dropdown (I think, at least) that you can use hosted over at Github. Check it out here. If you don't want the fade or arrows, you can just remove those, then apply your own style. The rest should work as you want it to.
Edits to fix other issues:
Again, the original question just asks to solve one of the problems I noted with this dropdown. Another is the fact that your submenu ul is pushing the parents lis to the right. You can fix this by applying this styling:
.top-menu > li {
position: relative;
}
.top-menu li ul {
position: absolute;
}
Another is the fact that your all of your lis are styled to float:left;. You only want the top level lis to be styled in this way. This is cased by this section:
.top-menu li, .top-menu li a{
display:block;
float:left;
}
Changing this to
.top-menu > li, .top-menu > li > a{
display:block;
float:left;
}
will fix that, but then you'll need to re-apply the display:block; to the submenu as.
I imagine your next concern would be regarding the huge spacing between the submenu as. This is because you're targeting them with this code:
.top-menu li:hover ul a, .top-menu li:hover ul {
position: abolute;
display: block;
padding: 32px 0 0 14px;
font-size: 16px;
z-index: 999px;
}
That padding-top is quite large! Be sure your selectors are only selecting what you want, or you'll end up getting strange behavior like this. This is particular important when you're working with something like a dropdown, which has lis inside of lis, and they need to be styled completely different from one another.
For a good overview of selectors, check out this page.
A functional version of this is here. Please note that I tried to change the original css as little as possible. I think this has restricted my ability to write the best possible dropdown that I think I can write. But this does work!
Here's a JSFiddle with rewritten code that works completely and cleanly!.