How to use CSS Class and ID selectors - html

I am new to css and i have been trying to come up with a nice looking homepage but got confused with the right selectors to use.
I have designed the buttons very well using unordered lists but the lists in the other content also inherit the formats of the buttons.
how should i assign a one class or two to the unorderd button list?
many thanks!
i want the class to have the following code.
here is the code i used for the buttons.
/* button styling */
ul {
list-style: none;
margin: 0;
}
li {
float: left;
}
a {
background: #404853;
background: linear-gradient(#687587, #404853);
border-left: 1px solid rgba(0, 0, 0, 0.2);
border-right: 1px solid rgba(255, 255, 255, 0.1);
color: #fff;
display: block;
font-size: 11px;
font-weight: bold;
padding: 0 20px;
line-height: 38px;
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.6);
text-transform: uppercase;
}
a:hover {
background: #454d59;
box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.4);
border-right: 1px solid rgba(0, 0, 0, 0.2);
color: #d0d2d5;
}
li:first-child a {
border-left: none;
border-radius: 4px 0 0 4px;
}
li:last-child a {
border-right: none;
border-radius: 0 4px 4px 0;
}

You should scope your selector to make them more explicit.
A good way is, if your ul is in a header element:
header ul {}
header ul li {}
Or also, if it is in some element with id #navigation:
#navigation ul {}
#navigation ul li {}
This will affect all ul elements inside header or #navigation.
Another way is to add an ID to your unsorted list in your html:
<ul id="navigation">
<li></li>
</ul>
In this case you could use just that ID in your selector:
ul#navigation {}
ul#navigation li {}
Or just:
#navigation {}
#navigation li {}

Ok, so as I think you know, you are using very broad selectors here - which is of course the reason why all of your <li> tags are appearing the same, site-wide.
As you say, classes, or even ids could be used to help here.
Although there is some debate over whether you should use ids at all in CSS, I will show you examples of both.
IDs:
First rule of IDs: IDs must be unique to the page!.
This doesn't mean you can't reuse the ID on other pages within your site, but you must ensure that, per page load, your IDs are unique. In CSS selectors, an ID selector is decorated with a #.
Example:
HTML:
<ul id="myList">
<li>Text 1</li>
<li>Text 2</li>
<li>Text 3</li>
</ul>
CSS:
/* This selector will select the element with the "myList" ID,
in this case, the <ul> tag in the above example.
Keep in mind, it isn't selecting the <li> tags */
#myList
{
float: left;
}
/* The following style selects all
<li> tags WITHIN any element with the "myList" ID */
#myList li
{
font-weight:bold;
}
Classes:
Classes are, for the most part, the same as IDs but do not have to be unique to a certain page. Classes are decorated with a . (period).
HTML:
<ul class="myList">
<li>Text 1</li>
<li class="selected">Text 2</li>
<li>Text 3</li>
</ul>
CSS:
/* same as before, but now we are targeting a class */
.myList
{
float: left;
}
/* as you can see, there is no difference in the usage here. */
.myList li
{
color:blue;
}
/* if you prefix the class or ID name with an element tag
(in this case, li for the <li> element), then the selector will
only select elements with the specified ID/Class, that is of
that element type.
In this example, the following selector means:
"Select all <li> tags that have the class 'selected'"
This is useful, say, in a navigation bar. */
li.selected
{
/* this will overwrite the
color attribute defined in the
".myList li" style, in this case,
to highlight that the selected item is green */
color:green;
}
JSFiddle: (Very useful site)http://jsfiddle.net/fSsdf/
I hope this helps!

HTML:
<ul class="class1">
<li>Content</li>
<li>Content</li>
</ul>
CSS:
ul.class1{
float: left;
}

Related

Stop pushing elements on hover [duplicate]

