Skip to content

Instantly share code, notes, and snippets.

@shrinkray
Created December 6, 2014 02:20
Show Gist options
  • Save shrinkray/462c560371bcdbe20f1f to your computer and use it in GitHub Desktop.
Save shrinkray/462c560371bcdbe20f1f to your computer and use it in GitHub Desktop.
LESS Mixins CSS arrow
<div class="test test2">Both my arrow and its border are handled with a mixin!</div>
<div class="test test1">My arrow is handled with a mixin!</div>

LESS Mixins CSS arrow

Still many things to do and edge cases to fix. So feel free to make suggestions here or on the GitHub repo: https://github.com/HugoGiraudel/LESS-Mixin-for-CSS-arrows. :)

USAGE:
.arrow(size, color, direction, offset, border-size, border-color);

  • size: you can set pretty much whatever you want. Further tests required for em unit.

  • color: sadly, no way to inherit. Use the same color as the background of your element.

  • direction: the direction of the arrow (top, right, bottom, left).

  • offset: the position on the side (20px, 50%, etc.).

  • border-size (optional): you may have to set it 1px thinner than the actual border to smooth the rendering.

  • border-color (optional): "inherit" as a default value.

CHANGELOG:
Edit 1: it now handles borders
Edit 2: "inherit" now supported as a border-color value
Edit 3: dramatically simplified the position
Edit 4: drop-shadow enabled

A Pen by Hugo Giraudel on CodePen.

License.

/* LESS Mixin for CSS arrow
*
* Usage:
* .arrow(size, color, direction, offset, border-size(optional), border-color(optional));
*
* 1. size: you can set pretty much whatever you want. Further tests required for em unit.
* 2. color: sadly, no way to inherit. Use the same color as the background of your element.
* 3. direction: the direction of the arrow (top, right, bottom, left).
* 4. offset: the position on the side (20px, 50%, etc.).
* 5. border-size (optional): you may have to set it 1px thinner than the actual border to smooth the rendering.
* 6. border-color (optional): "inherit" as a default value.
*
*
* Still many things to do and edge cases to fix.
* It uses the :after pseudo-element to create the arrow. If there is a border, it uses the :before pseudo-element
*
* Changelog:
* - now handles border
* - "inherit" now supported as a @border-color value
* - "inherit" now supported as a @color value as long as there is no border involved
* - dramatically simplified the position
* - drop-shadow enabled
* - GitHub repo: https://github.com/HugoGiraudel/LESS-Mixin-for-CSS-arrows
*/
.test {
/* Size and position */
box-sizing: border-box;
display: block;
width: 50%;
padding: 10px;
margin: 30px auto;
/* Styles */
background: #08C;
border-color: #08C;
border-radius: 3px;
-webkit-filter: drop-shadow(0 4px 3px rgba(0,0,0,.3));
/* Font styles */
color: white;
font-weight: bold;
text-align: center;
line-height: 1.5;
font-family: Arial, sans-serif;
text-shadow: 0 -1px 1px rgba(0,0,0,0.3);
}
.test1 {
.arrow(8px, inherit, right, 50%);
}
.test2 {
border: 2px solid darken(#08C, 10%);
.arrow(20px, #08C, bottom, 25%, 2px, darken(#08C, 10%));
}
.arrow(
@size,
@color,
@direction,
@offset,
@border-size: 0,
@border-color: inherit) {
position: relative;
&:after,
&:before {
content: "";
position: absolute;
width: 0;
height: 0;
}
}
.arrow(@size, @color, @direction, @offset, @border-size: 0, @border-color: inherit) when (@direction = top) {
@m-size: @size + (@border-size*2);
&:after {
bottom: 100%;
left: @offset;
margin-left: -@size;
border-left: @size solid transparent;
border-right: @size solid transparent;
border-bottom: @size solid @color;
}
&:before {
bottom: 100%;
left: @offset;
margin-left: -@m-size;
border-left: @m-size solid transparent;
border-right: @m-size solid transparent;
border-bottom: @m-size solid;
border-bottom-color: @border-color;
}
}
.arrow(@size, @color, @direction, @offset, @border-size: 0, @border-color: inherit) when (@direction = bottom) {
@m-size: @size + (@border-size*2);
&:after {
top: 100%;
left: @offset;
margin-left: -@size;
border-left: @size solid transparent;
border-right: @size solid transparent;
border-top: @size solid @color;
}
&:before {
top: 100%;
left: @offset;
margin-left: -@m-size;
border-left: @m-size solid transparent;
border-right: @m-size solid transparent;
border-top: @m-size solid;
border-top-color: @border-color;
}
}
.arrow(@size, @color, @direction, @offset, @border-size: 0, @border-color: inherit) when (@direction = right) {
@m-size: @size + (@border-size*2);
&:after {
left: 100%;
top: @offset;
margin-top: -@size;
border-top: @size solid transparent;
border-bottom: @size solid transparent;
border-left: @size solid @color;
}
&:before {
left: 100%;
top: @offset;
margin-top: -@m-size;
border-top: @m-size solid transparent;
border-bottom: @m-size solid transparent;
border-left: @m-size solid;
border-left-color: @border-color;
}
}
.arrow(@size, @color, @direction, @offset, @border-size: 0, @border-color: inherit) when (@direction = left) {
@m-size: @size + (@border-size*2);
&:after {
right: 100%;
top: @offset;
margin-top: -@size;
border-top: @size solid transparent;
border-bottom: @size solid transparent;
border-right: @size solid @color;
}
&:before {
right: 100%;
top: @offset;
margin-top: -@m-size;
border-top: @m-size solid transparent;
border-bottom: @m-size solid transparent;
border-right: @m-size solid;
border-right-color: @border-color;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment