Use CSS class in span to set current menu state? - css

I'm learning CSS and html and am stuck on retaining the look of the hover/active state after an item has been clicked. I've looked at several posts on this site and haven't been able to apply the lesson to my application. I also found a solution here http://www.456bereastreet.com/archive/200503/setting_the_current_menu_state_with_css/ but it didn't work for me (I'll assume it's my fault).
Another source suggested using a span class which is what I'm currently trying. I want to have the same hover color (#fff), weight (bold), and background image in use when a menu item is selected to show the user exactly where they are (this is in the secondary sidebar nav and comes in to use on those pages where the main nav has a dropdown with multiple otions). The only characteristic that's working for me is the bold text. You can see the work in progress here:
http://www.mentalwarddesign.net/dynamec/About/index.html
I'm assuming the class I've created in the span is being overridden, but I'm at a loss as to the remedy. Any and all help would be greatly appreciated.
Following is the code for the li and then the corresponding CSS. Thanks in advance!
<ul class="nav">
<span class="chosen"><li>What We Do</li></span>
<li>How It Started</li>
<li>Who We Are</li>
<li>What We Know</li>
</ul>
.chosen {
font-weight: bold;
color: #ffffff;
background-image: url(../imgGlobal/bulletRight.jpg);
background-repeat: no-repeat;
display: block;
padding-left: -12px;
background-position: 168px;
}
.content ul, .content ol {
padding: 0 15px 15px 40px;
background-color: #fff;
}
ul.nav {
list-style: none;
}
ul.nav li {
border-bottom-width: 1px;
border-bottom-style: solid;
border-bottom-color: #464646;
height: 50px;
background-color: #000;
}
ul.nav a, ul.nav a:visited {
display: block;
width: 160px;
text-decoration: none;
padding-top: 12px;
padding-right: 5px;
padding-left: 15px;
}
ul.nav a:hover, ul.nav a:active, ul.nav a:focus {
color: #ffffff;
font-weight: bold;
height: 38px;
background-image: url(../imgGlobal/bulletRight.jpg);
background-repeat: no-repeat;
background-position: 168px;
}

Ed, the CSS selector :active means "Being activated (e.g. by being clicked on)", not "Having an href attribute that resolves to the URL of the current page". You can use server-side logic to insert a class=”chosen” or similar. E.g:
<li class="chosen">What We Do</li>
And, CSS style: ul.nav li.chosen a { }
There is another way to do it as mentioned on the tutorial link you gave, however it is not a good example.

Well first of all, you cannot wrap an li inside of a span. The only direct descendent of a ul is a li. You can put the class chosen directly on to the li and it works just fine.
<ul class="nav">
<li class="chosen">What We Do</li>
<li>How It Started</li>
<li>Who We Are</li>
<li>What We Know</li>
</ul>

Put the chosen class in the li element itself. Drop the span altogether.
EDIT:
Sorry, in the a element, i meant to say.

A span is a tag, a class is just an identifier. They don't really have anything to do with one another except a class can be used to apply a style to a span but that's true of any tag.
In your case you're trying to put a span (an inline element) around an li (a block level element). In HTML inline elements should not contain block elements.
You should be able to just do it like this: EDIT fixed based on the actual CSS
<li>What We Do</li>

Related

Why does selecting multiple elements CSS work differently? [duplicate]

