How can I create a round arrow with only HTML and CSS?

Solution 1:

You could use a pseudo element to generate the triangle (using the famous border hack).

After that, you would be able to use a thick border on the actual element (with a border-radius of 50% to make it a circle). This allows you to rotate the arrow to your liking.

div {
  border: 20px solid transparent;
  border-top-color: black;
  border-left-color: black;
  height: 100px;
  width: 100px;
  border-radius: 50%;
  position: relative;
  -webkit-transform: rotate(-45deg);
  -ms-transform: rotate(-45deg);
  transform: rotate(-45deg);
  margin:30px auto;
}
div:before {
  content: "";
  position: absolute;
  top: -20px;
  left: 80%;
  height: 0;
  width: 0;
  border-left: 30px solid black;
  border-top: 30px solid transparent;
  border-bottom: 30px solid transparent;
  -webkit-transform: rotate(45deg);
  -ms-transform: rotate(45deg);
  transform: rotate(45deg);
}


/*BELOW IS FOR DEMO ONLY*/

div:hover {
  -webkit-transform: rotate(315deg);
  -ms-transform: rotate(315deg);
  transform: rotate(315deg);
  transition: all 0.8s;
}
html {
  text-align:center;
  color:white;
  font-size:30px;
  height: 100%;
  background: rgb(79, 79, 79);
  /* Old browsers */
  background: -moz-radial-gradient(center, ellipse cover, rgba(79, 79, 79, 1) 0%, rgba(34, 34, 34, 1) 100%);
  /* FF3.6+ */
  background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, rgba(79, 79, 79, 1)), color-stop(100%, rgba(34, 34, 34, 1)));
  /* Chrome,Safari4+ */
  background: -webkit-radial-gradient(center, ellipse cover, rgba(79, 79, 79, 1) 0%, rgba(34, 34, 34, 1) 100%);
  /* Chrome10+,Safari5.1+ */
  background: -o-radial-gradient(center, ellipse cover, rgba(79, 79, 79, 1) 0%, rgba(34, 34, 34, 1) 100%);
  /* Opera 12+ */
  background: -ms-radial-gradient(center, ellipse cover, rgba(79, 79, 79, 1) 0%, rgba(34, 34, 34, 1) 100%);
  /* IE10+ */
  background: radial-gradient(ellipse at center, rgba(79, 79, 79, 1) 0%, rgba(34, 34, 34, 1) 100%);
  /* W3C */
  filter: progid: DXImageTransform.Microsoft.gradient(startColorstr='#4f4f4f', endColorstr='#222222', GradientType=1);
  /* IE6-9 fallback on horizontal gradient */
}
HOVER ME
<div></div>

If you then wanted to lengthen the arrow, you could make the bottom border visible. For example;

div {
  border: 20px solid transparent;
  border-top-color: black;
  border-left-color: black;
  border-bottom-color: black;
  height: 100px;
  width: 100px;
  border-radius: 50%;
  position: relative;
  transform: rotate(-45deg);
  margin:30px auto;
}
div:before {
  content: "";
  position: absolute;
  top: -20px;
  left: 80%;
  height: 0;
  width: 0;
  border-left: 30px solid black;
  border-top: 30px solid transparent;
  border-bottom: 30px solid transparent;
  transform: rotate(45deg);
}


/*BELOW IS FOR DEMO ONLY*/

div:hover {
  transform: rotate(315deg);
  transition: all 0.8s;
}
html {
  text-align:center;
  color:white;
  font-size:30px;
  height: 100%;
  background: rgb(79, 79, 79);
  /* Old browsers */
  background: -moz-radial-gradient(center, ellipse cover, rgba(79, 79, 79, 1) 0%, rgba(34, 34, 34, 1) 100%);
  /* FF3.6+ */
  background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, rgba(79, 79, 79, 1)), color-stop(100%, rgba(34, 34, 34, 1)));
  /* Chrome,Safari4+ */
  background: -webkit-radial-gradient(center, ellipse cover, rgba(79, 79, 79, 1) 0%, rgba(34, 34, 34, 1) 100%);
  /* Chrome10+,Safari5.1+ */
  background: -o-radial-gradient(center, ellipse cover, rgba(79, 79, 79, 1) 0%, rgba(34, 34, 34, 1) 100%);
  /* Opera 12+ */
  background: -ms-radial-gradient(center, ellipse cover, rgba(79, 79, 79, 1) 0%, rgba(34, 34, 34, 1) 100%);
  /* IE10+ */
  background: radial-gradient(ellipse at center, rgba(79, 79, 79, 1) 0%, rgba(34, 34, 34, 1) 100%);
  /* W3C */
  filter: progid: DXImageTransform.Microsoft.gradient(startColorstr='#4f4f4f', endColorstr='#222222', GradientType=1);
  /* IE6-9 fallback on horizontal gradient */
}
HOVER ME
<div></div>

Solution 2:

SVG solution

The shape is really simple to create in SVG.

For the svg interested:

<svg width="200px" height="200px" viewbox="0 0 400 400">
  <path stroke="#000" stroke-width="50" fill="none"
        d="M200 350 A 100 100 0 0 1 200 150
           M200 150 200 125 225 150 200 175Z"/>
</svg>

Can i use it?

Solution 3:

I have created this little thing in CSS, you can look at the code to see how it works.

Note: this does need a solid background.

.arrow {
  width: 200px;
  height: 200px;
  border: 6px solid;
  border-radius: 50%;
  position: relative;
}
.arrow:before {
  content: "";
  display: block;
  width: 10px;
  height: 50px;
  background: #fff;
  position: absolute;
  bottom: 0;
  top: 0;
  right: -6px;
  margin: auto;
}
.arrow:after {
  content: "";
  width: 0;
  height: 0;
  border-left: 20px solid transparent;
  border-right: 20px solid transparent;
  border-top: 20px solid #000;
  position: absolute;
  bottom: 106px;
  right: -20px;
}
<div class="arrow"></div>

Solution 4:

Here's another way to do it using clip-paths instead of messing around with borders.

Demo - http://jsfiddle.net/r8rd0yde/4/

.arrow {
  position: relative;
  padding: 20px;
  width: 100px;
  height: 100px;
}
.circle {
  position: absolute;
  box-sizing: border-box;
  height: 100px;
  width: 100px;
  border: 15px solid #000;
  border-radius: 50%;
  -webkit-clip-path: inset(0 50% 0 0);
  clip-path: inset(0 50% 0 0);
}
.triangle {
  position: absolute;
  width: 35px;
  height: 30px;
  background: #000;
  margin-top: -6px;
  margin-left: 38px;
  -webkit-clip-path: polygon(50% 0, 0% 100%, 100% 100%);
  clip-path: polygon(50% 0, 0% 100%, 100% 100%);
  -moz-transform: rotate(90deg);
  -webkit-transform: rotate(90deg);
  -o-transform: rotate(90deg);
  -ms-transform: rotate(90deg);
  transform: rotate(90deg);
}
/* JUST FOR DEMO */

.arrow:hover {
  -webkit-transform: rotate(720deg);
  -ms-transform: rotate(720deg);
  transform: rotate(720deg);
  transition: all 1.2s;
}
<div class="arrow">
  <div class="circle"></div>
  <div class="triangle"></div>
</div>