I created a horizontal menu using a HTML lists and CSS. Everything works as it should except when you hover over the links. You see, I created a bold hover state for the links, and now the menu links shift because of the bold size difference.
I encounter the same problem as this SitePoint post. However, the post does not have proper solution. I've searched everywhere for a solution and can't find one.
Surely I can't be the only one trying to do this.
Does anyone have any ideas?
P.S: I don't know the width of the text in menu items so I cannot just set the width of the li items.
.nav { margin: 0; padding: 0; }
.nav li {
list-style: none;
display: inline;
border-left: #ffffff 1px solid;
}
.nav li a:link, .nav li a:visited {
text-decoration: none;
color: #000;
margin-left: 8px;
margin-right: 5px;
}
.nav li a:hover{
text-decoration: none;
font-weight: bold;
}
.nav li.first { border: none; }
<ul class="nav">
<li class="first">item 0</li>
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
<li>item 4</li>
</ul>
Pre-set the width by using an invisible pseudo-element which has the same content and styling as the parent hover style. Use a data attribute, like title, as the source for content.
li {
display: inline-block;
font-size: 0;
}
li a {
display:inline-block;
text-align:center;
font: normal 16px Arial;
text-transform: uppercase;
}
a:hover {
font-weight:bold;
}
/* SOLUTION */
/* The pseudo element has the same content and hover style, so it pre-sets the width of the element and visibility: hidden hides the pseudo element from actual view. */
a::before {
display: block;
content: attr(title);
font-weight: bold;
height: 0;
overflow: hidden;
visibility: hidden;
}
<ul>
<li>height</li>
<li>icon</li>
<li>left</li>
<li>letter-spacing</li>
<li>line-height</li>
</ul>
A compromised solution is to fake bold with text-shadow, e.g:
text-shadow: 0 0 0.01px black;
For better comparison I created these examples:
a, li {
color: black;
text-decoration: none;
font: 18px sans-serif;
letter-spacing: 0.03em;
}
li {
display: inline-block;
margin-right: 20px;
color: gray;
font-size: 0.7em;
}
.bold-x1 a.hover:hover,
.bold-x1 a:not(.hover) {
text-shadow: 0 0 .01px black;
}
.bold-x2 a.hover:hover,
.bold-x2 a:not(.hover){
text-shadow: 0 0 .01px black, 0 0 .01px black;
}
.bold-x3 a.hover:hover,
.bold-x3 a:not(.hover){
text-shadow: 0 0 .01px black, 0 0 .01px black, 0 0 .01px black;
}
.bold-native a.hover:hover,
.bold-native a:not(.hover){
font-weight: bold;
}
.bold-native li:nth-child(4),
.bold-native li:nth-child(5){
margin-left: -6px;
letter-spacing: 0.01em;
}
<ul class="bold-x1">
<li><a class="hover" href="#">Home</a></li>
<li><a class="hover" href="#">Products</a></li>
<li>Contact</li>
<li>About</li>
<li>Bold (text-shadow x1)</li>
</ul>
<ul class="bold-x2">
<li><a class="hover" href="#">Home</a></li>
<li><a class="hover" href="#">Products</a></li>
<li>Contact</li>
<li>About</li>
<li>Extra Bold (text-shadow x2)</li>
</ul>
<ul class="bold-native">
<li><a class="hover" href="#">Home</a></li>
<li><a class="hover" href="#">Products</a></li>
<li>Contact</li>
<li>About</li>
<li>Bold (native)</li>
</ul>
<ul class="bold-x3">
<li><a class="hover" href="#">Home</a></li>
<li><a class="hover" href="#">Products</a></li>
<li>Contact</li>
<li>About</li>
<li>Black (text-shadow x3)</li>
</ul>
Passing to text-shadow really low value for blur-radius will make the blurring effect not so apparent.
In general the more your repeat text-shadow the bolder your text will get but in the same time loosing original shape of the letters.
I should warn you that setting the blur-radius to fractions is not going to render the same in all browsers! Safari for example need bigger values to render it the same way Chrome will do.
Another idea is using letter-spacing
li, a { display: inline-block; }
a {
font-size: 14px;
padding-left: 10px;
padding-right: 10px;
letter-spacing: 0.235px
}
a:hover, a:focus {
font-weight: bold;
letter-spacing: 0
}
<ul>
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
</ul>
If you cannot set the width, then that means the width will change as the text gets bold. There is no way to avoid this, except by compromises such as modifying the padding/margins for each state.
One line in jquery:
$('ul.nav li a').each(function(){
$(this).parent().width($(this).width() + 4);
});
edit:
While this can bring about the solution, one should mention that it does not work in conjunction with the code in the original post. "display:inline" has to be replaced with floating-parameters for a width-setting to be effective and that horizontal menu to work as intended.
CSS3 Solution - Experimental (Fake boldness)
Thought to share a different solution which no one suggested here. There's a property called text-stroke which will be handy for this.
p span:hover {
-webkit-text-stroke: 1px black;
}
<p>Some stuff, <span>hover this,</span> it's cool</p>
Here, I am targeting the text inside of the span tag and we stroke it by a pixel with black which will simulate bold style for that particular text.
Note that this property is not widely supported, as of now (while writing this answer), only Chrome and Firefox seems to support this. For more information on browser support for text-stroke, you can refer to CanIUse.
Just for sharing some extra stuff, you can use -webkit-text-stroke-width: 1px; if you are not looking to set a color for your stroke.
If you don't want to preset the width of the list items, a really good alternative would be to try using a uniwidth font in your list items.
Unlike a monospace font, they're still proportional typefaces -- but they occupy the same size across different font weights. No CSS, JS, or fancy hacks are required to keep the size constant. It's baked right into the typeface.
I think it's a really elegant solution to this common problem.
Here's an example from this excellent article comparing the proportional font IBM Plex Sans to the uniwidth Recursive.
Notice how in the proportional font (IBM Plex Sans), the list items shift as they change size in the bold typeface. With the uniwidth font Recursive, the items become bold on hover but don't change size.
Free uniwidth fonts you can try are:
Recursive
PT Root UI
Golos UI
Grandstander
There are also many non-free options linked to via the aforementioned article.
You could use somehting like
<ul>
<li>Some text<span><br />Some text</span></li>
</ul>
and then in your css just set the span content bold and hide it with visibility: hidden, so that it keeps its dimensions. Then you can adjust margins of the following elements to make it fit properly.
I am not sure if this approach is SEO friendly though.
I just solved the problem with the "shadow" solution.
It seems the most simple and effective.
nav.mainMenu ul li > a:hover, nav.mainMenu ul li.active > a {
text-shadow:0 0 1px white;
}
No need to repeat the shadow three times (result was the same for me).
I use text-shadow solution as some others mentioned here:
text-shadow: 0 0 0.01px;
the difference is that I do not specify shadow color, so this solution is universal for all font colors.
I had a problem similar to yours. I wanted my links to get bold when you hover over them but not only in the menu but also in the text. As you cen guess it would be a real chore figuring out all the different widths. The solution is pretty simple:
Create a box that contains the link text in bold but coloured like your background and but your real link above it. Here's an example from my page:
CSS:
.hypo { font-weight: bold; color: #FFFFE0; position: static; z-index: 0; }
.hyper { position: absolute; z-index: 1; }
Of course you need to replace #FFFFE0 by the background colour of your page. The z-indices don't seem to be necessary but I put them anyway (as the "hypo" element will occur after the "hyper" element in the HTML-Code). Now, to put a link on your page, include the following:
HTML:
You can find foo here<span class="hypo">here</span>
The second "here" will be invisible and hidden below your link. As this is a static box with
your link text in bold, the rest of your text won't shift any longer as it is already shifted before you hover over the link.
I like to use text-shadow instead. Especially because you can use transitions to animate text-shadow.
All you really need is:
a {
transition: text-shadow 1s;
}
a:hover {
text-shadow: 1px 0 black;
}
For a complete navigation check out this jsfiddle:
https://jsfiddle.net/831r3yrb/
Browser support and more info on text-shadow:
http://www.w3schools.com/cssref/css3_pr_text-shadow.asp
An alternative approach would be to "emulate" bold text via text-shadow. This has the bonus (/malus, depending on your case) to work also on font icons.
nav li a:hover {
text-decoration: none;
text-shadow: 0 0 1px; /* "bold" */
}
Kinda hacky, although it saves you from duplicating text (which is useful if it is a lot, as it was in my case).
You can work with the "margin" property:
li a {
margin: 0px 5px 0px 5px;
}
li a:hover {
margin: 0;
font-weight: bold;
}
Just make sure that the left and right margin are big enough so the extra space can contain the bold text. For long words, you might choose different margins.
It's just another workaround but doing the job for me.
I would advice against switching fonts(°) on hover. In this case it's just the menu items moving a bit, but I've seen cases where the complete paragraph gets reformatted because the widening causes an extra word wrap. You don't want to see this happen when the only thing you do is move the cursor; if you don't do anything the page layout should not change.
The shift can also happen when switching between normal and italic. I would try changing colors, or toggle underline if you have room below the text. (underlining should stay clear from the bottom border)
I would be boo'd if I used switching fonts for my Form Design class :-)
(°) The word font is often misused. "Verdana" is a typeface, "Verdana normal" and "Verdana bold" are different fonts of the same typeface.
Not very elegant solution, but "works":
a
{
color: #fff;
}
a:hover
{
text-shadow: -1px 0 #fff, 0 1px #fff, 1px 0 #fff, 0 -1px #fff;
}
ul {
list-style-marker: none;
padding: 0;
}
li {
display: inline-block;
}
li + li {
margin-left: 1em;
}
a {
display: block;
position: relative;
text-align: center;
}
a:before, a:after {
content: attr(aria-label);
text-decoration: inherit;
}
a:before {
font-weight: bold;
visibility: hidden;
}
a:after {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
}
a:hover:before {
visibility: visible;
}
a:hover:after {
display: none;
}
<ul>
<li>
</li><li>
</li><li>
</li><li>
</li><li>
</li>
</ul>
Use letter-spacing with text-shadow:
a {
letter-spacing: .1em;
}
a:hover {
text-shadow: 0 0 .9px #color, 0 0 .9px #color, 0 0 .9px #color;
}
I solved this with few lines of javascript.
$('a.menu_item').each(function() {
let width = $(this).width();
$(this).css('width',width + 'px');
});
Seeing a lot of great but very involved answers here. There's really not a need for resetting widths, adding hidden elements, reworking elements for different layout declarations, etc. The simplest solution is just to account for the increase in size from the bold text by adjusting the font size in the hover declaration to a slightly smaller size. Like for example font-size: .985em from the normal 1em declaration, which allows the text to bold when hovered but also maintain the original size appearance.
This is the solution I prefer. It requires a bit of JS but you don't need your title property to be the exact same and your CSS can remain very simple.
$('ul a').each(function() {
$(this).css({
'padding-left': 0,
'padding-right': 0,
'width': $(this).outerWidth()
});
});
li, a { display: inline-block; }
a {
padding-left: 10px;
padding-right: 10px;
text-align: center; /* optional, smoother */
}
a:hover { font-weight: bold; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul>
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
</ul>
What about this? A javascript - CSS3 free solution.
http://jsfiddle.net/u1aks77x/1/
ul{}
li{float:left; list-style-type:none; }
a{position:relative; padding-right: 10px; text-decoration:none;}
a > .l1{}
a:hover > .l1{visibility:hidden;}
a:hover > .l2{display:inline;}
a > .l2{position: absolute; left:0; font-weight:bold; display:none;}
<ul>
<li><span class="l1">Home</span><span class="l2">Home</span></li>
<li><span class="l1">Contact</span><span class="l2">Contact</span></li>
<li><span class="l1">Sitemap</span><span class="l2">Sitemap</span></li>
</ul>
I've combined a bunch of the techniques above to provide something that doesn't totally suck with js turned off and is even better with a bit of jQuery. Now that browsers support for subpixel letter-spacing is improving, it's really nice to use it.
jQuery(document).ready(function($) {
$('.nav a').each(function(){
$(this).clone().addClass('hoverclone').fadeTo(0,0).insertAfter($(this));
var regular = $(this);
var hoverclone = $(this).next('.hoverclone');
regular.parent().not('.current_page_item').hover(function(){
regular.filter(':not(:animated)').fadeTo(200,0);
hoverclone.fadeTo(150,1);
}, function(){
regular.fadeTo(150,1);
hoverclone.filter(':not(:animated)').fadeTo(250,0);
});
});
});
ul {
font:normal 20px Arial;
text-align: center;
}
li, a {
display:inline-block;
text-align:center;
}
a {
padding:4px 8px;
text-decoration:none;
color: #555;
}
.nav a {
letter-spacing: 0.53px; /* adjust this value per font */
}
.nav .current_page_item a,
.nav a:hover {
font-weight: bold;
letter-spacing: 0px;
}
.nav li {
position: relative;
}
.nav a.hoverclone {
position: absolute;
top:0;
left: 0;
white-space: nowrap;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<ul class="nav">
<li>Item 1</li>
<li>Item 2</li>
<li class="current_page_item">Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
</ul>
It's better to use a::before instead a::after like this:
.breadcrumb {
margin: 0;
padding: 0;
list-style: none;
overflow: hidden;
}
.breadcrumb li,
.breadcrumb li a {
display: inline-block;
}
.breadcrumb li:not(:last-child)::after {
content: '>'; /* or anything else */
display: inline-block;
}
.breadcrumb a:hover {
font-weight: bold;
}
.breadcrumb a::before {
display: block;
content: attr(data-label);
font-weight: bold;
height: 0;
overflow: hidden;
visibility: hidden;
}
<ul class="breadcrumb">
<li><a data-label="one" href="https://www.google.fr/" target="_blank">one</a></li>
<li><a data-label="two" href="https://duckduckgo.com/" target="_blank">two</a></li>
<li><a data-label="three" href="#">three</a></li>
</ul>
For more details: https://jsfiddle.net/r25foavy/
I fixed menu when hover bold success. It support responsive, this is my code:
(function ($) {
'use strict';
$(document).ready(function () {
customWidthMenu();
});
$(window).resize(function () {
customWidthMenu();
});
function customWidthMenu() {
$('ul.nav li a').each(function() {
$(this).removeAttr('style');
var this = $(this);
var width = this.innerWidth();
this.css({'width': width + 12});
});
}})(jQuery);
I can advise you two variants
The first option: is you set the width of each list item to %
Here is a simple example
<ul>
<li>First Item</li>
<li>Second Item</li>
<li>Third Item</li>
<li>Fourth Item</li>
</ul>
li {
list-style-type: none;
display: inline-block;
width: 24%;
}
a {
text-decoration: none;
color: #333;
font-size: 1.4em;
background: #A5C77F;
display: block;
padding: 10px 15px;
margin: 10px 0;
border-right: 1px solid whitesmoke;
transition: font-weight .3s;
}
a:hover {
font-weight: bold;
}
The second option: is to use a text-shadow on the active element
text-shadow: 0 0 .65px #333, 0 0 .65px #333;
But I recommend using the first option, that is, specifying the width as a percentage for each element, since text-shadow does not always work in mobile browsers
If you're not averse to using Javascript, you can set the proper width once the page is shown. Here's how I did it (using Prototype):
$$('ul.nav li').each(this.setProperWidth);
setProperWidth: function(li)
{
// Prototype's getWidth() includes padding, so we
// have to subtract that when we set the width.
var paddingLeft = li.getStyle('padding-left'),
paddingRight = li.getStyle('padding-right');
// Cut out the 'px' at the end of each padding
paddingLeft = paddingLeft.substring(0,paddingLeft.length-2);
paddingRight = paddingRight.substring(0,paddingRight.length-2);
// Make the li bold, set the width, then unbold it
li.setStyle({ fontWeight: 'bold' });
li.setStyle({ width: (li.getWidth() - paddingLeft - paddingRight) + 'px'});
li.setStyle({ fontWeight: 'normal', textAlign: 'center' });
}
I really can't stand it when someone tells you not to do something that way when there's a simple solution to the problem. I'm not sure about li elements, but I just fixed the same issue. I have a menu consisting of div tags.
Just set the div tag to be "display: inline-block". Inline so they sit next to each other and block to that you can set a width. Just set the width wide enough to accomodate for the bolded text and have the text center aligned.
(Note: It seems to be stripping out my html [below], but each menu item had a div tag wrapped around it with the corrasponding ID and the class name SearchBar_Cateogory. ie: <div id="ROS_SearchSermons" class="SearchBar_Category">
HTML
(I had anchor tags wrapped around each menu item, but i wasn't able to submit them as a new user)
<div id="ROS_SearchSermons" class="SearchBar_Cateogry bold">Sermons</div>|
<div id="ROS_SearchIllustrations" class="SearchBar_Cateogry">Illustrations</div>|
<div id="ROS_SearchVideos" class="SearchBar_Cateogry">Videos</div>|
<div id="ROS_SearchPowerPoints" class="SearchBar_Cateogry">PowerPoints</div>|
<div id="ROS_SearchScripture" class="SearchBar_Cateogry">Scripture</div>|
CSS:
#ROS_SearchSermons { width: 75px; }
#ROS_SearchIllustrations { width: 90px; }
#ROS_SearchVideos { width: 55px; }
#ROS_SearchPowerPoints { width: 90px; }
#ROS_SearchScripture { width: 70px; }
.SearchBar_Cateogry
{
display: inline-block;
text-align:center;
}
try this:
.nav {
font-family: monospace;
}
You can try the negative margins too if the bold text is wider than the regular. (not always)
So the idea is to use classes instead to style the :hover state.
jQuery:
$(".nav-main .navbar-collapse > ul > li > a").hover(function() {
var originalWidth = $(this).outerWidth();
$(this).parent().addClass("hover");
$(this).css({
"margin-left": -(($(this).outerWidth() - originalWidth) / 2),
"margin-right": -(($(this).outerWidth() - originalWidth) / 2)
});
},
function() {
$(this).removeAttr("style");
$(this).parent().removeClass("hover");
});
CSS:
ul > li > a {
font-style: normal;
}
ul > li > a.hover {
font-style: bold;
}
I hope I could help!

Add id name to each part of the css when making a navigation bar

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;}.

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

CSS: Class of first menu layer applied on submenu

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

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 */
}