Open demo

CSS code

HTML
<div><span class="lbl">Border chevrons</span><div class="tiles">
<div class="tile"><span class="arw arw-chev up" aria-hidden="true"></span>Up</div>
<div class="tile"><span class="arw arw-chev" aria-hidden="true"></span>Right</div>
<div class="tile"><span class="arw arw-chev down" aria-hidden="true"></span>Down</div>
<div class="tile"><span class="arw arw-chev left" aria-hidden="true"></span>Left</div></div></div>
<div><span class="lbl">Border triangles</span><div class="tiles">
<div class="tile"><span class="arw arw-tri up" aria-hidden="true"></span>Up</div>
<div class="tile"><span class="arw arw-tri" aria-hidden="true"></span>Right</div>
<div class="tile"><span class="arw arw-tri down" aria-hidden="true"></span>Down</div>
<div class="tile"><span class="arw arw-tri left" aria-hidden="true"></span>Left</div></div></div>
<div><span class="lbl">clip-path triangles and block arrows</span><div class="tiles">
<div class="tile"><span class="arw arw-clip up" aria-hidden="true"></span>Triangle up</div>
<div class="tile"><span class="arw arw-clip down" aria-hidden="true"></span>Triangle down</div>
<div class="tile"><span class="arw arw-block" aria-hidden="true"></span>Block right</div>
<div class="tile"><span class="arw arw-block left" aria-hidden="true"></span>Block left</div></div></div>
<div><span class="lbl">Thin line arrows</span><div class="tiles">
<div class="tile"><span class="arw arw-line up" aria-hidden="true"></span>Up</div>
<div class="tile"><span class="arw arw-line" aria-hidden="true"></span>Right</div>
<div class="tile"><span class="arw arw-line down" aria-hidden="true"></span>Down</div>
<div class="tile"><span class="arw arw-line left" aria-hidden="true"></span>Left</div></div></div>
<div><span class="lbl">Sized by one custom property</span><div class="tiles">
<div class="tile"><span class="arw arw-chev down" style="--a:14px;--w:2px" aria-hidden="true"></span><code>14px</code></div>
<div class="tile"><span class="arw arw-chev down" style="--a:22px" aria-hidden="true"></span><code>22px</code></div>
<div class="tile"><span class="arw arw-chev down" style="--a:34px;--w:4px" aria-hidden="true"></span><code>34px</code></div>
<div class="tile"><span class="arw arw-chev down" style="--a:46px;--w:5px" aria-hidden="true"></span><code>46px</code></div></div></div>
CSS
/* CSS arrow shapes. Every shape points right by default, is sized by --a (and --w for line weight)
   and takes currentColor. .up, .down and .left rotate it. All arrows are decorative: keep aria-hidden="true". */