This question already has answers here:
Understanding CSS selector priority / specificity
(4 answers)
Closed 3 years ago.
I was trying to create a responsive menu but selecting a specific element worked out differently.
For example, when I selected "nav ul li" for list styles in the default size and selected "ul li" for list style in the breakpoint, it didn't work as I intended.
It was fixed when I selected "ul li" for both the default size and the breakpoint but I don't know why it fixed the issue because as far as I know, selecting "nav ul li" and "ul li" are the same thing. Could somebody help me with this?
nav {
width: 100%;
background-color: darkblue;
}
ul {
width: 80%;
margin: 0 auto;
padding: 0;
}
nav ul li {
list-style-type: none;
display: inline-block;
padding: 20px;
}
ul li:hover {
background-color: orange;
}
ul li a {
color: #ffffff;
text-decoration: none;
}
.toggle {
width: 100%;
padding: 10px 20px;
background-color: #001f44;
text-align: right;
box-sizing: border-box;
color: #ffffff;
font-size: 30px;
/* to hide toggle */
display: none;
}
/* Break Point for the toggle */
#media screen and (max-width:768px) {
.toggle {
display: block;
}
ul {
width: 100%;
}
ul li {
display: block;
text-align: center;
}
}
<div class="toggle">
<i class="fa fa-bars"></i>
</div>
<nav>
<ul>
<li>Home</li>
<li>About</li>
<li>Portfolio</li>
<li>Resume</li>
</ul>
</nav>
You are running into specificity issues. In CSS, if two different rules target the same element with same attributes, the rule with the more specific selector will win and cancel out the less specific rule.
Reading: https://developer.mozilla.org/en-US/docs/Web/CSS/Specificity
nav ul li {/* more specific rule wins */
color: blue;
}
ul li {
color: red;
}
<nav>
<ul>
<li>The first list example</li>
</ul>
</nav>
<nav>
<ul>
<li>The second list example</li>
</ul>
</nav>
What is happing is that you are not overriding your selection in the media query.
For instance lets say you got:
CSS:
p a{
color: red
}
#media screen and (max-width:768px) {
a {
color: blue;
}
}
html:
<p> <a>Some Url </a> </p>
The media query wont override the selection for is not as specific as the prior selection.
CSS is about priorities for the more specific the higher the priority of style.
So as:
p a { some style} is more specific than a {some style} then the priority stands for the first one.
In your example, ul li is less specific than nav ul li, thats why you are not overriding the style with the media query.
Hope this answer your question.
Go to w3schools.com for CSS selection rules.
CSS is easy to start writing and really hard to maintain.
One approach to simplify maintainability and avoid specificity conflicts is BEM (Block, Element, Modifier) in which every element has a class and that class describes the element as either:
a Block
a Block Element
a Modified Block
a Modified Block Element
Eg.
<nav class="navigation">
<ul class="navigation__list">
<li class="navigation__list-item">The first list example</li>
</ul>
</nav>
<nav class="navigation">
<ul class="navigation__list">
<li class="navigation__list-item">The second list example</li>
</ul>
</nav>
This will help you entirely avoid any specificity conflicts.
N.B.
BEM is just one approach to writing CSS. Others which similarly seek to simplify maintainability and extendability are OOCSS and SMACSS.
You will find on the web nearly a decade's worth of blog posts and tutorials on any of these approaches to writing CSS.

How to color specifics parts (letters) of menu?

Firstly, happy new year to you all! :)
Ok let's get to it. I have 5 items in my menu, and i would like to color "+" part of the word to red, choosing 2nd,3rd and 4th item of menu.
This is what menu looks like right now.
This is how the menu should look like, when its done.
I might have given a bad picture, but i think you can see the red "+" on 2nd,3rd and 4th item of menu.
This is what i've tried so far, but i can't seem to figure out the nth-child method.
#menu li:nth-child(2):first-letter a{color:red;}
Also tried this, but it colors every first letter in all 5 elements :S
#menu .nav > li > a:first-letter{color:red;}
Any help will be appreciated!
Thank you all!
I've managed to find the solution. Not sure if it's the best one, but im posting it below, so that any1 in the future can use it too, if no other solution is found
#menu .nav > li:nth-child(2) > a:first-letter
{
color:red;
}
#menu .nav > li:nth-child(3) > a:first-letter
{
color:red;
}
#menu .nav > li:nth-child(4) > a:first-letter
{
color:red;
}
Use the :not() selector to have all but one selected like this:
#menu{
background: rgb(83,83,83);
width: 100vw;
height: 40px;
}
ul{
text-align: center;
line-height: 40px;
vertical-align: central;
}
ul li{
display: inline-block;
color: white;
list-style: none;
margin-left: 25px;
}
a{
color: white;
display: block;
}
#menu ul li:not(:first-child):not(:last-child) a::first-letter{
color: red;
}
<div id="menu">
<ul>
<li>+option</li>
<li>+option</li>
<li>+option</li>
<li>+option</li>
<li>+option</li>
</ul>
</div>
I know this question already has an accepted answer, but I think there is a semantically better way of doing this. Instead of having the + symbol inside the link's markup, why not add it as a pseudo :before element? Easier to style and not dependent on your markup.
<nav>
<ul>
<li>Domov</li>
<li class="with-symbol">Naravni kamen</li>
<li class="with-symbol">Dekorativni kamen</li>
<li class="with-symbol">Keramika</li>
<li>Kontakt</li>
</ul>
</nav>
And the respective CSS:
.with-symbol:before {
content: '+';
color: red;
}
Then position it with either position: absolute; or negative left margin.
From the docs (https://developer.mozilla.org/en-US/docs/Web/CSS/%3A%3Afirst-letter): A first line has meaning only in a block-container box, therefore the ::first-letter pseudo-element has an effect only on elements with a display value of block, inline-block, table-cell, list-item or table-caption. In all other cases, ::first-letter has no effect. So you will need to add display: block to your anchor tags.
I would also change the selector to:
ul li a:first-letter {
color:red;
}
as you need to select the first letter of the anchor tag, not the list item.
As a side note, it might be a better solution to use a span as suggested above or pseudo elements to insert the plus character and use a class to determine if it should be displayed or no.

Nested padding LESS

I am trying to create indentation for buttons that sit inside of a nested ul li structure.
I can't change the HTML as it is being rendered by a third party system.
The HTML
<ul>
<li><button>Parent</button>
<ul>
<li>
<button> Child</button>
<li><button>Parent</button>
<ul>
<li>
<button> Sibling etc</button>
</li>
</ul>
</li>
</li>
</ul>
</li>
</ul>
The ul and li have no margin or padding so the idea was to simply add padding to the button elements.
The issue is, because of the ul having no margin/padding, the buttons all start from the exact same point and there (no matter how deep they are nested) all have the exact same indentation.
LESS
ul{
li{
button{
padding-left: 25px;
}
ul{
li{
button{
padding-left: 35px;
}
}
}
}
}
I thought of doing something like the above (and account for as many levels as possible) but it would be a nightmare to maintain.
Surely there is a more elegant way to handle this, thoughts?
I don't know why you would want to go as far as to write a mixin for this.
My solution in LESS:
ul ul button {
padding-left: 25px;
}
ul ul ul button {
padding-left: 35px;
}
Would that solve the problem for you?
The resulting CSS would look like this:
ul ul button {
padding-left: 25px;
}
ul ul ul button {
padding-left: 35px;
}
Alright, so I thought of a different solution and looked at the LESS documentation but the underlying problem is that you can't know the number of levels of nesting coming into play beforehand obviously.
Thus you would have to wait for the HTML to be rendered, then read out the level of nesting (e.g. 5 levels) and based on that you could generate the CSS, which I'm afraid wouldn't make much sense and is something to be done in JavaScript.
All of that being said you could use a few variables to ease your writing process in LESS but that's about it. Here for an example:
#padding: 25px;
#addten: 10px;
#selector: ul button;
#selector { #padding; }
ul #selector { #padding + #addten; }
ul ul #selector { #padding + #addten*2; }
ul ul ul #selector { #padding + #addten*3; }
Probably you could also create a mixin for that to add another layer of abstraction but like I said, I wouldn't go thus far.
Hope this helps. =)

(.bmenu:hover li a) VS (.bmenu li a:hover) - difference?

I would like to ask anyone who could help me where is the difference between this two CSS tags.
.bmenu:hover li a{...}
VS
.bmenu li a:hover{...}
Thank you very much for help and sry for my bad english.
Edit 1: I would like to ask for explanation mainly, how do they both work, because in the first case, there is a "li a" behind the :hover. What does it mean please? Thx
To explain this, I'll use this example code:
<div class="bmenu">
<ul>
<li>one</li>
<li>two</li>
</ul>
</div>
if you use .bmenu:hover you're saying you want the CSS to apply when you hover the ENTIRE .bmenu div.
When you say .bmenu li a:hover you are saying that you want to apply the CSS when you hover the a tag within a .bmenu li.
Here's a quick example I made, the top is using the .bmenu:hover method, and the bottom is using the li a:hover method. fiddle here.
In the first case an <a> will apply styles when you hover .bmenu, in the second case - when you hover the <a> itself. Take a look at these two blocks:
.bmenu1, .bmenu2 {
width: 200px;
height: 100px;
margin: 10px;
padding: 40px;
background-color: orange;
}
a {
display: block;
height: 100%;
width: 100%;
background-color: firebrick;
}
.bmenu1:hover a {
background-color: lightblue;
}
.bmenu2 a:hover {
background-color: lightblue;
}
<div class="bmenu1">
</div>
<div class="bmenu2">
</div>

Parent menu and child menu vertical separator (unique, advanced)

I've the following navigation at http://www.roydukkey.com. The navigation is designed to have vertical separators between the parent menu and it's child menu. If you look under the 'Contact' menu-item it looks the way it's designed, however have a look under 'Projects'. The are vertical separators shouldn't exist where there aren't child items against the menu.
How can the proper design be achieved through CSS alone?
This cannot currently be achieved through CSS.
Here is the solution I've chosen:
// Naivagation Vertical Separator Counter
$("#main > ul > li > ul .level-has-sub").each(function(){
$(this).find("> ul > li")
.slice(0, $(this).find("~ li").length + 1)
.addClass("vertical-separator")
});
Them simply style those items for the vertical separator.
It's not possible with pure CSS. You would have to count the number of <li>s in the child <ul>. If you restructured the menu, you could put the separators in the child <ul> instead. Then you would either a) show the separator on the left of every <li> in the child <ul>, or use :first-child to only show it on the first.
Your CSS is minified so I cannot give you line numbers.
In you custom.css file replace
#main li li.level-open:after, #main li li.level-open~li:after {rules}
with
#main li li.level-open:after {rules}
You can't do this precisely, as CSS can't (yet) know the children count of another DOM-element.
CSS4 might be able to do this (ascend to the style's parent) in the near future: http://www.w3.org/TR/selectors4/#subject. This looks interesting too, although not pure CSS; http://demo.idered.pl/jQuery.cssParentSelector/. Maybe you can descend back down again after counting the children of the submenu, but that would be very complex to achieve with the low logical selection methods CSS has.
You could probably best do this in SASS, but then it's not native CSS anymore, and then you might as well just fallback to JavaScript.
Here's an example of how style a style of a parent itself based on how many children it "at least" has;
JSfiddle
HTML
<ul>
<li>
<ul class="submenu">
<li>Contact 1.1</li>
<li>Contact 1.2</li>
<li>Contact 1.3</li>
<li>Contact 1.4</li>
</ul>
</li>
</ul>
<ul>
<li>
<ul class="submenu">
<li>Contact 2.1</li>
<li>Contact 2.1</li>
<li>Contact 2.3</li>
</ul>
</li>
</ul>
CSS
li {
list-style: none;
display: inline-block;
border: 1px dotted red;
padding: 15px;
}
.submenu li {
display: block;
padding: 15px;
border: 0px;
border-top: 1px dotted blue;
}
.submenu li:nth-child(1) {
border: 0px;
}
/* This style only happens if the menu has 4 or more children li's */
.submenu li:first-child:nth-last-child(4),
.submenu li:first-child:nth-last-child(4) ~ li {
border-left: 1px dotted blue;
}
Good luck!
The solutions lays somewhere else then you might expect.
You have missed with expectation that on "Contacts" menuis all working well. I have added a new element just to show that the "bug" is in design of the menu.
So the problem is in the design of the drop down menu. To solve this , take a look in your css and look for
#main li li.level-open:after, #main li li.level-open ~ li:after
And delete line:
border-right: 1px dotted #7F7F7F;
Now, in order to achieve adding dotted menu you have to do change a little your php code. You can't do that in CSS. At least to my little research I couldn't find.
Create a new class - for example .dotted-right-border , and in you code, create an algorithm to add that css class to every element that will be printed on the left side of li when there is li element on the left.
Update:
Ok, then. I usually don't like to say that something is impossible, but in this case, and to my opinion here is impossible to do the change with pure CSS. Even current creating of menu items is adding level-open into HTML tag, so it would need something that will be doing around that.
There could be one more approach for this situation, for example:
To modify the class
#main li li.level-open:after, #main li li.level-open ~ li:after
and change mentioned line:
border-right: 1px dotted #7F7F7F;
Into line:
border-right: 1px dotted transparent;
and then to set border-color: #7F7F7F for every new item under sub-menu, but then you couldn't tell apparent if the sub menu has it's match on the left side, so it would then show/not show dotted border. This is just an example approach. If I explained the approach good.
It all ends up into situation - How can you tell apart if the sub menu has a parent item on the left side in order to show dotted border? And that is why I think there is no pure CSS solution. But if someone knows better, then even better.
CSS selector can not refer to children elements, the only class (pseudo) i know :empty. In your case at parent level you need information about number of children. The solution is to provide this info at design time and encode it (e.g. in class attribute).
Based on you code, for projects node you need to add info as follows:
<li class="level-has-sub limit">...</li>
<li class="level-has-sub limit2">...</li>
<li class="level-has-sub limit">...</li>
<li class="level-has-sub">...</li>
And corresponding CSS:
#main li li.level-open~li:after {
content: "";
position: absolute;
top: 10px;
bottom: 10px;
right: -17px;
border-right: none;
z-index: 1;
}
// above is not necessary if you remove this selector from your css
/* main job */
#main li li.level-open:not([class*=limit])~li:after {
content: "";
position: absolute;
top: 10px;
bottom: 10px;
right: -17px;
border-right: 1px dotted #7f7f7f;
z-index: 1;
}
#main li li.level-open.limit2+li:after,
#main li li.level-open.limit3+li:after,
#main li li.level-open.limit4+li:after
{
content: "";
position: absolute;
top: 10px;
bottom: 10px;
right: -17px;
border-right: 1px dotted #7f7f7f;
z-index: 1;
}
#main li li.level-open.limit3+li+li:after,
#main li li.level-open.limit4+li+li:after {
content: "";
position: absolute;
top: 10px;
bottom: 10px;
right: -17px;
border-right: 1px dotted #7f7f7f;
z-index: 1;
}
#main li li.level-open.limit4+li+li+li:after {
content: "";
position: absolute;
top: 10px;
bottom: 10px;
right: -17px;
border-right: 1px dotted #7f7f7f;
z-index: 1;
}
As you can see, there is problem with multiple selectors like:
#main li li.level-open.limit2+li:after,
#main li li.level-open.limit3+li:after,
#main li li.level-open.limit4+li:after
You can workaround it by using coding by attribute substring, eg: limit1, limit11, limit111, and selectors [class*=limit1], [class*=limit11], [class*=limit111].
Note:
I use substring selector [class*=limit] witch is little unpredictable ;) you can change it to pair: [class^="limit"], [class*=" limit"] for better control.
Hope it helps :)

Resources