include a pseudoelement inside a anchor hover state - html

I have pseudoelements next to my links in a navigation menu. There are small downward arrows indicating a dropdown and On hover, the background changes. However, the only area that is covered is the active link and not the downward pointing arrow.
A sample of that is below:
.item > a {
color: #000;
padding-top: 1.5rem;
padding-bottom: 1.1rem;
}
.item > a:hover {
background-color: blue;
color: #fff;
}
.arrow-nav-item:after {
content: '';
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-top: 4px solid #5a5a5a;
clear: both;
position: absolute;
top: 25px;
right: 625px;
}
<ul id="items">
<li class="item"><a class="arrow-nav-item" href="#">Main Item</a>
<ul class="subitem">
<li>Chapter 1</li>
</ul>
</li>
</ul>
Basically I have an ::after on my anchor tag which is positioned absolutely and is styled to look like a down arrow. On hover, a background appears, and I want the arrow included inside the colored hover area.
The reason it's not included I think is because of the absolute positioning - because when the arrow is relative, I can include it in the hover area. I don't think I can do that because giving the :after a relative positioning loses control of placement.
A couple of things I tried: add more right padding to the anchor, setting a fixed width on anchor and changing placement of pseudo-element (moving it to <li> tag) etc.
Should this be refactored to change? Is absolute positioning not the best way to handle these pseudoelements?

Using right in that way will cause problems as the screen resizes. Instead, you can remove absolute positioning and position the anchor with margin instead...
.item>a {
color: #000;
padding-top: 1.5rem;
padding-bottom: 1.1rem;
}
.item>a:hover {
background-color: blue;
color: #fff;
}
.arrow-nav-item:after {
content: '';
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-top: 4px solid #5a5a5a;
margin-left: 1em;
display: inline-block;
vertical-align: middle;
margin-right: 1em;
}
.arrow-nav-item:hover:after {
border-top-color: #FFF;
}
<ul id="items">
<li class="item"><a class="arrow-nav-item" href="#">Main Item</a>
<ul class="subitem">
<li>Chapter 1</li>
</ul>
</li>
</ul>

While absolute-positioning would be a good way to handle this, you certainly don't want to be using giant offsets relative to the right. What I would recommend is to make use of ::before, and simply set a small negative margin-left on the dropdown:
.item>a {
color: #000;
padding-top: 1.5rem;
padding-bottom: 1.1rem;
}
.item>a:hover {
background-color: blue;
color: #fff;
}
.arrow-nav-item:before {
content: '';
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-top: 4px solid #5a5a5a;
position: absolute;
margin-left: -35px;
margin-top: 5px;
}
<ul id="items">
<li class="item"><a class="arrow-nav-item" href="#">Main Item</a>
<ul class="subitem">
<li>Chapter 1</li>
</ul>
</li>
</ul>
Note that this makes the dropdown relative to the element's left-hand side, so it will always appear in the same place, regardless of the content of the <li>. However, it still has the dropdown arrow outside of the`. The problem is that in order to have the background cover both components, you need to move the arrow inside the bullet points.
This can then be offset with padding-left on the <a> tag itself, so that the dropdown remains within the blue background:
.item>a {
color: #000;
padding-top: 1.5rem;
padding-bottom: 1.1rem;
}
.item>a:hover {
background-color: blue;
color: #fff;
}
.arrow-nav-item:before {
content: '';
border-left: 4px solid transparent;
border-right: 4px solid transparent;
border-top: 4px solid #5a5a5a;
position: absolute;
margin-left: -15px;
margin-top: 5px;
}
.arrow-nav-item {
padding-left: 20px; /* Larger than margin-left */
}
<ul id="items">
<li class="item"><a class="arrow-nav-item" href="#">Main Item</a>
<ul class="subitem">
<li>Chapter 1</li>
</ul>
</li>
</ul>
I don't think it's possible to have the dropdown arrow outside the bullet point and still retain the background, but hopefully this will suffice :)

Related

How to remove border on active li tab

I have a list ul with items li. Under the list there is a box surrounded with border. The top border of the box is also the bottom border of the list items.
What I want to do know is to remove the bottom border of the active tab. That means removing the top border of the content box along the active tab. Is this possible or do I need to use a different approach?
li {
display: inline-block;
padding-top: 0;
padding: 15px;
border-right: 1px solid #e6e6e6;
cursor: pointer;
border-top: 1px solid #e6e6e6;
font-family: 'Cera';
font-size: 13px;
}
ul {
list-style-type: none;
margin: 0 auto;
border-left: 1px solid #e6e6e6;
padding-left: 0px;
}
.content-box {
display: block;
min-height: 100px;
margin: 0 auto;
border: 1px solid #e6e6e6;
overflow: hidden;
padding-bottom: 10px;
}
.active {
position: relative;
background-color: #f8f8f8;
top: -3px;
}
<ul id="menu">
<li class="active" data-nav="1">Prerender</li>
<li data-nav="2">Prefetch</li>
<li data-nav="3">Preconnect</li>
<li data-nav="4">DNS-prefetch</li>
</ul>
<div class="content-box box1 expanded">
<h3 id="isPrerender"> Prerendered page:</h3>
<ul class="results" id='pagetitle1'></ul>
</div>
Here's how I'd like it to look:
I suggest that you use negative margin to overlap elements.
Use a margin-top:-1px to overlap the top border of the lower box with the bottom edge of the top boxes. This allows the background-color of the active top box to cover the top border of the lower box.
Use margin-left:-1px on all top boxes except the first one to overlap the borders on their left and right sides. Otherwise, with a border on only one side, the active box will be missing a piece of border where it rises above the others.
I've removed the white space between <li> elements because, since they are display:inline-block, that space is rendered as gaps between the boxes.
I'm using additional padding to raise the active top box, instead of using negative top. This keeps the text inside the active box at the same height as the other boxes.
I've aligned the top boxes with vertical-align:bottom to keep them flush against the bottom box.
ul {
list-style-type: none;
margin: 0;
padding: 0;
}
li {
display: inline-block;
padding: 15px;
margin-left: -1px;
border-style: solid;
border-color: #e6e6e6;
border-width: 1px 1px 0 1px;
cursor: pointer;
font-family: 'Cera';
font-size: 13px;
vertical-align: bottom;
}
li:first-child {
margin-left: 0;
}
.content-box {
min-height: 100px;
border: 1px solid #e6e6e6;
margin-top: -1px;
padding: 10px;
}
.active {
background-color: #f8f8f8;
padding-top: 18px; /* 15 + 3 */
}
<ul id="menu">
<li data-nav="1">Prerender
</li><li class="active" data-nav="2">Prefetch
</li><li data-nav="3">Preconnect
</li><li data-nav="4">DNS-prefetch</li>
</ul>
<div class="content-box box1 expanded">
<h3 id="isPrerender">Prefetched page:</h3>
<ul class="results" id='pagetitle1'></ul>
</div>
If your idea is to slide down the tab to hide the border , then you should reset vetical-align on li (and eventually mind the white-space) , then increase the padding of 1px (for a one px border) and low it down of that extra pixel(s) like you tried.
li {
display: inline-block;
padding-top: 0;
padding: 15px;
border-right: 1px solid #e6e6e6;
cursor: pointer;
border-top: 1px solid #e6e6e6;
font-family: 'Cera';
font-size: 13px;
vertical-align: bottom;
}
ul {
list-style-type: none;
margin: 0 auto;
border-left: 1px solid #e6e6e6;
padding-left: 0px;
}
.content-box {
display: block;
min-height: 100px;
margin: 0 auto;
border: 1px solid #e6e6e6;
overflow: hidden;
padding-bottom: 10px;
}
.active {
position: relative;
background-color: #f8f8f8;
padding-bottom: 16px;/* increase height of 1 px here, can be any value you want */
top: 1px;/* low it done at least the border's thickness to hide */
}
body {
margin: 1em;
}
<ul id="menu">
<li class="active" data-nav="1">Prerender</li><!-- kill that white space via comments
--><li data-nav="2">Prefetch</li><!--
--><li data-nav="3">Preconnect</li><!--
--><li data-nav="4">DNS-prefetch</li>
</ul>
<div class="content-box box1 expanded">
<h3 id="isPrerender"> Prerendered page:</h3>
<ul class="results" id='pagetitle1'></ul>
</div>

Bootstrap dropdown hover issue

I have a bootstrap default dropdown on my website. The issue I am having is that I want the dropdown to show up on hover. It is working as intended but has a small issue. It goes away unless I go on it through the dropdown arrow if I go on it from anywhere beside the arrow but directly below the dropdown item.. it goes away so it is very inconsistent. How can I make it better? I have tried adding padding to the dropdown item but it didn't help at all.
HTML:
<nav class="navbar navbar-inverse" role="navigation">
<div class="collapse navbar-collapse text-right">
<ul class="nav navbar-nav pull-left">
<li>
<div class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#">Testing</a>
<ul class="dropdown-menu dropdown-menu-arrow">
<li>Testing</li>
<li>Testing</li>
</ul>
</div>
</li>
</ul>
</div>
</nav>
CSS:
a {
color: #fff
}
a:focus,
a:hover {
color: #fff!important;
border-bottom: 1px solid #fff;
text-decoration: none
}
#media (min-width:768px) {
.dropdown:hover .dropdown-menu {
display: block;
}
.dropdown-menu-arrow:before {
border-bottom: 7px solid rgba(0, 0, 0, 0.2);
border-left: 7px solid transparent;
border-right: 7px solid transparent;
content: "";
display: inline-block;
left: 9px;
position: absolute;
top: -7px;
}
.dropdown-menu-arrow::after {
border-bottom: 6px solid #FFFFFF;
border-left: 6px solid transparent;
border-right: 6px solid transparent;
content: "";
display: inline-block;
left: 10px;
position: absolute;
top: -6px;
}
}
JSFiddle Demo
Adding padding to the .dropdown-toggle item fixes the issue as the padding is part of the hoverable area of the item.
This is the code I added:
.dropdown-toggle {
padding: 10px;
}
Link to updated JSFiddle Demo
You said you added padding to the "dropdown item" which I am guessing means you tried to add it to the actual dropdown rather than the toggle for the dropdown. This wouldn't work as the dropdown toggle is the trigger that has the :hover pseudo class, therefore you must extend this item's hoverable area (with padding) to cover the gap between the trigger and the dropdown itself.
JJ's answer didn't work for me. The issue I had was a very small gap between the dropdown-toggle, and the dropdown-menu. This caused the dropdown to disappear if I moved the cursor down slowly from the menu item to the dropdown.
I added this to my css:
.dropdown-menu {
margin: 0px;
}

How to get chevron to align to center of link tab

I'm using Bootstrap and have a navbar with several links. The first few links have dropdown menus. On top of each dropdown menu I added a triangle turned upward pointing to the link you just clicked. The problem is, the links are of different lengths (BRANDS vs MEN'S WATCHES) and I want the triangle centered with the text. Since the triangle is done with CSS via the :before attribute on the dropdown-menu, I don't know how to center it according to the li with the dropdown class.
Bootply of my navbar: http://www.bootply.com/ebKpdebUKh
CSS for the triangle:
#main_navbar2 .dropdown-menu:before { position: absolute;
top: -10px;
left: 55px;
display: inline-block;
border-right: 9px solid transparent;
border-bottom: 9px solid #000;
border-left: 9px solid transparent;
content: '';}
Centering of "chevron" has been done by using JQuery.
Check complete example at CODEPEN
HTML:
<li class="dropdown">
BRANDS
<ul class="dropdown-menu multi-column columns-6" role="menu">
---- Multi column section ----
</ul>
</li>
JS:
$('.dropdown-menu , .dropdown > a').hover(function() {
$(this).parent().find('a:first-child').addClass('menu-pointer')
}, function() {
$(this).parent().find('a:first-child').removeClass('menu-pointer');
});
CSS:
#main_navbar2 .dropdown > a.menu-pointer:after {
top: 34px;
margin: auto;
position: absolute;
display: block;
border-right: 9px solid transparent;
border-bottom: 9px solid #000;
border-left: 9px solid transparent;
content: '';
left: 0;
right: 0;
z-index: 999;
width: 9px;
}
I hope this helps you
Enjoy :)
I know that this has an accepted answer - but you do not need jquery for it - just CSS and you can get a triangle under he center of the link text. I created a dodgy little navmenu - and have an active link which shows a little triangle under the active (selected) menu link - and then on the hover over each of the links - the triangle will show under the link text - and centered to the li. All without jQuery - and a little css magic. I also put in a longer than usual link text to show that the css tringle is autiomatically centered on the li.
.navLinks li{display:inline-block;list-style:none; text-decoration: none;padding:0 10px}
.navLinks li a, .navLinks li a:hover{text-decoration: none}
.navLinks li:hover:after,
.activeLink:after {
content: '';
position: relative;
border-style: solid;
border-width:0 9px 9px;
border-color: #006400 transparent;
display: block;
width: 0;
z-index: 1;
margin-left: -8px;
top:5px;
left: 50%;
background: none;
}
<ul class="navLinks">
<li class="activeLink">Home</li>
<li>About</li>
<li>About</li>
<li>Store</li>
<li>Contact</li>
<li>An Example of a long link text.</li>
</ul>

Bottom border with the same width from text value on css

I have an issue, I am trying to add 1 px to an underlined text, but researching a lot on the web I found that the only way was adding a border and a padding bottom
But the width is longer than the word and I want that the effect is the same form a underline effect, cropped with the word width.
Here is my fiddle
https://jsfiddle.net/0orb5h4s/1/
And my try to the selected underline class
/* Underline Issue */
.selected {
border-bottom: 1px solid #000;
/* text-decoration: underline; */
padding-bottom: 1px;
}
I think a span here is what you are looking for:
.horizontal-tabs li {
display: inline;
list-style-type: none;
padding-right: 10px;
padding-left: 10px;
}
.horizontal1,
.horizontal2 {
border-left: 1px solid #000;
}
/* Underline Issue */
.selected span {
text-decoration: underline;
}
<div class="tabs">
<ul class="horizontal-tabs">
<li class="horizontal0">Description</li>
<li class="horizontal1">Product Care</li>
<li class="horizontal2 selected"><span>Shipping Information</span>
</li>
</ul>
</div>
If you are actually looking to distance the underline from the text then you previous technique still works if you use the span as mentioned before.
.horizontal-tabs li {
display: inline;
list-style-type: none;
padding-right: 10px;
padding-left: 10px;
}
.horizontal1,
.horizontal2 {
border-left: 1px solid #000;
}
/* Underline Issue */
.selected span {
border-bottom: 1px solid #000;
padding-bottom: 1px;
}
<div class="tabs">
<ul class="horizontal-tabs">
<li class="horizontal0">Description</li>
<li class="horizontal1">Product Care</li>
<li class="horizontal2 selected"><span>Shipping Information</span>
</li>
</ul>
</div>
If you add a span inside your li elements you could use the border style on the span element instead. I edited your fiddle code and removed some unnecessary classes that you were using for setting the border-left style.
HTML
<div class="tabs">
<ul class="horizontal-tabs">
<li><span>Description</span></li>
<li><span>Product Care</span></li>
<li class="selected"><span>Shipping Information</span></li>
</ul>
</div>
CSS
.horizontal-tabs li {
display: inline-block;
list-style-type: none;
padding-right: 10px;
padding-left: 10px;
border-left: 1px solid #000;
}
/* This removes the first border */
.horizontal-tabs li:first-child {
border-left: none;
}
/* Underline Issue */
.horizontal-tabs li.selected span {
border-bottom: 1px solid #000;
padding-bottom: 1px;
display: inline-block;
}
JSFiddle
Here is an answer - https://jsfiddle.net/0orb5h4s/6/
Just added
.selected span {
border-bottom: 1px solid #000;
}
and
<li class="horizontal2 selected"><span>Shipping Information</span></li>
and removed the bottom border from the selected li.
The border applies to the padding as well and that's why adding a span moves the border to the content inside the padding.
Why don't you add a span?
HTML
<div class="tabs">
<ul class="horizontal-tabs">
<li class="horizontal0">Description</li>
<li class="horizontal1">Product Care</li>
<li class="horizontal2 selected">
<span>Shipping Information</span>
</li>
</ul>
</div>
CSS
.selected span {
border-bottom: 1px solid #000;
padding-bottom: 5px;
}
You can check my solution here: https://jsfiddle.net/lordfox/0orb5h4s/4/
Hope that helps! :)

CSS - nth-child conditions appearing on wrong elements

The goal is a rounded side nav with hover effects in CSS. I'm using nth-child to control border radius for the top and bottom. As you will see on the fiddle, when you hover over the elements in between the 1st and 4th child, you get the radius settings of nth-child(1). Why?
I'm using this markup:
http://jsfiddle.net/hKxt9/
HTML
<ul id="side-nav">
<li class="side-nav-item clients" id="link_clients">Clients</li>
<li class="side-nav-item rtemplates" id="link_routine_templates">Routines</li>
<li class="side-nav-item exlib" id="link_exercise_library">Exercise Library</li>
<li class="side-nav-item logout" id="link_log_out">Log Out</li>
</ul>
CSS
#side-nav{
border: 1px solid #D5D5D5;
border-radius: 10px;
padding: 0px !important;
list-style-type: none;
}
.side-nav-item{
padding: 10px;
border-bottom: 1px solid #D5D5D5;
border-radius: 0;
margin: 0px !important;
font-size: 16px;
font-weight: bold;
}
.side-nav-item a{
color: #808080;
}
.side-nav-item:hover{
background: #D5D5D5;
}
.side-nav-item.active{
background: #01bbea;
}
.side-nav-item.active {
color: #fff;;
}
.side-nav-item:nth-child(4){
border-bottom: 0px solid black;
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
}
.side-nav-item:nth-child(1){
border-top-left-radius: 10px;
border-top-right-radius: 10px;
border-bottom-left-radius: 0px;
border-bottom-right-radius: 0px;
border-bottom: 1px solid #D5D5D5;
}
First of all it is wrong to have anchors as child nodes of a list. You structure should look like ul>li>a.
On the other hand nth-child() works for elements, not for class selectors. And even not being so, your elements with .side-nav-item class are always the first element of its father, which are always the anchor. So if nth-child() would work for classes (which is not the case) then your code wouldn't work anyway.
So if you change your structure to this:
<ul>
<li></li>
<li></li>
<li></li>
</ul>
Which is valid HTML, then you can do what you are looking for in this way:
li:nth-child(1) a {
/* your stylings */
}