3

I'm trying to create a circle with CSS that has a gradient border but also a transparent inner so that it looks like this:

enter image description here

There are solutions to create a gradient border if the inner is not transparent, which my below snippet is based on, but they work in principle by overlaying a one-coloured div over the gradient.

>>JSFIDDLE<<

>>SNIPPET<<

#cont{
background: -webkit-linear-gradient(left top, crimson 0%, #f90 100%);
width: 150px;
height: 150px;
border-radius: 1000px;
padding: 5px;
}

#box{
background: #fff;
width: 150px;
height: 150px;
border-radius: 1000px;
}

#example {

background: url(http://blogs.taz.de/hausblog/files/2017/12/20171208_FB_reuters2.png);
}
<div id="example">
<div id="cont">
<div id="box"></div>
</div>
</div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415
AlphaX
  • 615
  • 1
  • 11
  • 25
  • 1
    What about using the same background as your "example" div?. If I replace `background: #fff` with `background: url(http://blogs.taz.de/hausblog/files/2017/12/20171208_FB_reuters2.png)` in your example, it seems to work. You might need to futz with `background-position` to get it to line up correctly though, so I didn't want to answer completely. – Heretic Monkey Feb 25 '18 at 16:12
  • Thanks Mike. It's actually a bit more complicated on the actual page (circle being on a transparent div that is again on top of a background img), so this work-around wouldnt work. – AlphaX Feb 25 '18 at 16:14
  • There is no reason to include the link to JS Fiddle because you've already done the right thing and created a Code Snippet right here. – Scott Marcus Feb 25 '18 at 16:31
  • @ScottMarcus people here sometimes were annoyed if there was no JSFIDDLE for them to play around and I can understand from a convenience perspective. – AlphaX Feb 25 '18 at 20:48
  • No one is going to ask you for a Fiddle if you include a working Code Snippet. You can play around in a code snippet even more easily because you don't need to leave the page. – Scott Marcus Feb 26 '18 at 00:10

3 Answers3

4

I think the best way is linear-gradient with SVG. The idea is to create a circle and fill its stroke with a gradient.

body {
  background: url(https://picsum.photos/id/1026/800/800);
}

text {
  font-size:8em
}
<svg viewBox='0 0 200 200' width=150 height=150>
  <!-- define the gradient -->
  <defs>
    <!-- x1,y1,x2,y2 are used to define the gradient direction -->
    <linearGradient id="linear" x1="0%" y1="0%" x2="100%" y2="60%">
      <!-- start color at 0%-->
      <stop offset="0%"   stop-color="crimson"/>
      <!-- end color at 100%-->
      <stop offset="100%" stop-color="#f90"/>
    </linearGradient>
  </defs>
  <!-- Create an svg circle at [100,100] with radius of 90
       make the border-width 6 (stroke-width) fill it with gradient (stroke)
       and make the content of circle transparent (fill)
  --->
  <circle cx="100" cy="100" r="90" stroke="url(#linear)" stroke-width="6" fill="transparent" />
  <!-- Create a text element at the postion [70,140] -->
  <text x="70" y="140" fill="white">7</text>
</svg>

That you can also use as background:

body {
  background: url(https://picsum.photos/id/1026/800/800);
}

#count {
  background: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" width="150" height="150"><defs><linearGradient id="linear" x1="0%" y1="0%" x2="100%" y2="60%"><stop offset="0%"   stop-color="crimson"/><stop offset="100%" stop-color="%23f90"/></linearGradient></defs><circle cx="100" cy="100" r="90" stroke="url(%23linear)" stroke-width="6" fill="transparent" /></svg>') no-repeat;
  text-align: center;
  color: #fff;
  font-size: 8em;
  width: 150px;
  height: 150px;
}
<div id="count">
  7
</div>

UPDATE

Now you can rely on mask to get this effect without using SVG:

body {
  background: url(https://picsum.photos/id/1026/800/800);
}

#count{
  text-align: center;
  color: #fff;
  font-size: 8em;
  width: 150px;
  height: 150px;
  position:relative;
}

#count::before {
  content:"";
  position:absolute;
  top:0;
  left:0;
  right:0;
  bottom:0;
  border-radius:50%;
  background:linear-gradient(crimson,#f90);
  -webkit-mask:radial-gradient(farthest-side, transparent calc(100% - 8px),#fff 0);
}
<div id="count">
  7
</div>

Related: Border Gradient with Border Radius

Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • 1
    Impressive Temani! I dont understand svg code tbh - could you elaborate on the code provided so I could tailor it to my needs? Thanks so much!!! – AlphaX Feb 25 '18 at 20:00
  • @AlphaX yes sure ;) i will add more comments :) – Temani Afif Feb 25 '18 at 20:01
  • @AlphaX i added more comment and a link ... you will only need to adjust the gradient color if needed and change the height/width of the SVG .. same thing with background ... as you can see i used the same svg code and put it as background image – Temani Afif Feb 25 '18 at 20:06
  • 1
    Thank you so much Temani! I really didnt think it would be possible! I will have a read and amend as needed! – AlphaX Feb 25 '18 at 20:14
1

Here is a CodePen example: (https://codepen.io/lazercaveman/pen/rNKbxdq) of how to solve this (or something similar) using CSS and implement a fully transparent loading spinner with angular gradient using CSS.

.spinner-icon {
  &:before {
    background-image: conic-gradient(
      transparent 72deg,
      #fff 360deg
    );
    mask: radial-gradient(
      farthest-side,
      transparent calc(100% - 12px),
      #fff 0
    );
  }
}

.bg-container {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  background: linear-gradient(217deg, rgba(255,0,0,.8), rgba(255,0,0,0) 70.71%),
            linear-gradient(127deg, rgba(0,255,0,.8), rgba(0,255,0,0) 70.71%),
            linear-gradient(336deg, rgba(0,0,255,.8), rgba(0,0,255,0) 70.71%);
  border-radius: 12px;
  
}
0

Set the color of the inner div to match the surrounding background and populate the inner div with data that is vertically and horizontally aligned to the middle (there are many ways to do that, I'm doing it in a "down and dirty" way here).

#cont{
background: -webkit-linear-gradient(left top, crimson 0%, #f90 100%);
width: 150px;
height: 150px;
border-radius: 1000px;
padding: 5px;
}

#box{
background: url(http://blogs.taz.de/hausblog/files/2017/12/20171208_FB_reuters2.png);
width: 150px;
height: 150px;
border-radius: 1000px;
text-align:center;
font-size:7em;
color:#FFF;
display:table-cell;
vertical-align:middle;
font-family:Calibri, Arial, Helvetica, sans-serif;
}

#example {

background: url(http://blogs.taz.de/hausblog/files/2017/12/20171208_FB_reuters2.png);
}
<div id="example">
<div id="cont">
<div id="box">7</div>
</div>
</div>
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
  • 1
    ... Pretty sure that's exactly what I said in my comment, and the OP said that it wasn't working for him... – Heretic Monkey Feb 25 '18 at 16:38
  • @MikeMcCaughan I didn't see your comment, but if this doesn't work for the OP, then he should explain his situation more clearly so we can more accurately help him. – Scott Marcus Feb 25 '18 at 16:39
  • Hi Scott, thank you. However, my starting solution already has a coloured inner, whilst the solution I need requires a transparent inner as per my original post. I start to feel confirmed that it's not possible with CSS and I may have to create an image with photoshop instead – AlphaX Feb 25 '18 at 17:10
  • @AlphaX Can you explain why you must have a transparent background? Isn't the goal to get the look you showed? – Scott Marcus Feb 25 '18 at 17:17