<div class="test test1">Both my arrow and its border are handled with a mixin!</div>
<div class="test test2">My arrow is handled with a mixin! heeelo fg</div>
/* 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: 20%;
  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;
  }
}
View Compiled

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. //cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js