Reputation: 359
I am trying to apply a pure css arrow to my SELECTED link of horizontal and vertical menu but can't seem to figure out the outcome I wanted. Some similar solutions here at stackoverflow but it doesn't solve my issue.
UL has a border and that's where the problem is coming from... But I shouldn't remove the UL border.
<li class="selected"><a href="#">Arrow please</a></li>
ul.hor {
border-bottom: 3px solid blue;
}
ul li {
display: inline-block;
position: relative;
}
ul li a {
display: block;
padding: 10px 15px;
}
ul li.selected a {
color: green;
}
ul li.selected:after {
content: "";
width: 12px;
height: 12px;
position: absolute;
background: #fff;
border-top: 3px solid blue;
border-right: 3px solid blue;
}
ul.hor li.selected:after {
left: 0;
right: 0;
bottom: -8px;
margin: 0 auto;
-moz-transform: rotate(315deg);
-webkit-transform: rotate(315deg);
-ms-transform: rotate(315deg);
}
ul.ver li.selected:after {
right: -8px;
top: 50%;
margin-top: -6px;
-moz-transform: rotate(225deg);
-webkit-transform: rotate(225deg);
-ms-transform: rotate(225deg);
}
ul.ver {
width: 200px;
border-right: 3px solid blue;
}
ul.ver li {
display: block;
}
ul.ver li a {
display: block;
padding: 10px 15px;
}
body {
width: 90%;
margin: 20px auto;
background: rgb(229, 180, 230);
background: -moz-linear-gradient(30deg, rgb(229, 180, 230) 30%, rgb(90, 140, 250) 70%);
background: -webkit-linear-gradient(30deg, rgb(229, 180, 230) 30%, rgb(90, 140, 250) 70%);
background: -o-linear-gradient(30deg, rgb(229, 180, 230) 30%, rgb(90, 140, 250) 70%);
background: -ms-linear-gradient(30deg, rgb(229, 180, 230) 30%, rgb(90, 140, 250) 70%);
background: linear-gradient(120deg, rgb(229, 180, 230) 30%, rgb(90, 140, 250) 70%);
}
<ul class="hor">
<li><a href="#">Lorem</a></li>
<li><a href="#">Ipsum</a></li>
<li class="selected"><a href="#">Sit amet</a></li>
<li><a href="#">Consectetur</a></li>
</ul>
<br>
<ul class="ver">
<li><a href="#">Lorem</a></li>
<li><a href="#">Ipsum</a></li>
<li class="selected"><a href="#">Sit amet</a></li>
<li><a href="#">Consectetur</a></li>
</ul>
Upvotes: 9
Views: 2857
Reputation: 585
This one is easier to position and has a perfect triangle. We are still using transform rotate but no need for transform skew. No need to calculate width as well. Fiddle here.
ul {
overflow: hidden;
}
li {
display:inline-block;position: relative;
}
ul li a {
display: block;padding:20px 15px;
}
ul li.selected a {
color: green;
}
ul.hor li.selected:before,
ul.hor li.selected:after {
content: "";
bottom: 0;
position: absolute;
border-bottom:3px solid blue;
width:9999px;
margin:0 10px;left:50%;
}
ul.hor li.selected:after {
left:auto;right:50%;
}
/*vertical menu starts*/
ul.ver {
width: 200px;
}
ul.ver li {
display: block;
}
ul.ver li a {
padding:10px 15px;
}
ul.ver li.selected:before,
ul.ver li.selected:after {
content: "";
position: absolute;
top:50%;
right: 0;
border-right:3px solid blue;
height:9999px;
margin:10px 0
}
ul.ver li.selected:after {
top:auto;bottom:50%;
}
/*arrow starts*/
ul li.selected a:after {
content: "";
width: 15px;
height: 15px;
position: absolute;
border: solid blue;
border-width: 3px 3px 0 0;
}
ul.hor li.selected a:after {
top:100%;
left: 0;
right: 0;
margin: -10px auto 0;
-moz-transform: rotate(315deg);
-webkit-transform: rotate(315deg);
-ms-transform: rotate(315deg);
}
ul.ver li.selected a:after {
left:100%;
margin-left:-10px;
-moz-transform:rotate(225deg);
-webkit-transform:rotate(225deg);
-ms-transform:rotate(225deg);
}
body {
width:90%;margin:20px auto;
background: rgb(229, 180, 230);
background: -moz-linear-gradient(30deg, rgb(229, 180, 230) 30%, rgb(90, 140, 250) 70%);
background: -webkit-linear-gradient(30deg, rgb(229, 180, 230) 30%, rgb(90, 140, 250) 70%);
background: -o-linear-gradient(30deg, rgb(229, 180, 230) 30%, rgb(90, 140, 250) 70%);
background: -ms-linear-gradient(30deg, rgb(229, 180, 230) 30%, rgb(90, 140, 250) 70%);
background: linear-gradient(120deg, rgb(229, 180, 230) 30%, rgb(90, 140, 250) 70%);
}
<ul class="hor">
<li><a href="#">Lorem</a></li>
<li class="selected"><a href="#">Ipsum</a></li>
<li><a href="#">Sit amet</a></li>
<li><a href="#">Consectetur</a></li>
</ul>
<br>
<ul class="ver">
<li class="selected"><a href="#">Lorem</a></li>
<li><a href="#">Ipsum</a></li>
<li><a href="#">Sit amet</a></li>
<li><a href="#">Consectetur</a></li>
</ul>
Upvotes: 9
Reputation: 84
I made this:
ul li.selected a {
color:green
}
ul.hor {
border-bottom:3px solid blue
}
ul.ver {
width:200px;
border-right:3px solid blue;
}
ul li {
display:inline-block;position:relative
}
ul li a {
display:block;padding:10px 15px;
}
}
ul.ver {
width:200px;border-right:3px solid blue
}
ul.ver li {
display:block;
}
ver li a {
display:block;padding:10px 15px;
}
body {
width:90%;margin:20px auto;
background: rgb(229, 180, 230);
background: -moz-linear-gradient(30deg, rgb(229, 180, 230) 30%, rgb(90, 140, 250) 70%);
background: -webkit-linear-gradient(30deg, rgb(229, 180, 230) 30%, rgb(90, 140, 250) 70%);
background: -o-linear-gradient(30deg, rgb(229, 180, 230) 30%, rgb(90, 140, 250) 70%);
background: -ms-linear-gradient(30deg, rgb(229, 180, 230) 30%, rgb(90, 140, 250) 70%);
background: linear-gradient(120deg, rgb(229, 180, 230) 30%, rgb(90, 140, 250) 70%);
}
.ver {
position: relative;
}
.ver:after, .arrow_box:before {
left: 177px;
top: 95px;
border: solid;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
.ver:after {
border-color: rgba(136, 183, 213, 0);
border-right-color: blue;
border-width: 12px;
margin-top: -12px;
}
.hor {
position: fixed;
}
.hor:after, .hor:before {
top: 20px;
left: 194px;
border: solid transparent;
content: " ";
height: 0;
max-width: 0;
position: absolute;
pointer-events: none;
}
.hor:before {
border-color: rgba(194, 225, 245, 0);
border-bottom-color: blue;
border-width: 10px;
margin-left: -10px;
}
<ul class="hor">
<div class="arrow_box-vertical">
<li><a href="#">Lorem</a>
</li>
<li><a href="#">Ipsum</a>
</li>
<li class="selected"><a href="#">Sit amet</a>
</li>
<li><a href="#">Consectetur</a>
</li>
</ul>
<br>
<br>
<br>
<ul class="ver">
<li><a href="#">Lorem</a>
</li>
<li><a href="#">Ipsum</a>
</li>
<li class="selected"><a href="#">Sit amet</a>
</li>
<li><a href="#">Consectetur</a>
</li>
</ul>
It looks horrible in the snippet, please look at the JSFiddle.
Upvotes: 0
Reputation: 4105
Update: Found using 50.6% on the width calc for the a
element borders greatly reduces the sub-pixel issues at certain window widths. Snippet updated and here's the fiddle link: http://jsfiddle.net/5wLe4r3h/
Disclaimer: I don't consider this to be elegant.
I moved the main border to the li
elements. I'm clearing out the li.selected
border, and adding before/after partial borders to the a
elements.
ul.hor li {
border-bottom:3px solid blue;
float: left;
}
ul.hor li.selected {
border-bottom: none;
}
ul.hor li.selected a:before {
content:"";
position: absolute;
bottom: -3px;
left: 0px;
border-bottom:3px solid blue;
width: calc(50.6% - 9px);
}
ul.hor li.selected a:after {
content:"";
position: absolute;
bottom: -3px;
right: 0px;
border-bottom:3px solid blue;
width: calc(50.6% - 9px);
}
ul li {
display:inline-block;
position:relative
}
ul li a {
display:block;
padding:10px 15px;
}
ul li.selected a {
color:green
}
ul li.selected:after {
content:"";
width:12px;
height:12px;
position:absolute;
border-top:3px solid blue;
border-right:3px solid blue;
}
ul.hor li.selected:after {
left:0;
right:0;
bottom:-8px;
margin:0 auto;
-moz-transform:rotate(315deg);
-webkit-transform:rotate(315deg);
-ms-transform:rotate(315deg);
}
ul.ver li.selected:after {
right:-5px;
top:50%;
margin-top:-6px;
-moz-transform:rotate(225deg);
-webkit-transform:rotate(225deg);
-ms-transform:rotate(225deg);
}
ul.ver {
width:200px;
}
ul.ver li {
display:block;
border-right:3px solid blue;
}
ul.ver li a {
display:block;
padding:10px 15px;
}
ul.ver li.selected {
border-right: none;
}
ul.ver li.selected a:before {
content:"";
position: absolute;
top: 0px;
right: 0px;
border-right:3px solid blue;
height: calc(50% - 7px);
}
ul.ver li.selected a:after {
content:"";
position: absolute;
bottom: 0;
right: 0px;
border-right:3px solid blue;
height: calc(50% - 10px);
}
body {
width:90%;
margin:20px auto;
background: rgb(229, 180, 230);
background: -moz-linear-gradient(30deg, rgb(229, 180, 230) 30%, rgb(90, 140, 250) 70%);
background: -webkit-linear-gradient(30deg, rgb(229, 180, 230) 30%, rgb(90, 140, 250) 70%);
background: -o-linear-gradient(30deg, rgb(229, 180, 230) 30%, rgb(90, 140, 250) 70%);
background: -ms-linear-gradient(30deg, rgb(229, 180, 230) 30%, rgb(90, 140, 250) 70%);
background: linear-gradient(120deg, rgb(229, 180, 230) 30%, rgb(90, 140, 250) 70%);
}
.clear {
clear: both;
}
<ul class="hor">
<li><a href="#">Lorem</a>
</li>
<li><a href="#">Ipsum</a>
</li>
<li class="selected"><a href="#">Sit amet</a>
</li>
<li><a href="#">Consectetur</a>
</li>
</ul>
<div class="clear"></div>
<br>
<ul class="ver">
<li><a href="#">Lorem</a>
</li>
<li><a href="#">Ipsum</a>
</li>
<li class="selected"><a href="#">Sit amet</a>
</li>
<li><a href="#">Consectetur</a>
</li>
</ul>
Upvotes: 2
Reputation: 103770
One approach would be to use absolute positioning with pseudo elements on the selected element.
The arrow is made with borders and skewX() skewY()
on the pesudo elements. Their with for the horizontal menu and the height for the vertical one are set to a high value and the overflow is hidden on the <ul>
element :
ul {
overflow: hidden;
}
ul li {
position: relative;
display: inline-block;
text-align: center;
}
ul li a {
display: block;
padding: 10px 15px;
}
ul li.selected a {
color: green;
}
.hor .selected:before, .hor .selected:after {
content: '';
position: absolute;
bottom: 0;
height: 7px;
width: 9999px;
border-style: solid;
border-width: 0px 4px 3px;
border-color: blue;
}
.hor .selected:before {
right: 50%;
margin-right: -2px;
transform-origin: 100% 0;
transform: skewX(-45deg);
}
.hor .selected:after {
left: 50%;
margin-left: -2px;
transform-origin: 0 0;
transform: skewX(45deg);
}
ul.ver {
width: 200px;
}
ul.ver li {
display: block;
}
ul.ver li a {
display: block;
padding: 10px 15px;
}
.ver .selected:before, .ver .selected:after {
content: '';
position: absolute;
right: 0;
height: 9999px;
width: 7px;
border-style: solid;
border-width: 4px 3px 4px 0;
border-color: blue;
}
.ver .selected:before {
bottom: 50%;
margin-bottom: -2px;
transform-origin: 0 100%;
transform: skewY(-45deg);
}
.ver .selected:after {
top: 50%;
margin-top: -2px;
transform-origin: 0 0;
transform: skewY(45deg);
}
body {
width: 90%;
margin: 20px auto;
background: rgb(229, 180, 230);
background: -moz-linear-gradient(30deg, rgb(229, 180, 230) 30%, rgb(90, 140, 250) 70%);
background: -webkit-linear-gradient(30deg, rgb(229, 180, 230) 30%, rgb(90, 140, 250) 70%);
background: -o-linear-gradient(30deg, rgb(229, 180, 230) 30%, rgb(90, 140, 250) 70%);
background: -ms-linear-gradient(30deg, rgb(229, 180, 230) 30%, rgb(90, 140, 250) 70%);
background: linear-gradient(120deg, rgb(229, 180, 230) 30%, rgb(90, 140, 250) 70%);
}
<ul class="hor">
<li><a href="#">Lorem</a></li>
<li><a href="#">Ipsum</a></li>
<li class="selected"><a href="#">Sit amet</a></li>
<li><a href="#">Consectetur</a></li>
</ul>
<br>
<ul class="ver">
<li><a href="#">Lorem</a></li>
<li><a href="#">Ipsum</a></li>
<li class="selected"><a href="#">Sit amet</a></li>
<li><a href="#">Consectetur</a></li>
</ul>
Upvotes: 4
Reputation: 357
Take a look at what I did for the horizontal list.
ul.hor {
overflow: hidden;
padding-bottom: 5px;
}
ul.hor li.selected a:after,
ul.hor li.selected a:before {
content: "";
width: 1000%;
height: 20px;
position: absolute;
left: 59px;
bottom: -3px;
border-bottom:3px solid blue;
z-index: -1;
}
ul.hor li.selected a:after {
left: auto;
right: 58px;
}
Basically, don't add border for the ul, instead, add fake border to active element which is Really big. Hide overflow of the ul and voila!
'http://jsfiddle.net/wvs9o8oy/12/'
Upvotes: 1