Skip to content

Instantly share code, notes, and snippets.

@elyseholladay
Last active December 21, 2023 19:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save elyseholladay/90cbd1c319e2c546f52f915ded2a921e to your computer and use it in GitHub Desktop.
Save elyseholladay/90cbd1c319e2c546f52f915ded2a921e to your computer and use it in GitHub Desktop.
CSS triangle
<div class="preview-section">
<h2>CSS Triangle with optional Border</h2>
<p>Creates a CSS triangle of any size that can be plain (borderless), or
have an optional border. The size and color of the border are customizable.
The triangle can be in any direction (up, down, right, left).
By default the triangle is positioned in the vertical or horizontal
center; it can have an optional offset (a percentage, positive or
negative) to be moved in any direction.</p>
<div class="tests">
<div class="test-plain-left">plain arrow, left facing, centered</div>
<div class="test-plain-right">plain arrow, right facing, centered</div>
<div class="test-plain-up">plain arrow, up facing, centered</div>
<div class="test-plain-up-20offset">plain arrow, up facing, 20% offset</div>
<div class="test-plain-down-big">plain arrow, down facing, really big</div>
<div class="test-plain-down-neg20offset">plain arrow, down facing, -20% offset</div>
<div class="test-border-left">left facing arrow, default border</div>
<div class="test-border-right">right facing arrow, custom border</div>
<div class="test-border-up-20offset">up facing arrow, border, 20% offset</div>
<div class="test-border-down-neg20offset">down facing arrow, border, -20% offset</div>
<div class="test-border-down-big">down facing arrow, really big border</div>
<div class="test-left-shadow-tooltip">left arrow, transparent tooltip style</div>
<div class="test-right-shadow-tooltip-small-arrow">small right arrow, transparent tooltip style</div>
<div class="test-up-shadow-offset-tooltip-small-arrow">small up arrow with offset, transparent tooltip style</div>
</div>
</div>
<div class="preview-section">
<h2>CSS Triangle with Box Shadow</h2>
<p>Creates a CSS triangle of any size that always has a box shadow.
The box shadow offsets (x and y), blur, and color can be customized.
The triangle can be in any direction (up, down, right, left).
By default the triangle is positioned in the vertical or horizontal
center; it can have an optional offset (a percentage, positive or
negative) to be moved in any direction.</p>
<p>Notes/Limitations: Typically you want the shadow x and y offsets to be
the same, to make a shadow that is the same all the way around. We could
force the offsets to be the same property so they are always the same if
we prefer less flexibility (or think we won't use both offsets seperately.)
The blur can't be larger than the offset, or the shadow will be visible in
between the box and the border. See the last test item for an example.</p>
<div class="tests">
<div class="test-left-shadow-default">left arrow, default shadow</div>
<div class="test-up-shadow-fuzzy">up arrow, fuzzy shadow</div>
<div class="test-right-shadow-small">small right arrow, default shadow</div>
<div class="test-down-shadow-big">big down arrow, small shadow</div>
<div class="test-right-shadow-custom">right arrow, shadow custom</div>
<div class="test-down-shadow-small-offset">small down arrow, offset, default shadow</div>
<div class="test-down-shadow-border">down offset arrow, shadow as border</div>
<div class="test-left-im-ugly">visible border blur</div>
</div>
</div>
// ----
// Sass (v3.4.21)
// Compass (v1.0.3)
// ----
@import url('https://fonts.googleapis.com/css?family=Rubik:300,500');
body {
margin: 40px;
font-family: "Rubik";
color: mix(slategray,dimgray,40%);
font-weight: 300;
line-height: 1.6;
}
* {
box-sizing: border-box;
}
h2 { font-weight: 500; }
.preview-section {
margin: 40px 0;
padding-bottom: 40px;
border-bottom: 1px solid gainsboro;
p { margin-bottom: 40px; }
}
.tests {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
[class*="test-"] {
flex: 0 0 300px;
margin: 0 20px 40px 0;
border-radius: 3px;
height: 100px;
line-height: 100px;
text-align: center;
background: gainsboro;
color: white;
font-size: 12px;
font-weight: 500;
text-transform: uppercase;
}
/* -------------------------------------------------------------------------- */
/* TRIANGLE with OPTIONAL BORDER -------------------------------------------- */
/* -------------------------------------------------------------------------- */
// Creates a CSS triangle of any size that can be plain (borderless), or have
// an optional border. The size and color of the border are customizable.
// The triangle can be in any direction (up, down, right, left). By default
// the triangle is positioned in the vertical or horizontal center; it can
// have an optional offset (a percentage, positive or negative, passed in as
// a unitless number). Note that a large offset % may move the arrow past
// the parent element it's supposed to be connected to.
// Defaults: left 20px sized arrow with no border, centered
// Border defaults (has-border set to true but no changes): #999 5px
@mixin triangle(
$direction: left,
$size: 16px,
$color: currentColor,
$has-border: false,
$border-color: #d3d3d3,
$border-size: 2px,
$offset: 0) {
// make the parent element relative to allow for the pseudo element
// that generates the arrow to be absolutely positioned
position: relative;
// DIRECTION
// The direction of the arrow corresponds to the inverse border.
// A right arrow has transparent right, top, and bottom borders,
// and a colored left border. Therefore:
// an up arrow needs `border-bottom-color`
// a down arrow needs `border-top-color`
// a left arrow needs `border-right-color`
// and a right arrow needs `border-left-color`
// sets a default border direction of bottom, so that the variable
// exists and the mixin won't throw an error if undefined.
$border-direction: bottom;
// taking the $direction parameter, define which border needs to be colored
@if $direction == up {
$border-direction: bottom;
} @else if $direction == down {
$border-direction: top;
} @else if $direction == left {
$border-direction: right;
} @else if $direction == right {
$border-direction: left;
}
// POSITION
// The arrow is on the :after pseudoelement; because we want a border, we
// have to use :after and the faux border triangle on the :before.
// Create the :after pseudo element for the arrow
&:after {
// define all borders as transparent and solid
border: solid transparent;
// create the pseudo content
content: " ";
height: 0;
width: 0;
// absolutely position it against the element
position: absolute;
// COLOR
// Define the color of the arrow, as passed in by parameters.
// As defined in the if statement for direction, this property takes
// either top, bottom, left, or right
border-#{$border-direction}-color: $color;
// SIZE
// Size of the arrow, as passed in by parameters.
border-width: $size;
// POSITION
// Positioning the arrow. If the arrow position is left or right,
// position the arrow in the vertical center of the box,
// if up or down, position the arrow in the horizontal center.
// The negative margin is always the negative of the size of the arrow.
@if $direction == up {
bottom: 100%;
left: 50% + $offset;
margin-left: -$size;
} @else if $direction == down {
top: 100%;
left: 50% + $offset;
margin-left: -$size;
} @else if $direction == left {
right: 100%;
top: 50% + $offset;
margin-top: -$size;
} @else if $direction == right {
left: 100%;
top: 50% + $offset;
margin-top: -$size;
}
}
// BORDER
// with a border around the item and arrow
// the "border" is created by generating another pseudo element :before
// that is a triangle that is slightly larger than the original triangle
// and positioning it underneath so that it looks like a border. tricky!
// if the has-border variable is set to true:
@if $has-border == true {
// add a border on the parent element of the requested size and color
border: $border-size solid $border-color;
// if the border is 1px or 2px, it's aligned properly
// if the border is more than 2px, it's off by 2px
@if $border-size >= 3 {
$border-size: $border-size + 2;
}
// generate the :before pseudoelement to create a second triangle
&:before {
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
// POSITION
// Positioning the arrow. If the arrow position is left or right,
// position the arrow in the vertical center of the box,
// if up or down, position the arrow in the horizontal center.
// The negative margin is always the negative of the size of the arrow.
@if $direction == up {
bottom: 100%;
left: 50% + $offset;
margin-left: -($size+$border-size);
} @else if $direction == down {
top: 100%;
left: 50% + $offset;
margin-left: -($size+$border-size);
} @else if $direction == left {
right: 100%;
top: 50% + $offset;
margin-top: -($size+$border-size);
} @else if $direction == right {
left: 100%;
top: 50% + $offset;
margin-top: -($size+$border-size);
}
// set the border color on the border-direction requested
border-#{$border-direction}-color: $border-color;
// set border width to be the triangle size + requested border-size
border-width: $size + $border-size;
}
}
}
// TESTS for TRIANGLE with BORDER ------------------------------------------ //
// Usage:
// Call the mixin either by
// Defining the properties in order, e.g.
// @include triangle(left, 20px, salmon);
// or for all properties:
// @include triangle(left, 20px, salmon, true, black, 5px, 0);
// OR
// Define only the property/ies you care about by including the var name:
// @include triangle($color: salmon);
// @include triangle($direction: right, $has-border: true, $offset: 20);
// OR
// combine the two!
// @include triangle(up, 20px, olivedrab, $offset: 20);
// Properties in order:
// $direction
// $size
// $color
// $has-border
// $border-color
// $border-size
// $offset
.test-plain-left {
background: salmon;
@include triangle($color: salmon);
}
.test-plain-right {
background: palevioletred;
@include triangle($direction: right, $color: palevioletred);
}
.test-plain-up {
background: sandybrown;
@include triangle($direction: up, $color: sandybrown)
}
.test-plain-up-20offset {
background: olivedrab;
@include triangle($direction: up, $color: olivedrab, $offset: 20);
}
// note that a really big arrow might bump into other elements, since it's
// an absolutely positioned element
.test-plain-down-big {
background: skyblue;
@include triangle(down, 40px, skyblue);
}
.test-plain-down-neg20offset {
background: yellowgreen;
@include triangle($direction: down, $color: yellowgreen, $offset: -20);
}
.test-border-left {
background: #f7f7f7;
color: #b8b8b8;
@include triangle($direction: left, $color: #f7f7f7, $has-border: true);
}
.test-border-right {
background: cornflowerblue;
@include triangle(left, 16px, cornflowerblue, true, navy, 5px);
}
.test-border-up-20offset {
background: plum;
@include triangle(up, 16px, plum, true, darkmagenta, 1px, 20);
}
.test-border-down-neg20offset {
background: wheat;
@include triangle($direction: down, $color: wheat, $has-border: true, $border-color: chocolate, $border-size: 4px, $offset: -20);
}
.test-border-down-big {
background: tomato;
@include triangle($direction: down, $color: tomato, $has-border: true, $border-color: crimson, $border-size: 20px);
}
.test-left-shadow-tooltip {
background: rgba(0, 0, 0, .75);
@include triangle($color: rgba(0, 0, 0, .75));
box-shadow: 3px 3px 8px 0px rgba(0,0,0,.2);
}
.test-right-shadow-tooltip-small-arrow {
background: rgba(0, 0, 0, .75);
@include triangle($direction: right, $color: rgba(0, 0, 0, .75), $size: 10px);
box-shadow: -3px 3px 8px 0px rgba(0,0,0,.2);
}
.test-up-shadow-offset-tooltip-small-arrow {
background: rgba(0, 0, 0, .75);
@include triangle($direction: up, $color: rgba(0, 0, 0, .75), $size: 10px, $offset: 30);
box-shadow: 3px 3px 8px 0px rgba(0,0,0,.2);
}
/* -------------------------------------------------------------------------- */
/* TRIANGLE with SHADOW ----------------------------------------------------- */
/* -------------------------------------------------------------------------- */
// Creates a CSS triangle of any size that always has a box shadow.
// The box shadow offsets (x and y), blur, and color can be customized.
// The triangle can be in any direction (up, down, right, left). By default
// the triangle is positioned in the vertical or horizontal center;
// it can have an optional offset (a percentage, positive or negative)
// to be moved in any direction.
/* box-shadow: offset-x | offset-y | blur-radius | spread-radius | color */
@mixin triangleWithShadow (
$direction: left,
$size: 16px,
$color: currentColor,
$shadow-offset-x: 1px,
$shadow-offset-y: 1px,
$shadow-blur: 2px,
$shadow-color: rgba( 0, 0, 0, 0.2 ),
$offset: 0) {
// make the parent element relative to allow for the pseudo element
// that generates the arrow to be absolutely positioned
position: relative;
// Create the :after pseudo element for the arrow
&:after {
// define all borders as transparent and solid
border: solid transparent;
// create the pseudo content
content: " ";
height: 0;
width: 0;
// absolutely position it against the element
position: absolute;
// position the triangle's transform origin to the center of the box
transform-origin: 50% 50%;
// define the border to be the requested size
border: $size solid;
@if ($direction == up){
top: (-1 * $size) + 1;
left: 50% + $offset;
bottom: auto;
right: auto;
transform: translateX(-50%) rotate(-45deg);
border-color: $color $color transparent transparent;
box-shadow: $shadow-offset-x (-1 * $shadow-offset-y) $shadow-blur 0 $shadow-color;
}
@else if ($direction == down){
bottom: (-1 * $size) + 1;
left: 50% + $offset;
top: auto;
right: auto;
transform: translateX(-50%) rotate(-45deg);
border-color: transparent transparent $color $color;
box-shadow: (-1 * $shadow-offset-x) $shadow-offset-y $shadow-blur 0 $shadow-color;
}
@else if ($direction == left){
left: (-1 * $size) + 1;
top: 50% + $offset;
right: auto;
bottom: auto;
transform: translateY(-50%) rotate(-45deg);
border-color: $color transparent transparent $color;
box-shadow: (-1 * $shadow-offset-x) (-1 * $shadow-offset-y) $shadow-blur 0 $shadow-color;
}
@else if ($direction == right){
right: (-1 * $size) + 1;
top: 50% + $offset;
left: auto;
bottom: auto;
transform: translateY(-50%) rotate(-45deg);
border-color: transparent $color $color transparent;
box-shadow: $shadow-offset-x $shadow-offset-y $shadow-blur 0 $shadow-color;
}
}
}
.test-left-shadow-default {
background: salmon;
box-shadow: 0px 0px 2px 0px rgba( 0, 0, 0, 0.5 );
@include triangleWithShadow($color: salmon);
}
.test-up-shadow-fuzzy {
background: palevioletred;
box-shadow: 0px 0px 6px 3px #b8b8b8;
@include triangleWithShadow(up, $color: palevioletred, $shadow-offset-x: 4px, $shadow-offset-y: 4px, $shadow-blur: 6px, $shadow-color: #b8b8b8);
}
.test-right-shadow-small {
background: cornflowerblue;
box-shadow: 0px 0px 2px 0px rgba( 0, 0, 0, 0.5 );
@include triangleWithShadow($direction: right, $color: cornflowerblue, $size: 10px);
}
.test-down-shadow-big {
background: azure;
color: slategray;
box-shadow: 0px 0px 4px 1px slategray;
@include triangleWithShadow(down, $color: azure, $size: 30px, $shadow-offset-x: 2px, $shadow-offset-y: 2px, $shadow-blur: 2px, $shadow-color: rgba(slategray,.75));
}
.test-right-shadow-custom {
background: yellowgreen;
color: greenyellow;
box-shadow: 0px 0px 20px 5px greenyellow;
@include triangleWithShadow(right, $color: yellowgreen, $shadow-offset-x: 6px, $shadow-offset-y: 6px, $shadow-blur: 10px, $shadow-color: rgba(greenyellow,.75));
}
.test-down-shadow-small-offset {
background: plum;
box-shadow: 0px 0px 2px 0px rgba( 0, 0, 0, 0.5 );
@include triangleWithShadow($direction: down, $color: plum, $size: 10px, $offset: 30);
}
.test-down-shadow-border {
background: gold;
box-shadow: 0 0 0 1px orange;
@include triangleWithShadow(down, 16px, gold, 1px, 1px, 0px, darkorange, -20);
}
.test-left-im-ugly {
background: brown;
box-shadow: 0px 0px 20px 5px chocolate;
@include triangleWithShadow($direction: left, $color: brown, $shadow-blur: 20px, $shadow-color: chocolate);
}
@import url("https://fonts.googleapis.com/css?family=Rubik:300,500");
body {
margin: 40px;
font-family: "Rubik";
color: #6c7279;
font-weight: 300;
line-height: 1.6;
}
* {
box-sizing: border-box;
}
h2 {
font-weight: 500;
}
.preview-section {
margin: 40px 0;
padding-bottom: 40px;
border-bottom: 1px solid gainsboro;
}
.preview-section p {
margin-bottom: 40px;
}
.tests {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
[class*="test-"] {
flex: 0 0 300px;
margin: 0 20px 40px 0;
border-radius: 3px;
height: 100px;
line-height: 100px;
text-align: center;
background: gainsboro;
color: white;
font-size: 12px;
font-weight: 500;
text-transform: uppercase;
}
/* -------------------------------------------------------------------------- */
/* TRIANGLE with OPTIONAL BORDER -------------------------------------------- */
/* -------------------------------------------------------------------------- */
.test-plain-left {
background: salmon;
position: relative;
}
.test-plain-left:after {
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
border-right-color: salmon;
border-width: 16px;
right: 100%;
top: 50%;
margin-top: -16px;
}
.test-plain-right {
background: palevioletred;
position: relative;
}
.test-plain-right:after {
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
border-left-color: palevioletred;
border-width: 16px;
left: 100%;
top: 50%;
margin-top: -16px;
}
.test-plain-up {
background: sandybrown;
position: relative;
}
.test-plain-up:after {
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
border-bottom-color: sandybrown;
border-width: 16px;
bottom: 100%;
left: 50%;
margin-left: -16px;
}
.test-plain-up-20offset {
background: olivedrab;
position: relative;
}
.test-plain-up-20offset:after {
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
border-bottom-color: olivedrab;
border-width: 16px;
bottom: 100%;
left: 70%;
margin-left: -16px;
}
.test-plain-down-big {
background: skyblue;
position: relative;
}
.test-plain-down-big:after {
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
border-top-color: skyblue;
border-width: 40px;
top: 100%;
left: 50%;
margin-left: -40px;
}
.test-plain-down-neg20offset {
background: yellowgreen;
position: relative;
}
.test-plain-down-neg20offset:after {
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
border-top-color: yellowgreen;
border-width: 16px;
top: 100%;
left: 30%;
margin-left: -16px;
}
.test-border-left {
background: #f7f7f7;
color: #b8b8b8;
position: relative;
border: 2px solid #d3d3d3;
}
.test-border-left:after {
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
border-right-color: #f7f7f7;
border-width: 16px;
right: 100%;
top: 50%;
margin-top: -16px;
}
.test-border-left:before {
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
right: 100%;
top: 50%;
margin-top: -18px;
border-right-color: #d3d3d3;
border-width: 18px;
}
.test-border-right {
background: cornflowerblue;
position: relative;
border: 5px solid navy;
}
.test-border-right:after {
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
border-right-color: cornflowerblue;
border-width: 16px;
right: 100%;
top: 50%;
margin-top: -16px;
}
.test-border-right:before {
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
right: 100%;
top: 50%;
margin-top: -23px;
border-right-color: navy;
border-width: 23px;
}
.test-border-up-20offset {
background: plum;
position: relative;
border: 1px solid darkmagenta;
}
.test-border-up-20offset:after {
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
border-bottom-color: plum;
border-width: 16px;
bottom: 100%;
left: 70%;
margin-left: -16px;
}
.test-border-up-20offset:before {
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
bottom: 100%;
left: 70%;
margin-left: -17px;
border-bottom-color: darkmagenta;
border-width: 17px;
}
.test-border-down-neg20offset {
background: wheat;
position: relative;
border: 4px solid chocolate;
}
.test-border-down-neg20offset:after {
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
border-top-color: wheat;
border-width: 16px;
top: 100%;
left: 30%;
margin-left: -16px;
}
.test-border-down-neg20offset:before {
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
top: 100%;
left: 30%;
margin-left: -22px;
border-top-color: chocolate;
border-width: 22px;
}
.test-border-down-big {
background: tomato;
position: relative;
border: 20px solid crimson;
}
.test-border-down-big:after {
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
border-top-color: tomato;
border-width: 16px;
top: 100%;
left: 50%;
margin-left: -16px;
}
.test-border-down-big:before {
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
top: 100%;
left: 50%;
margin-left: -38px;
border-top-color: crimson;
border-width: 38px;
}
.test-left-shadow-tooltip {
background: rgba(0, 0, 0, 0.75);
position: relative;
box-shadow: 3px 3px 8px 0px rgba(0, 0, 0, 0.2);
}
.test-left-shadow-tooltip:after {
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
border-right-color: rgba(0, 0, 0, 0.75);
border-width: 16px;
right: 100%;
top: 50%;
margin-top: -16px;
}
.test-right-shadow-tooltip-small-arrow {
background: rgba(0, 0, 0, 0.75);
position: relative;
box-shadow: -3px 3px 8px 0px rgba(0, 0, 0, 0.2);
}
.test-right-shadow-tooltip-small-arrow:after {
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
border-left-color: rgba(0, 0, 0, 0.75);
border-width: 10px;
left: 100%;
top: 50%;
margin-top: -10px;
}
.test-up-shadow-offset-tooltip-small-arrow {
background: rgba(0, 0, 0, 0.75);
position: relative;
box-shadow: 3px 3px 8px 0px rgba(0, 0, 0, 0.2);
}
.test-up-shadow-offset-tooltip-small-arrow:after {
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
border-bottom-color: rgba(0, 0, 0, 0.75);
border-width: 10px;
bottom: 100%;
left: 80%;
margin-left: -10px;
}
/* -------------------------------------------------------------------------- */
/* TRIANGLE with SHADOW ----------------------------------------------------- */
/* -------------------------------------------------------------------------- */
/* box-shadow: offset-x | offset-y | blur-radius | spread-radius | color */
.test-left-shadow-default {
background: salmon;
box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, 0.5);
position: relative;
}
.test-left-shadow-default:after {
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
transform-origin: 50% 50%;
border: 16px solid;
left: -15px;
top: 50%;
right: auto;
bottom: auto;
transform: translateY(-50%) rotate(-45deg);
border-color: salmon transparent transparent salmon;
box-shadow: -1px -1px 2px 0 rgba(0, 0, 0, 0.2);
}
.test-up-shadow-fuzzy {
background: palevioletred;
box-shadow: 0px 0px 6px 3px #b8b8b8;
position: relative;
}
.test-up-shadow-fuzzy:after {
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
transform-origin: 50% 50%;
border: 16px solid;
top: -15px;
left: 50%;
bottom: auto;
right: auto;
transform: translateX(-50%) rotate(-45deg);
border-color: palevioletred palevioletred transparent transparent;
box-shadow: 4px -4px 6px 0 #b8b8b8;
}
.test-right-shadow-small {
background: cornflowerblue;
box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, 0.5);
position: relative;
}
.test-right-shadow-small:after {
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
transform-origin: 50% 50%;
border: 10px solid;
right: -9px;
top: 50%;
left: auto;
bottom: auto;
transform: translateY(-50%) rotate(-45deg);
border-color: transparent cornflowerblue cornflowerblue transparent;
box-shadow: 1px 1px 2px 0 rgba(0, 0, 0, 0.2);
}
.test-down-shadow-big {
background: azure;
color: slategray;
box-shadow: 0px 0px 4px 1px slategray;
position: relative;
}
.test-down-shadow-big:after {
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
transform-origin: 50% 50%;
border: 30px solid;
bottom: -29px;
left: 50%;
top: auto;
right: auto;
transform: translateX(-50%) rotate(-45deg);
border-color: transparent transparent azure azure;
box-shadow: -2px 2px 2px 0 rgba(112, 128, 144, 0.75);
}
.test-right-shadow-custom {
background: yellowgreen;
color: greenyellow;
box-shadow: 0px 0px 20px 5px greenyellow;
position: relative;
}
.test-right-shadow-custom:after {
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
transform-origin: 50% 50%;
border: 16px solid;
right: -15px;
top: 50%;
left: auto;
bottom: auto;
transform: translateY(-50%) rotate(-45deg);
border-color: transparent yellowgreen yellowgreen transparent;
box-shadow: 6px 6px 10px 0 rgba(173, 255, 47, 0.75);
}
.test-down-shadow-small-offset {
background: plum;
box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, 0.5);
position: relative;
}
.test-down-shadow-small-offset:after {
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
transform-origin: 50% 50%;
border: 10px solid;
bottom: -9px;
left: 80%;
top: auto;
right: auto;
transform: translateX(-50%) rotate(-45deg);
border-color: transparent transparent plum plum;
box-shadow: -1px 1px 2px 0 rgba(0, 0, 0, 0.2);
}
.test-down-shadow-border {
background: gold;
box-shadow: 0 0 0 1px orange;
position: relative;
}
.test-down-shadow-border:after {
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
transform-origin: 50% 50%;
border: 16px solid;
bottom: -15px;
left: 30%;
top: auto;
right: auto;
transform: translateX(-50%) rotate(-45deg);
border-color: transparent transparent gold gold;
box-shadow: -1px 1px 0px 0 darkorange;
}
.test-left-im-ugly {
background: brown;
box-shadow: 0px 0px 20px 5px chocolate;
position: relative;
}
.test-left-im-ugly:after {
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
transform-origin: 50% 50%;
border: 16px solid;
left: -15px;
top: 50%;
right: auto;
bottom: auto;
transform: translateY(-50%) rotate(-45deg);
border-color: brown transparent transparent brown;
box-shadow: -1px -1px 20px 0 chocolate;
}
<div class="preview-section">
<h2>CSS Triangle with optional Border</h2>
<p>Creates a CSS triangle of any size that can be plain (borderless), or
have an optional border. The size and color of the border are customizable.
The triangle can be in any direction (up, down, right, left).
By default the triangle is positioned in the vertical or horizontal
center; it can have an optional offset (a percentage, positive or
negative) to be moved in any direction.</p>
<div class="tests">
<div class="test-plain-left">plain arrow, left facing, centered</div>
<div class="test-plain-right">plain arrow, right facing, centered</div>
<div class="test-plain-up">plain arrow, up facing, centered</div>
<div class="test-plain-up-20offset">plain arrow, up facing, 20% offset</div>
<div class="test-plain-down-big">plain arrow, down facing, really big</div>
<div class="test-plain-down-neg20offset">plain arrow, down facing, -20% offset</div>
<div class="test-border-left">left facing arrow, default border</div>
<div class="test-border-right">right facing arrow, custom border</div>
<div class="test-border-up-20offset">up facing arrow, border, 20% offset</div>
<div class="test-border-down-neg20offset">down facing arrow, border, -20% offset</div>
<div class="test-border-down-big">down facing arrow, really big border</div>
<div class="test-left-shadow-tooltip">left arrow, transparent tooltip style</div>
<div class="test-right-shadow-tooltip-small-arrow">small right arrow, transparent tooltip style</div>
<div class="test-up-shadow-offset-tooltip-small-arrow">small up arrow with offset, transparent tooltip style</div>
</div>
</div>
<div class="preview-section">
<h2>CSS Triangle with Box Shadow</h2>
<p>Creates a CSS triangle of any size that always has a box shadow.
The box shadow offsets (x and y), blur, and color can be customized.
The triangle can be in any direction (up, down, right, left).
By default the triangle is positioned in the vertical or horizontal
center; it can have an optional offset (a percentage, positive or
negative) to be moved in any direction.</p>
<p>Notes/Limitations: Typically you want the shadow x and y offsets to be
the same, to make a shadow that is the same all the way around. We could
force the offsets to be the same property so they are always the same if
we prefer less flexibility (or think we won't use both offsets seperately.)
The blur can't be larger than the offset, or the shadow will be visible in
between the box and the border. See the last test item for an example.</p>
<div class="tests">
<div class="test-left-shadow-default">left arrow, default shadow</div>
<div class="test-up-shadow-fuzzy">up arrow, fuzzy shadow</div>
<div class="test-right-shadow-small">small right arrow, default shadow</div>
<div class="test-down-shadow-big">big down arrow, small shadow</div>
<div class="test-right-shadow-custom">right arrow, shadow custom</div>
<div class="test-down-shadow-small-offset">small down arrow, offset, default shadow</div>
<div class="test-down-shadow-border">down offset arrow, shadow as border</div>
<div class="test-left-im-ugly">visible border blur</div>
</div>
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment