Add :before content to an elements child - css

I have the following, simplified:
<ul class="menu">
<li class="button-1">
Link
</li>
</ul>
The 'a' is dynamically loaded and I cannot add a class to it. I can only add a class to the 'li'. I want to add an icon before the 'a', so that it is included as part of the clickable link.
Currently I have:
.button-1:before {
font-family: "FontAwesome";
content: "\f007";
padding-left: 14px;
}
which sets the icon perfectly above the text link. But it's not clickable. Thus, I tried...
.button-1 a:before
But this doesn't work. Nor any other variation that I can think of or find. I think I am being incredibly stupid here and missing something obvious. Any advice. Thanks

It works (i.e. clickable etc.) when you use the :before on the child, i.e. .button-1 > a:before:
.button-1 > a:before {
content: "© ";
}
<ul class="menu">
<li class="button-1">
Link
</li>
</ul>
(As you can see, I used some other content to work around the non-available FontAwesome Icon)
ADDITION AFER COMMENTS:
You can also use :afer insteadof before. In this case you need some more settings, also for the parent, especially a relative/absolute position pairing as shown below:
.button-1 {
position: relative;
padding-left: 20px;
}
.button-1>a:after {
content: "©";
position: absolute;
left: 0px;
}
<ul class="menu">
<li class="button-1">
Link
</li>
</ul>

Related

Foundation 6.4 tweaking top bar

Foundation's top bar navigation tool is set-up to fully flesh out a hierarchy of links, relying upon list and item tags.
<div class="top-bar">
<div class="top-bar-left">
<ul class="dropdown menu" data-dropdown-menu>
<li class="menu-text">Site Title</li>
<li>
One
<ul class="menu vertical">
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>
</li>
<li>Two</li>
<li>Three</li>
</ul>
</div>
</div>
However, in an attempt to soften this structure, the goal is to have the second layer links on a single line, say
<ul><li>
One Two Three
</li></ul>
Unfortunately, either display is relinquished to the browser definition for line-item or display:block; from the base code of Foundation overrides even <li style='display: float'><a href="#" style='display: float'> with its .menu a class definition.
How can this one-liner be achieved?
Looks like you may have mixed up your css rules: display: block; and float: none. The default behaviour looks like it wants it to be vertical, and the structure looks to be built in that way. I didn't see anything in their docs for this (I skimmed them lol) but what I did to make it work was to use position:absolute; on that submenu, and then position it. I don't know what the rest of your menu looks like, but you will need to adjust I assume.
I created a codepen that might do what you need it to.
https://codepen.io/bjorniobennett/pen/bGGajWZ
ul.dropdown > li {
position: relative;
&:hover {
> ul.vertical {
display: block;
}
}
> ul.vertical {
display: none;
position: absolute;
width: 500%;
background: #c5c5c5;
top: 120%;
> li {
display: inline-block;
float: left;
}
}
}

Is it appropriate to wrap each navigation element in a div?

