Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make diagonal circle border gradient?

I have a problem with CSS3. I don't know how to make a diagonal round gradient border like that: circle example

I found something like this:

.box {
  width: 250px;
  height: 250px;
  margin: auto;
  background: #eee;
  border: 20px solid transparent;
  -moz-border-image: -moz-linear-gradient(top left, #3acfd5 0%, #3a4ed5 100%);
  -webkit-border-image: -webkit-linear-gradient(top left, #3acfd5 0%, #3a4ed5 100%);
  border-image: linear-gradient(to bottom right, #3acfd5 0%, #3a4ed5 100%);
  border-image-slice: 1;
}
<div class="box"></div>

But unfortunately this works only with squares.

Any help would be appreciated.

like image 645
kuba12 Avatar asked Jan 03 '16 22:01

kuba12


1 Answers

Conical gradient is a gradient which goes along the circular arc around a center. This is what we see in color wheels. As Paulie_D had noted, these are currently not possible with CSS but Lea Verou has developed a polyfill for it.

Having said that, what you are looking for doesn't seem to be a conical gradient, it is normal angled linear gradient but applied only to the borders. This cannot be achieved through CSS border-image property because of how it is intended to work as per specs.

A box's backgrounds, but not its border-image, are clipped to the appropriate curve


If the center portion of the circle is a solid color then the approach mentioned in Vitorino's answer can be used. If it is not a solid color (that is, the page background is a gradient or an image which needs to show through) then it would not help. The following approaches can be used for that case.

Using Mask Image:

This approach uses a circular mask image to mask the inner portion of the circle. This makes it look as though only the border has the gradient applied to it. The drawback is that this feature is currently supported only in Webkit powered browsers.

.border-gradient-mask {
  height: 200px;
  width: 200px;
  border-radius: 50%;
  background-image: linear-gradient(to bottom left, #7B73A4 0%, #150E5E 100%);
  -webkit-mask-image: radial-gradient(circle at center, transparent 57%, white 58%);
  mask-image: radial-gradient(circle at center, transparent 57%, white 58%);
}
body {
  background: radial-gradient(circle at center, sandybrown, chocolate);
}
<div class="border-gradient-mask"></div>

Using SVG Shape or Mask:

The other approach is to use SVG circle element to create the circle and then assign the gradient to the stroke property. The gradient also has a gradientTransform applied to it because that is the only way to produce angled linear gradients with SVG.

.border-gradient-svg {
  position: relative;
  height: 200px;
  width: 200px;
  border-radius: 50%;
}
.border-gradient-svg svg {
  position: absolute;
  top: 0px;
  left: 0px;
  height: 100%;
  width: 100%;
}
.border-gradient-svg circle {
  fill: transparent;
  stroke: url(#grad);
  stroke-width: 8;
}
body {
  background: radial-gradient(circle at center, sandybrown, chocolate);
}
<div class="border-gradient-svg">
  <svg viewBox="0 0 100 100">
    <defs>
      <linearGradient id="grad" gradientUnits="objectBoundingBox" gradientTransform="rotate(135 0.5 0.5)">
        <stop offset="0%" stop-color="#7B73A4" />
        <stop offset="100%" stop-color="#150E5E" />
      </linearGradient>
    </defs>
    <circle r="46" cx="50" cy="50" />
  </svg>
</div>

The same can be achieved by using SVG mask also. All that is needed is to create a mask with two circle elements, fill the larger circle with white, smaller circle with black and then apply the mask to our original circle element. The area occupied by smaller circle (with black fill) will be transparent.

.border-gradient-svg {
  position: relative;
  height: 200px;
  width: 200px;
  border-radius: 50%;
}
.border-gradient-svg svg {
  position: absolute;
  top: 0px;
  left: 0px;
  height: 100%;
  width: 100%;
}
.border-gradient-svg .grad-border {
  fill: url(#grad);
  mask: url(#masker);
}
body {
  background: radial-gradient(circle at center, sandybrown, chocolate);
}
<div class="border-gradient-svg">
  <svg viewBox="0 0 100 100">
    <defs>
      <linearGradient id="grad" gradientUnits="objectBoundingBox" gradientTransform="rotate(135 0.5 0.5)">
        <stop offset="0%" stop-color="#7B73A4" />
        <stop offset="100%" stop-color="#150E5E" />
      </linearGradient>
      <mask id="masker" x="0" y="0" width="100" height="100">
        <circle r="50" cx="50" cy="50" fill="#fff" />
        <circle r="42" cx="50" cy="50" fill="#000" />
      </mask>
    </defs>
    <circle r="50" cx="50" cy="50" class="grad-border"/>
  </svg>
</div>

Using Clip Path:

Another approach to creating this would be to use a clip-path (with inline SVG) with clip-rule set to evenodd. Advantage of clip path solution over the others is that this will trigger hover effects only while hovering on filled area (and not the transparent area). The drawback is that IE doesn't support clip paths (even with SVG).

.border-gradient-clip {
  height: 200px;
  width: 200px;
  border-radius: 50%;
  background-image: linear-gradient(to bottom left, #7B73A4 0%, #150E5E 100%);
  -webkit-clip-path: url(#clipper);
  clip-path: url(#clipper);
}
body {
  background: radial-gradient(circle at center, sandybrown, chocolate);
}
<svg width="0" height="0">
  <defs>
    <clipPath id="clipper" clipPathUnits="objectBoundingBox">
      <path d="M0,0.5 a0.5,0.5 0 1,0 1,0 a0.5,0.5 0 1,0 -1,0z M0.08,0.5 a0.42,0.42 0 1,0 0.84,0 a0.42,0.42 0 1,0 -0.84,0z" clip-rule="evenodd" />
    </clipPath>
  </defs>
</svg>
<div class="border-gradient-clip"></div>
like image 157
Harry Avatar answered Sep 19 '22 08:09

Harry