// The mixin @mixin css-arrow($box-edge : bottom, $edge-side : center, $arrow-size : 10px, $edge-side-offset : 0, $fill-color : black, $border-color : none, $border-style : border) { $box-edge-inverse: bottom; $edge-side-pos: $edge-side; $edge-side-pos-value: 0; @if $box-edge == top { $box-edge-inverse: bottom; } @else if $box-edge == right { $box-edge-inverse: left; } @else if $box-edge == bottom { $box-edge-inverse: top; } @else if $box-edge == left { $box-edge-inverse: right; } @if ($box-edge == 'top' or $box-edge == 'bottom') { @if $edge-side == center { $edge-side-pos: left; $edge-side-pos-value: 50%; $edge-side-offset: (-$arrow-size); } } @if ($box-edge == 'left' or $box-edge == 'right') { @if $edge-side == center { $edge-side-pos: top; $edge-side-pos-value: 50%; $edge-side-offset: (-$arrow-size); } } &:after, &:before { content: " "; height: 0; width: 0; position: absolute; pointer-events: none; border: solid rgba(#fff, 0); } &:after { border-color: rgba(#fff, 0); border-width: $arrow-size - 1; #{$box-edge}: (-$arrow-size) - $arrow-size + 2; border-#{$box-edge-inverse}-color: $fill-color; #{$edge-side-pos}: $edge-side-pos-value; margin-#{$edge-side-pos}: $edge-side-offset + 1; } @if $border-style == flag { @include border-radius(2px); &:before { border-color: rgba(#fff, 0); border-width: $arrow-size - 1; #{$box-edge}: (-$arrow-size) - $arrow-size + 2; border-#{$box-edge-inverse}-color: $border-color; #{$edge-side-pos}: $edge-side-pos-value; margin-#{$edge-side-pos}: $edge-side-offset + 2; } } @else { &:before { border-color: rgba(#fff, 0); border-width: $arrow-size; #{$box-edge}: (-$arrow-size) - $arrow-size; border-#{$box-edge-inverse}-color: $border-color; #{$edge-side-pos}: $edge-side-pos-value; margin-#{$edge-side-pos}: $edge-side-offset; } } } // Example uses // @include css-arrow([$box-edge], [$edge-side], [$arrow-size], [$edge-side-offset], [$fill-color], [$border-color], [$border-style]) // $box-edge accepts 'top', 'bottom', 'left', or 'right' // $edge-side accepts 'left', 'right', or 'center' if $box-edge is 'top' or 'bottom', or: // $edge-side accepts 'top', 'bottom', or 'center', if $box-edge is 'left' or 'right' // $arrow-size accepts any standard unit size for css border attribute // $edge-side-offset accepts any standard unit size for css margin attribute // NOTE: $edge-side-offset will be ignored if $edge-side is 'center'. It can also be set to the default of 0 in this case. // $fill-color and $border-color take any color value or variable containing a color // $border-style accepts 'default' or 'flag' - more options are planned, including border width .default { @include css-arrow; } // If $edge-side is not 'center', use $edge-side-offset to offset the arrow from the top, right, bottom, or left side of the parent container .offset { @include css-arrow(bottom, right, 14px, 15px, #ddd); } // Add a second color to create a 1px border effect .border-style { @include css-arrow(top, center, 18px, 0, #ddd, #aaa); } // Adding 'flag' to the end of the mxin drops the :before arrow by 1 pixel to create a shadow effect instead of 1px border effect .flag-style { @include css-arrow(right, center, 20px, 0, #ddd, #aaa, flag); }