I'm learning HTML + CSS and working on a website where I need to have a vertical navigation bar on the left side which will have four elements which can be interacted with. Is it standard practice to wrap each of these four elements with a div or is there a more elegant or semantic way to solve this problem? I will want each element to have unique on-click functions associated with them, which is why I thought giving them divs and classes would make the most sense for interacting with them later.
Thanks!
JSFIDDLE DEMO
HTML structure:
There are many ways to achieve a vertical navigation.
The most common would be to use ul and li:
<div id="lnav_container">
<ul id="lnav">
<li class="lnav_item">Item 1</li>
<li class="lnav_item">Item 2</li>
<li class="lnav_item">Item 3</li>
<li class="lnav_item">Item 4</li>
</ul>
</div>
Also very common to have a tags inside li.
Styling:
You can get rid of the bullets by having list-style-type: none; for the ul.
You can give them different style on hover by using :hover selector to make it more interactive.
.lnav_item {
width: 74%;
margin-top: 10px;
}
.lnav_item:first-child {margin-top: 0px;}
.lnav_item.selected {width: 86%;}
.lnav_item a {
display: inline-block;
width: 100%;
line-height: 30px;
padding: 8px 5px 5px 0px;
background-color: yellow;
color: black;
font-weight: bold;
text-decoration: none;
border-radius: 2px 12px 12px 2px;
}
.lnav_item.selected a {
background-color: green;
color: white;
font-size: 18px;
}
.lnav_item:hover a {background-color: orange;}
To get rid of a underline use text-decoration: none; and override its default coloring if you wish.
Javascript (jQuery):
It'll be easy to bind clickListener to the items:
$('.lnav_item a').on('click', function() {
//$(this) item is clicked, do whatever you want
$('.lnav_item').removeClass('selected');
$(this).parent().addClass('selected');
});
EDIT:
If you want to give each of the navigation items a different style, etc, you can achieve it different ways:
jsfiddle DEMO
You can use CSS' nth-child() selector:
.lnav_item:nth-child(2):hover a{background-color: #252F1D;}
.lnav_item:nth-child(3):hover a{background-color: white;}
If you're doing it in jQuery, alternatively you can use the function with parameter (index) and maybe use eq if needed.
$('.lnav_item > a').each(function(index) {
if(index == 0) {
//give it a different onClick, CSS rule, etc
}
//and so on
});
index is zero-based, but nth-child starts from one.
The typical HTML5 markup for a site navigation menu would be a nav element that contains an ul element:
<nav>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
</nav>
If you can get your CSS/JS to work with this markup (+ class attributes or whatever you need), great.
If you need more elements, add div and/or span elements: they are meaningless, so they don’t change the semantics of your document.
NAV elements are simply LISTS.
You don't need to wrap them in anything.
Here's an example of my own Navigation Panel (I also placed it on the left-hand side of my screen)
<nav>
<ul style="list-style: none">
<h3>Main Menu</h3>
<li style="font-size: 100%"><b>Article 1</b></li>
<ul style="list-style: none">
<br>
<dt>
<li style="font-size: 100%"><a href="Article 1.1">Article
1.1</a>
</li>
<br>
<li style="font-size: 100%"><a href="Article 1.2">Article
1.2</a>
</li>
<br>
</dt>
</ul>
<br>
</nav>

Why a:before gets underlined

How can I remove the underline bellow "-"? I only want the text to be underlined on Hover not the "-"
-- DEMO --
Many thanks!
HTML
<ul class="menu">
<li>
Commercial Property Management
<ul>
<li>
Industrial
</li>
<li>
Office
</li>
<li>
Retail
</li>
<li>
Shopping Centres
</li>
</ul>
</li>
<li>
Mixed-Use Residential Property Management
</li>
</ul>
CSS
ul.menu li li a:before {
content: "-";
margin-right: 8px;
}
Edit 4 years later: This answer is pretty much a low-quality duplicate of https://stackoverflow.com/a/8820459/3285730. I'd recommend going there and getting an actual explanation.
Try giving it display:inline-block;:
ul.menu li li a:before {
content: "-";
margin-right: 8px;
display:inline-block;
}
JSFiddle Demo
content of the :before selector is counted to the a-tag as it creates a pseudo-element within the element.
Add display:inline-block; to the definition to solve this issue.

Add dropdown arrow indicators to menu items that have submenus only?

I am currently trying to add arrow indicators on my navigation menu for items which have submenu options.
Currently I am using this CSS:
.mainNav li > a:after {
color: #444;
content: ' ▾';
}
But this adds a dropdown arrow to every <li> regardless of if there is a submenu or not. Is there a way with just CSS to only add this arrow to items that have sub-items?
Thanks!
No. CSS has no contains child selector. You'd probably be better to just add a class to the li element. For example:
<li class="has-child">
The Link
<ul class="child">
<li>Child 1</li>
</ul>
</li>
Your CSS selector would in turn look like:
.mainNav li.has-child > a:after {
color: #444;
content: ' ▾';
}
You could have jQuery add the class for you, if that's an option:
$('.mainNav li:has(ul)').addClass('has-child');
jsFiddle Demo
CSS has no contains child selector.
However it has various sibling selectors, only-child and not(:only-child)
Since you add indicator to the anchor, use following CSS
.mainNav li>a:not(:only-child):after {
color: #444;
content: ' ▾';
}
<div class="mainNav">
<li>
The item with child
<ul class="child">
<li>Child 1</li>
</ul>
</li>
<li>
No child item
</li>
</div>
Yes you can without any jQuery : https://css-tricks.com/targetting-menu-elements-submenus-navigation-bar/

Why does :first-child:before target all elements?

I have a list of items which I am trying to add dividers to right of each using the :before psuedo element.
Unfortunately, it seems like when I use it in combination with both last-child and first-child, it targets every element in the list.
Example - http://codepen.io/anon/pen/rupqi
Markup
<ul class="nav nav--inline nav--secondary">
<li><a class="nav--secondary__item" href="#">Site Map</a> </li>
<li><a class="nav--secondary__item" href="#" title="Search Terms">Search Terms</a> </li>
<li><a class="nav--secondary__item" href="#" title="Advanced Search">Advanced Search</a> </li>
<li><a class="nav--secondary__item" href="#" title="Contact Us">Contact Us</a> </li>
</ul>
CSS
.nav--inline, .nav--inline > li, .nav--inline > li > a { float: left; }
.nav--secondary__item {
color: #706782;
font-size: 1.2em;
padding: 0.8em;
position: relative;
#include transition (background-color 0.5s ease-in-out);
}
.nav--secondary__item:before {
content: "|";
color: #939EB7;
position: absolute;
left: 0;
}
.nav--secondary__item:first-child:before, .nav--secondary__item:last-child:before { content: "*"; }
Does anyone know why this happens, and if so, how to fix it?
Change your css to :
li:first-child .nav--secondary__item:before,
li:last-child .nav--secondary__item:before {
content:"*";
}
Because .nav--secondary__item is first-child as well as last-child of its parent li, following selector applies the content to all of them.
.nav--secondary__item:first-child:before,
.nav--secondary__item:last-child:before
{ content: "*"; }
Fiddle
:first-child pseudoclass selects the first child of its parent, similarly :last-child.
The :first-child CSS pseudo-class represents any element that is the first child element of its parent.
See doc
This is happening because you have a elements inside li elements and you are applying first-child to those a elements.
So .nav--secondary__item:first-child applies to every .nav--secondary__item, because the parents for each a are the surrounding li, not your ul.
Going by your class naming scheme, you can change your HTML to look like this:
<li class="nav--secondary__item">
<a class="nav--secondary__item__link" href="#" title="Site Map">Site Map</a>
</li>
And your CSS for the first-child/last-child will need a slight tweak:
.nav--secondary__item:first-child .nav--secondary__item__link:before,
.nav--secondary__item:last-child .nav--secondary__item__link:before {
content: "*";
}
You will also have to make the styles that apply to the a element use the .nav--secondary__item__link class instead.
Example forked from yours: http://codepen.io/anon/pen/rknmL

Resources