Inverted triangle for active menu item in a mega menu - html

I want to produce something like the following (note the inverted arrow below "Product":
I want to show an inverted arrow below the active menu item. The mega menu is inside Bootstrap .container.
However with my skills this is what I've been able to accomplish so far. There are two overflowing lines from both sides. I have created these using :before and :after of the arrow element inside the active <li>. Challenge is to make them visible only within the range of .container below
Demo

I didn't see the demo link, but already set up this pure CSS code for you:
<ul>
<li>Menu item</li>
<li>Menu item</li>
<li>Menu item</li>
</ul>
<div class="content"> </div>
ul {
margin: 0 auto;
width: 90%;
height: 60px;
overflow: hidden;
position: relative;
}
ul li {
float: right;
padding: 5px;
height: 40px;
background: lightblue;
position: relative;
}
ul li:hover:before {
content: ' ';
position: absolute;
right: 50%;
margin-right: 5px;
top: 40px;
width: 10000px;
height: 20px;
background: white;
-webkit-transform: skew(20deg);
-moz-transform: skew(20deg);
-o-transform: skew(20deg);
}
ul li:hover:after {
content: ' ';
position: absolute;
left: 50%;
margin-left: 5px;
top: 40px;
width: 10000px;
height: 20px;
background: white;
-webkit-transform: skew(-20deg);
-moz-transform: skew(-20deg);
-o-transform: skew(-20deg);
}
ul:after {
content: ' ';
position: absolute;
top: 40px;
width: 100%;
height: 20px;
background: white;
}
ul:hover:after {
display: none;
}
It creates a 20px space under the menu items. This space is filled by a ul:after element. When hovering the ul, the :after class gets removed. When hovering the menu items, a li:before and li:after are shown, which provide a white background and is skewed, making it look like an arrow.
The only downside with this script is that the default white space (presented by ul:after) is also removed when hovering the ul and not the li. Maybe someone can come up with a fix for that.
JSFiddle

The way you did it is way too complicated. The spaces are due to the height of your pseudo-elements. In this example I deleted your arrows and replace them with CSS triangles, you just need a pseudo element on your open class like this (I let you tweak dimension and position):
.open::after {
content: '';
position: absolute;
left: 50%;
top: 126px;
transform: translate(-50%, 0);
display: block;
width: 0;
height: 0;
border-style: solid;
border-width: 8px 5px 0 5px;
border-color: #808080 transparent transparent transparent;
}
Example : http://codepen.io/mbrillaud/pen/ZGOqoa?editors=110

Done the following modifications: RESULT PEN
Added z-index, adjusted margin-top and removed width from :after and :before . The reason you were getting extra white background was because you have given the width as 100vw full viewport which was not needed
.header .menu > li.open.horizontal > span.arrow {
background-image:
url(https://s3.amazonaws.com/imgrvx/white.svg);
background-repeat: no-repeat;
width: 14px;
height: 7px;
left: calc(50% - 14px);
margin-top: 19px;
position: absolute;
z-index:2;
}
.header .menu > li.open.horizontal > span.arrow:before {
content: '';
position: absolute;
height: 7px;
width: 100vw;
background-color: #ffffff;
display: block;
left: -100vw;
border-top: 1px solid #e6e6e6;
}
.header .menu > li.open.horizontal > span.arrow:after {
content: '';
position: absolute;
height: 7px;
left: 14px;
background-color: #ffffff;
border-top: 1px solid #e6e6e6;
}

Related

How to keep text in anchor tag in the same position when border property is used

I am planning to use Bootstrap's Scrollspy component to work on a <ul> element.
The issue for me is that when I use the border-left property on a <li> element, the text in the anchor tag gets shifted a little to the right.
What could I do to fix this?
Please see Pen:
https://codepen.io/AshNaz87/pen/QmVJVY
.wrapper {
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
li {
list-style: none;
margin-bottom: 0.5rem;
padding-left: 1rem;
}
li:last-child {
margin: 0;
}
.with-border {
border-left: 3px solid grey;
}
a {
text-decoration: none;
color: #000;
}
<div class="wrapper">
<ul class="nav">
<li class="with-border">Fortune</li>
<li>Favours</li>
<li>The</li>
<li class="with-border">Brave</li>
</ul>
</div>
The reason why you're seeing this inconsistent offset of the text is because the border of an element actually take up physical space in the layout. To circumvent this, you will need to account for the space the border will take (see solution 1), or use alternative strategies that do not alter the flow of the document (see solution 2 and 3).
You can either use a:
transparent left-border on all your elements <li>,
background-image to visually mimic a border, or
abolustely positioned pseudo-element
Solution 1: Transparent left border
This solution means introducing a transparent border on all <li> elements, and simply changing the border-color property when needed:
li {
border-left: 3px solid transparent;
}
li.with-border {
border-color: grey;
}
.wrapper {
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
li {
border-left: 3px solid transparent;
list-style: none;
margin-bottom: 0.5rem;
padding-left: 1rem;
}
li:last-child {
margin: 0;
}
li.with-border {
border-color: grey;
}
a {
text-decoration: none;
color: #000;
}
<div class="wrapper">
<ul class="nav">
<li class="with-border">Fortune</li>
<li>Favours</li>
<li>The</li>
<li class="with-border">Brave</li>
</ul>
</div>
Solution 2: background-image to mimic border
Alternatively, you can use a linear gradient as a background image with a clearly demarcated border/breakpoint, to visually mimic a border:
li.with-border {
background-image: linear-gradient(90deg, grey 3%, transparent 3%);
}
.wrapper {
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
li {
list-style: none;
margin-bottom: 0.5rem;
padding-left: 1rem;
}
li:last-child {
margin: 0;
}
li.with-border {
background-image: linear-gradient(90deg, grey 3%, transparent 3%);
}
a {
text-decoration: none;
color: #000;
}
<div class="wrapper">
<ul class="nav">
<li class="with-border">Fortune</li>
<li>Favours</li>
<li>The</li>
<li class="with-border">Brave</li>
</ul>
</div>
Solution 3: Absolutely-positioned pseudo-element
This solution is the most verbose one: it uses a generated pseudo-element that is absolutely positioned within the <li> element to visually mimic a border:
li {
position: relative;
}
li::before {
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 3px;
display: none;
content: '';
background-color: grey;
}
li.with-border::before {
display: block;
}
.wrapper {
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
li {
position: relative;
list-style: none;
margin-bottom: 0.5rem;
padding-left: 1rem;
}
li:last-child {
margin: 0;
}
li::before {
position: absolute;
top: 0;
left: 0;
bottom: 0;
width: 3px;
display: none;
content: '';
background-color: grey;
}
li.with-border::before {
display: block;
}
a {
text-decoration: none;
color: #000;
}
<div class="wrapper">
<ul class="nav">
<li class="with-border">Fortune</li>
<li>Favours</li>
<li>The</li>
<li class="with-border">Brave</li>
</ul>
</div>

semi-transparent rectangle behind css arrow

I'm quite new to coding so it's probably something really easy that I'm trying to do but can't get it to work.
I've made some arrows with css borders. Now I want to do a rectangle that is semi transparent behind each arrow.
Something like this
But with rectangles instead of the circle.
This is the code I've got so far :
<div id="arrow"></div>
#arrow {
display: block;
border-right: 2px solid; border-bottom: 2px solid;
width: 30px; height: 30px;
transform: rotate(-45deg);
border-color:black;
margin:auto;
display:block;
position:relative;
}
super easy way:
HTML:
<div id="arrowBox">
<div id="arrow"></div>
</div>
CSS:
#arrow {
display: block;
border-right: 2px solid; border-bottom: 2px solid;
width: 30px; height: 30px;
transform: rotate(-45deg);
border-color:black;
margin:auto;
display:block;
position:relative;
}
#arrowBox{
background:rgba(0,0,0,0.5);
display:inline-block;
padding:10px 15px 10px 0;
}
adjust padding to change the size of the box.
Instead of using the div as your arrow, try using the div as your rectangle (or circle if desired). You'll need background-color: rgba(0,0,0,0.4) or similar to get the "translucent black" effect.
Once that's done, put your arrow styles in the ::before pseudo-element. Use positioning to get it in the right place, but it should be pretty easy to get the arrow to appear. Don't forget content:'' to make the pseudo-element appear.
set css property to your rectangle div or any shape as,
{ opacity: 0.5;}
You can user pseudo-elements to add the box with no additional markup. As already suggested, use rgba to define the background color.
I made a fiddle with an example showing the result, with 4 arrows in different directions on different background colors: https://jsfiddle.net/7f6tg9s3/4/
Here is the arrows part:
.arrow {
display: inline-block;
position:relative;
width: 30px;
height: 30px;
}
.arrow::before {
content: ' ';
display: block;
background-color: rgba(0, 0, 0, 0.3);
position: relative;
width: 30px;
height: 30px;
margin-right: -30px;
margin-bottom: -30px;
z-index: 1;
}
.arrow::after {
content: ' ';
display: block;
box-sizing: border-box;
position: relative;
border-right: 2px solid;
border-bottom: 2px solid;
width: calc(25px / 1.41421);
height: calc(25px / 1.41421);
border-color: #fff;
z-index: 2;
}
.arrow.right::after {
transform: rotate(-45deg);
top: 6px;
left: 2px;
}
.arrow.left::after {
transform: rotate(135deg);
top: 6px;
left: 12px;
}
.arrow.up::after {
transform: rotate(-135deg);
top: 12px;
left: 7px;
}
.arrow.down::after {
transform: rotate(45deg);
top: 2px;
left: 7px;
}

css border with triangle shape

Is there any way to create the border on the left with css ?
Here is a way to do it using CSS; you are just layering a Parallelogram and a Rectangle:
.espanolIcon
{
width: 300px;
height: 100px;
padding-left: 30px;
}
.rectangle {
position: absolute;
top: 0px;
left: 200px;
width: 200px;
height: 100px;
background-color: green;
border-radius: 0px 0px 30px 40px;
}
.arrow-left {
position: absolute;
top: 0px;
width: 300px;
height: 100px;
background-color: green;
-webkit-transform: skew(22deg);
transform: skew(22deg);
border-radius: 0px 0px 30px 40px;
}
h1 {
color: white;
}
<div class="espanolIcon">
<div class="rectangle"><h1>Espanol</h1></div>
<div class="arrow-left"></div>
</div>
Use a zero-dimension :before with thick, partial borders
By adjusting the top/bottom and left/right values of border-width on the :before pseudo-element, you can effectively change the skew of the triangle. The left position can then be changed to properly align the pseudo-element.
a {
display: inline-block;
position: relative;
margin-left: 14px; /* Should counter `left` value of `a:before` */
padding: .5em 1em;
color: #fff;
font: bold 1em/1 sans-serif;
text-decoration: none;
text-transform: uppercase;
border-radius: 0 0 10px 10px;
background: #75bf41;
}
a:before {
content: '\200B'; /* zero-width non-breaking space */
display: block;
position: absolute;
top: 0;
left: -14px; /* Adjust to align */
width: 0;
height: 0;
border-width: 14px 8px; /* Adjust top/bottom and left/right to skew */
border-style: solid;
border-color: #75bf41 #75bf41 transparent transparent; /* Triangle orientation. */
}
Español
Full css could work, but you should use .png as background-image or perhaps you could use .svg as you can animate and/or change every point or pixel. You might be able to use just CSSbut it would take a lot of leveling and positioning and alot of layers of absolute and relative positioning. As Css would only change the full width of the element, and it can only be used to change the width of elements. What you can do is use .svg, you could map every pixel which could be animated.
I accomplished it using borders and pseudo elements.
<ul>
<li class="lang-item lang-item-6 lang-item-es">
::before
<a>Español</a>
</li>
</ul>
ul {
position:relative;
}
.lang-item {
text-align: right;
position: relative;
}
.lang-item a {
background: #76c53f;
padding: 15px;
color: #fff;
text-transform: uppercase;
border-bottom-right-radius: 10px;
border-bottom-left-radius: 14px;
}
.lang-item::before {
position: absolute;
right: 101px;
top: -15px;
content: "";
display: inline-block;
border-top: 40px solid #76C541;
border-left: 40px solid transparent;
}
jsfiddle

CSS tooltip getting cut off

I have a CSS tooltip that is being cut off when the hovered item is too close to the edge of the content area. See the links towards the bottom of this post: http://blog.betbright.com/top-stories/manchester-united-v-club-brugge-betting-preview/
Here is the code I'm using for the tooltip:
a.tooltip {
position: relative;
display: inline;
}
a.tooltip span {
position: absolute;
width:110px;
color: #FFFFFF;
background: #00A1E0;
height: 30px;
line-height: 30px;
text-align: center;
visibility: hidden;
border-radius: 6px;
}
a.tooltip span:after {
content: '';
position: absolute;
top: 100%;
left: 50%;
margin-left: -8px;
width: 0; height: 0;
border-top: 8px solid #00A1E0;
border-right: 8px solid transparent;
border-left: 8px solid transparent;
}
a:hover.tooltip span {
visibility: visible;
opacity: 1;
bottom: 30px;
left: 100%;
margin-left: -76px;
z-index: 999;
}
Any solutions you can recommend to stop the tooltip being cut would be appreciated.
Thanks,
Paul
You should set the overflow property on your .entry-content class to visible instead of hidden. Your current setting hides everything that does not fit within that div. Since your tooltip would be displayed partly outside your .entry-content div, a part is cut of unless you change the overflow property. So, your error is not in the tooltip, it's in a parent element.

Css border shape and working with hover state

Question: Why when you make css shapes using the border tricks seen here does it move the visual of your element out of its dom-box?
So I found these two questions while searching:
Can I use CSS hover on this complex irregular shaped link
Hovering on overlapping CSS3 shapes
But I don't think that either addresses my question (though if I want to change my html structure I could probably use the answer from that first link.
Example pics to illustrate:
Which means that when I hover over the bottom half of that element it highlights the one below it.
I understand that even though I have a diamond visually the box-model says that it's still a rectangle, but why is the diamond not contained inside that rectangle?
Is there a way around this - with css/markup -, or do I have to go with the maping solution from the first link?
My source code incase anyone wants that:
<header class="navigation">
<div class="nav">
<ul class='master_nav'>
<li>Home</li>
<li>About</li>
<li>Resources</li>
<li>FAQs</li>
</ul>
</div>
</header>
.navigation li{
height: 0;
width: 0;
margin: 10px 0;
list-style: none;
position: relative;
border: 70px solid transparent;
border-bottom: 90px solid #2B2B2B;
display: block;
}
.navigation li:after{
content: '';
position: absolute;
left: -70px; top: 90px;
width: 0;
height: 0;
border: 70px solid transparent;
border-top: 90px solid #2B2B2B;
}
.navigation li a{
height: 25px;
width: 100%;
display: inline-block;
text-decoration: none;
color: #b7b7b7;
position: absolute;
top: 75px;
left: -19px;
}
.navigation li:hover a{
color: #010101;
}
I'm not 100% sure why but you can get around it by making the <a> the hover target and filling the space:
.navigation li a{
height:70px;
width: 80px;
display: block;
text-decoration: none;
color: #b7b7b7;
position: absolute;
top: 38px;
left: -40px;
padding-top: 40px;
text-align: center;
border: 1px solid yellow; //just to see it.
}
.navigation a:hover{
color: #010101;
}
Here's a working pen http://codepen.io/willthemoor/pen/KpcLD/ (updated)
Edit
Getting it lined up perfectly might take a little trial and error but you can use the transform property to rotate and skew the <a> to match the shape. I updated the pen.
I had to add some skew to match the shape of the diamonds, and then use a a <span> inside of the <a> to sort revert the changes. Skew messes with text so you might try to find a happy medium between the shape of your border diamonds and the shape you can make without using skew.
.navigation li{
height: 0;
width: 0;
margin: 10px 0;
list-style: none;
position: relative;
border: 70px solid transparent;
border-bottom: 90px solid #2B2B2B;
display: block;
/* position fix */
top: -90px;
left: -19px;
}
.navigation li:before{
content: '';
position: absolute;
left: -70px;
top: 90px;
width: 0;
height: 0;
border: 70px solid transparent;
border-top: 90px solid #2B2B2B;
}
.navigation li a{
background-color: rgba(255, 0, 0, 0.3);
color: #B7B7B7;
display: block;
height: 68px;
left: -55px;
padding-top: 40px;
position: absolute;
text-align: center;
text-decoration: none;
top: 34px;
-webkit-transform:rotate(314deg);
transform: rotate(314deg);
width: 110px;
}
.skew li a {
/* following lines it up better but hard to 'rewind it' on the span witout the text looking a little strange */
-webkit-transform: rotate(310deg) skewX(-11deg) skewY(-2deg);
transform: rotate(310deg) skewX(-11deg) skewY(-2deg);
height: 73px;
left: -55px;
width: 112px;
}
.navigation a:hover{
background-color: rgba(0,0,255,.3);
color: #010101;
}
.navigation a > span {
display: block;
/* and reset the text*/
-webkit-transform: rotate(46deg);
transform: rotate(46deg);
}
.skew a > span {
-webkit-transform: rotate(45deg);
transform: rotate(45deg);
letter-spacing: .04em;
}
/*
lis are actually covering each other on the bottoms.
Adding this hacky bit makes the bottom of the diamond link work. Could use classes instead.
*/
.navigation li { z-index: 100; }
.navigation li + li { z-index: 90; }
.navigation li + li + li { z-index: 80; }
.navigation li + li + li + li { z-index: 70; }