.arw{--a:28px;--w:3px;position:relative;display:inline-block;flex:none;width:var(--a);height:var(--a);color:#5b4cf0}
.arw.up{rotate:-90deg}.arw.down{rotate:90deg}.arw.left{rotate:180deg}
/* 1. Border chevron: two borders of a square, turned 45deg */
.arw-chev::before{content:"";position:absolute;top:20%;left:0;width:60%;height:60%;
  border-top:var(--w) solid currentColor;border-right:var(--w) solid currentColor;rotate:45deg}
/* 2. Border triangle: a zero-size box with one coloured border */
.arw-tri{width:calc(var(--a) * .87);height:0;border-style:solid;border-color:transparent;
  border-width:calc(var(--a) / 2) 0 calc(var(--a) / 2) calc(var(--a) * .87);border-left-color:currentColor}
/* 3. clip-path triangle and block arrow */
.arw-clip{background:currentColor;clip-path:polygon(14% 0,100% 50%,14% 100%)}
.arw-block{background:currentColor;clip-path:polygon(0 32%,50% 32%,50% 6%,100% 50%,50% 94%,50% 68%,0 68%)}
/* 4. Thin line arrow: a shaft plus a chevron head */
.arw-line::before{content:"";position:absolute;left:0;right:1px;top:calc(50% - var(--w) / 2);height:var(--w);
  background:currentColor;border-radius:var(--w)}
.arw-line::after{content:"";position:absolute;top:30%;left:52%;width:40%;height:40%;
  border-top:var(--w) solid currentColor;border-right:var(--w) solid currentColor;rotate:45deg}

Bootstrap 5 code

Requires: Bootstrap 5.3.8 CSS

HTML
<div><span class="lbl d-block text-uppercase mb-3">Border chevrons</span><div class="row row-cols-4 g-2 g-sm-3">
<div class="col"><div class="card tile"><div class="card-body d-flex flex-column align-items-center justify-content-center gap-3 p-2"><span class="arw arw-chev up" aria-hidden="true"></span>Up</div></div></div>
<div class="col"><div class="card tile"><div class="card-body d-flex flex-column align-items-center justify-content-center gap-3 p-2"><span class="arw arw-chev" aria-hidden="true"></span>Right</div></div></div>
<div class="col"><div class="card tile"><div class="card-body d-flex flex-column align-items-center justify-content-center gap-3 p-2"><span class="arw arw-chev down" aria-hidden="true"></span>Down</div></div></div>
<div class="col"><div class="card tile"><div class="card-body d-flex flex-column align-items-center justify-content-center gap-3 p-2"><span class="arw arw-chev left" aria-hidden="true"></span>Left</div></div></div></div></div>
<div><span class="lbl d-block text-uppercase mb-3">Border triangles</span><div class="row row-cols-4 g-2 g-sm-3">
<div class="col"><div class="card tile"><div class="card-body d-flex flex-column align-items-center justify-content-center gap-3 p-2"><span class="arw arw-tri up" aria-hidden="true"></span>Up</div></div></div>
<div class="col"><div class="card tile"><div class="card-body d-flex flex-column align-items-center justify-content-center gap-3 p-2"><span class="arw arw-tri" aria-hidden="true"></span>Right</div></div></div>
<div class="col"><div class="card tile"><div class="card-body d-flex flex-column align-items-center justify-content-center gap-3 p-2"><span class="arw arw-tri down" aria-hidden="true"></span>Down</div></div></div>
<div class="col"><div class="card tile"><div class="card-body d-flex flex-column align-items-center justify-content-center gap-3 p-2"><span class="arw arw-tri left" aria-hidden="true"></span>Left</div></div></div></div></div>
<div><span class="lbl d-block text-uppercase mb-3">clip-path triangles and block arrows</span><div class="row row-cols-4 g-2 g-sm-3">
<div class="col"><div class="card tile"><div class="card-body d-flex flex-column align-items-center justify-content-center gap-3 p-2"><span class="arw arw-clip up" aria-hidden="true"></span>Triangle up</div></div></div>
<div class="col"><div class="card tile"><div class="card-body d-flex flex-column align-items-center justify-content-center gap-3 p-2"><span class="arw arw-clip down" aria-hidden="true"></span>Triangle down</div></div></div>
<div class="col"><div class="card tile"><div class="card-body d-flex flex-column align-items-center justify-content-center gap-3 p-2"><span class="arw arw-block" aria-hidden="true"></span>Block right</div></div></div>
<div class="col"><div class="card tile"><div class="card-body d-flex flex-column align-items-center justify-content-center gap-3 p-2"><span class="arw arw-block left" aria-hidden="true"></span>Block left</div></div></div></div></div>
<div><span class="lbl d-block text-uppercase mb-3">Thin line arrows</span><div class="row row-cols-4 g-2 g-sm-3">
<div class="col"><div class="card tile"><div class="card-body d-flex flex-column align-items-center justify-content-center gap-3 p-2"><span class="arw arw-line up" aria-hidden="true"></span>Up</div></div></div>
<div class="col"><div class="card tile"><div class="card-body d-flex flex-column align-items-center justify-content-center gap-3 p-2"><span class="arw arw-line" aria-hidden="true"></span>Right</div></div></div>
<div class="col"><div class="card tile"><div class="card-body d-flex flex-column align-items-center justify-content-center gap-3 p-2"><span class="arw arw-line down" aria-hidden="true"></span>Down</div></div></div>
<div class="col"><div class="card tile"><div class="card-body d-flex flex-column align-items-center justify-content-center gap-3 p-2"><span class="arw arw-line left" aria-hidden="true"></span>Left</div></div></div></div></div>
<div><span class="lbl d-block text-uppercase mb-3">Sized by one custom property</span><div class="row row-cols-4 g-2 g-sm-3">
<div class="col"><div class="card tile"><div class="card-body d-flex flex-column align-items-center justify-content-center gap-3 p-2"><span class="arw arw-chev down" style="--a:14px;--w:2px" aria-hidden="true"></span><code class="font-monospace fw-semibold">14px</code></div></div></div>
<div class="col"><div class="card tile"><div class="card-body d-flex flex-column align-items-center justify-content-center gap-3 p-2"><span class="arw arw-chev down" style="--a:22px" aria-hidden="true"></span><code class="font-monospace fw-semibold">22px</code></div></div></div>
<div class="col"><div class="card tile"><div class="card-body d-flex flex-column align-items-center justify-content-center gap-3 p-2"><span class="arw arw-chev down" style="--a:34px;--w:4px" aria-hidden="true"></span><code class="font-monospace fw-semibold">34px</code></div></div></div>
<div class="col"><div class="card tile"><div class="card-body d-flex flex-column align-items-center justify-content-center gap-3 p-2"><span class="arw arw-chev down" style="--a:46px;--w:5px" aria-hidden="true"></span><code class="font-monospace fw-semibold">46px</code></div></div></div></div></div>
CSS
/* Bootstrap .card tiles in a .row-cols-4 grid; the arrow shapes are the same small CSS as the plain version. */
.tile{--bs-card-border-color:#e4e2ef;--bs-card-border-radius:14px;height:104px;font-size:.78rem;color:#5d5a72}
.tile code{font-size:.74rem;color:#3f3b57}
/* CSS arrow shapes. Every shape points right by default, is sized by --a (and --w for line weight)
   and takes currentColor. .up, .down and .left rotate it. All arrows are decorative: keep aria-hidden="true". */
.arw{--a:28px;--w:3px;position:relative;display:inline-block;flex:none;width:var(--a);height:var(--a);color:#5b4cf0}
.arw.up{rotate:-90deg}.arw.down{rotate:90deg}.arw.left{rotate:180deg}
/* 1. Border chevron: two borders of a square, turned 45deg */
.arw-chev::before{content:"";position:absolute;top:20%;left:0;width:60%;height:60%;
  border-top:var(--w) solid currentColor;border-right:var(--w) solid currentColor;rotate:45deg}
/* 2. Border triangle: a zero-size box with one coloured border */
.arw-tri{width:calc(var(--a) * .87);height:0;border-style:solid;border-color:transparent;
  border-width:calc(var(--a) / 2) 0 calc(var(--a) / 2) calc(var(--a) * .87);border-left-color:currentColor}
/* 3. clip-path triangle and block arrow */
.arw-clip{background:currentColor;clip-path:polygon(14% 0,100% 50%,14% 100%)}
.arw-block{background:currentColor;clip-path:polygon(0 32%,50% 32%,50% 6%,100% 50%,50% 94%,50% 68%,0 68%)}
/* 4. Thin line arrow: a shaft plus a chevron head */
.arw-line::before{content:"";position:absolute;left:0;right:1px;top:calc(50% - var(--w) / 2);height:var(--w);
  background:currentColor;border-radius:var(--w)}
.arw-line::after{content:"";position:absolute;top:30%;left:52%;width:40%;height:40%;
  border-top:var(--w) solid currentColor;border-right:var(--w) solid currentColor;rotate:45deg}

Tailwind 4 code

Requires: Tailwind CSS 4

HTML
<div><span class="mb-3.5 block text-[.72rem] tracking-[.12em] text-[#5d5a72] uppercase">Border chevrons</span><div class="grid grid-cols-4 gap-2 sm:gap-3">
<div class="flex h-[104px] flex-col items-center justify-center gap-3.5 rounded-[14px] border border-[#e4e2ef] bg-white text-[.78rem] text-[#5d5a72]"><span class="arw arw-chev -rotate-90 text-[#5b4cf0]" aria-hidden="true"></span>Up</div>
<div class="flex h-[104px] flex-col items-center justify-center gap-3.5 rounded-[14px] border border-[#e4e2ef] bg-white text-[.78rem] text-[#5d5a72]"><span class="arw arw-chev text-[#5b4cf0]" aria-hidden="true"></span>Right</div>
<div class="flex h-[104px] flex-col items-center justify-center gap-3.5 rounded-[14px] border border-[#e4e2ef] bg-white text-[.78rem] text-[#5d5a72]"><span class="arw arw-chev rotate-90 text-[#5b4cf0]" aria-hidden="true"></span>Down</div>
<div class="flex h-[104px] flex-col items-center justify-center gap-3.5 rounded-[14px] border border-[#e4e2ef] bg-white text-[.78rem] text-[#5d5a72]"><span class="arw arw-chev rotate-180 text-[#5b4cf0]" aria-hidden="true"></span>Left</div></div></div>
<div><span class="mb-3.5 block text-[.72rem] tracking-[.12em] text-[#5d5a72] uppercase">Border triangles</span><div class="grid grid-cols-4 gap-2 sm:gap-3">
<div class="flex h-[104px] flex-col items-center justify-center gap-3.5 rounded-[14px] border border-[#e4e2ef] bg-white text-[.78rem] text-[#5d5a72]"><span class="arw arw-tri -rotate-90 text-[#5b4cf0]" aria-hidden="true"></span>Up</div>
<div class="flex h-[104px] flex-col items-center justify-center gap-3.5 rounded-[14px] border border-[#e4e2ef] bg-white text-[.78rem] text-[#5d5a72]"><span class="arw arw-tri text-[#5b4cf0]" aria-hidden="true"></span>Right</div>
<div class="flex h-[104px] flex-col items-center justify-center gap-3.5 rounded-[14px] border border-[#e4e2ef] bg-white text-[.78rem] text-[#5d5a72]"><span class="arw arw-tri rotate-90 text-[#5b4cf0]" aria-hidden="true"></span>Down</div>
<div class="flex h-[104px] flex-col items-center justify-center gap-3.5 rounded-[14px] border border-[#e4e2ef] bg-white text-[.78rem] text-[#5d5a72]"><span class="arw arw-tri rotate-180 text-[#5b4cf0]" aria-hidden="true"></span>Left</div></div></div>
<div><span class="mb-3.5 block text-[.72rem] tracking-[.12em] text-[#5d5a72] uppercase">clip-path triangles and block arrows</span><div class="grid grid-cols-4 gap-2 sm:gap-3">
<div class="flex h-[104px] flex-col items-center justify-center gap-3.5 rounded-[14px] border border-[#e4e2ef] bg-white text-[.78rem] text-[#5d5a72]"><span class="arw arw-clip -rotate-90 text-[#5b4cf0]" aria-hidden="true"></span>Triangle up</div>
<div class="flex h-[104px] flex-col items-center justify-center gap-3.5 rounded-[14px] border border-[#e4e2ef] bg-white text-[.78rem] text-[#5d5a72]"><span class="arw arw-clip rotate-90 text-[#5b4cf0]" aria-hidden="true"></span>Triangle down</div>
<div class="flex h-[104px] flex-col items-center justify-center gap-3.5 rounded-[14px] border border-[#e4e2ef] bg-white text-[.78rem] text-[#5d5a72]"><span class="arw arw-block text-[#5b4cf0]" aria-hidden="true"></span>Block right</div>
<div class="flex h-[104px] flex-col items-center justify-center gap-3.5 rounded-[14px] border border-[#e4e2ef] bg-white text-[.78rem] text-[#5d5a72]"><span class="arw arw-block rotate-180 text-[#5b4cf0]" aria-hidden="true"></span>Block left</div></div></div>
<div><span class="mb-3.5 block text-[.72rem] tracking-[.12em] text-[#5d5a72] uppercase">Thin line arrows</span><div class="grid grid-cols-4 gap-2 sm:gap-3">
<div class="flex h-[104px] flex-col items-center justify-center gap-3.5 rounded-[14px] border border-[#e4e2ef] bg-white text-[.78rem] text-[#5d5a72]"><span class="arw arw-line -rotate-90 text-[#5b4cf0]" aria-hidden="true"></span>Up</div>
<div class="flex h-[104px] flex-col items-center justify-center gap-3.5 rounded-[14px] border border-[#e4e2ef] bg-white text-[.78rem] text-[#5d5a72]"><span class="arw arw-line text-[#5b4cf0]" aria-hidden="true"></span>Right</div>
<div class="flex h-[104px] flex-col items-center justify-center gap-3.5 rounded-[14px] border border-[#e4e2ef] bg-white text-[.78rem] text-[#5d5a72]"><span class="arw arw-line rotate-90 text-[#5b4cf0]" aria-hidden="true"></span>Down</div>
<div class="flex h-[104px] flex-col items-center justify-center gap-3.5 rounded-[14px] border border-[#e4e2ef] bg-white text-[.78rem] text-[#5d5a72]"><span class="arw arw-line rotate-180 text-[#5b4cf0]" aria-hidden="true"></span>Left</div></div></div>
<div><span class="mb-3.5 block text-[.72rem] tracking-[.12em] text-[#5d5a72] uppercase">Sized by one custom property</span><div class="grid grid-cols-4 gap-2 sm:gap-3">
<div class="flex h-[104px] flex-col items-center justify-center gap-3.5 rounded-[14px] border border-[#e4e2ef] bg-white text-[.78rem] text-[#5d5a72]"><span class="arw arw-chev rotate-90 text-[#5b4cf0] [--a:14px] [--w:2px]" aria-hidden="true"></span><code class="font-mono text-[.74rem] font-semibold text-[#3f3b57]">14px</code></div>
<div class="flex h-[104px] flex-col items-center justify-center gap-3.5 rounded-[14px] border border-[#e4e2ef] bg-white text-[.78rem] text-[#5d5a72]"><span class="arw arw-chev rotate-90 text-[#5b4cf0] [--a:22px]" aria-hidden="true"></span><code class="font-mono text-[.74rem] font-semibold text-[#3f3b57]">22px</code></div>
<div class="flex h-[104px] flex-col items-center justify-center gap-3.5 rounded-[14px] border border-[#e4e2ef] bg-white text-[.78rem] text-[#5d5a72]"><span class="arw arw-chev rotate-90 text-[#5b4cf0] [--a:34px] [--w:4px]" aria-hidden="true"></span><code class="font-mono text-[.74rem] font-semibold text-[#3f3b57]">34px</code></div>
<div class="flex h-[104px] flex-col items-center justify-center gap-3.5 rounded-[14px] border border-[#e4e2ef] bg-white text-[.78rem] text-[#5d5a72]"><span class="arw arw-chev rotate-90 text-[#5b4cf0] [--a:46px] [--w:5px]" aria-hidden="true"></span><code class="font-mono text-[.74rem] font-semibold text-[#3f3b57]">46px</code></div></div></div>
CSS
/* Arrow shapes as utilities. Each points right, is sized by --a (default 28px) and --w (line weight, default 3px)
   and takes the text colour. Turn it with -rotate-90 (up), rotate-90 (down) or rotate-180 (left). */
@utility arw{position:relative;display:inline-block;flex:none;width:var(--a,28px);height:var(--a,28px)}
@utility arw-chev{&::before{content:"";position:absolute;top:20%;left:0;width:60%;height:60%;
  border-top:var(--w,3px) solid currentColor;border-right:var(--w,3px) solid currentColor;rotate:45deg}}
@utility arw-tri{width:calc(var(--a,28px) * .87);height:0;border-style:solid;border-color:transparent;
  border-width:calc(var(--a,28px) / 2) 0 calc(var(--a,28px) / 2) calc(var(--a,28px) * .87);border-left-color:currentColor}
@utility arw-clip{background:currentColor;clip-path:polygon(14% 0,100% 50%,14% 100%)}
@utility arw-block{background:currentColor;clip-path:polygon(0 32%,50% 32%,50% 6%,100% 50%,50% 94%,50% 68%,0 68%)}
@utility arw-line{
  &::before{content:"";position:absolute;left:0;right:1px;top:calc(50% - var(--w,3px) / 2);height:var(--w,3px);background:currentColor;border-radius:var(--w,3px)}
  &::after{content:"";position:absolute;top:30%;left:52%;width:40%;height:40%;
    border-top:var(--w,3px) solid currentColor;border-right:var(--w,3px) solid currentColor;rotate:45deg}}

About this set

Four ways to draw an arrow with CSS alone, each shown pointing up, right, down and left, plus a row that shows one shape at four sizes. The border chevron is a square with only its top and right borders, turned 45 degrees; it is the arrow most interfaces need for links, accordions and pagers. The border triangle is a zero-size box with one coloured border, the classic way to draw a caret or a tooltip pointer. The clip-path triangle and block arrow cut a filled box with polygon(), which gives sharper edges and lets you fill the arrow with a gradient. The thin line arrow is a shaft plus a chevron head built from two pseudo-elements, the style used for read more links and carousels. Every shape points right by default and is turned with a rotate class, so there is one rule per shape rather than four. Size comes from a single custom property, –a, and line weight from –w; the colour is currentColor, so an arrow follows the text colour of whatever it sits in. All arrows are empty spans marked aria-hidden, because an arrow on its own carries no meaning for a screen reader.

What’s included

  • Four techniques: border chevron, border triangle, clip-path polygon and line arrow
  • One rule per shape, turned with up, down and left rotate classes
  • Sized by one custom property (--a), line weight by --w
  • Coloured with currentColor, so arrows follow the surrounding text
  • Tailwind version ships each shape as an @utility

Accessibility

The arrows are decorative empty spans with aria-hidden="true", so they are never announced. Each demo tile carries a visible text label for the direction. There is nothing interactive and nothing animated in this set.

Customise it

Set --a for size and --w for line weight on any .arw element, and change color to recolour it. In Tailwind use the arw and arw-chev, arw-tri, arw-clip, arw-block or arw-line utilities with [--a:…] and a text- colour, and -rotate-90, rotate-90 or rotate-180 for direction.