Is it possible to create this shape (two partial circles connected together) with CSS?

I tried to fulfill this border for two divs with CSS:

Desired Result

I tried using border-radius , but two partial circles do not compress together: http://jsfiddle.net/uwz6L79w/

  .left { position: absolute; left: 0; top: 0; width: 100px; height: 100px; border-width: 4px; border-color: black white black black; border-style: solid; border-radius: 60px } .right { position: absolute; left: 104px; top: 0; width: 100px; height: 100px; border-width: 4px; border-color: black black black white; border-style: solid; border-radius: 60px; } 
 <div class="left"></div> <div class="right"></div> 

I could just squeeze them together, but I would have to overlay one div on another, for example: http://jsfiddle.net/uwz6L79w/1/ .

 .left { position: absolute; left: 0; top: 0; width: 100px; height: 100px; border-width: 4px; border-color: black white black black; border-style: solid; border-radius: 60px } .right { position: absolute; left: 70px; top: 0; width: 100px; height: 100px; border-width: 4px; border-color: black black black white; border-style: solid; border-radius: 60px; background: #f2f2f2; } 
 <div class="left"></div> <div class="right"></div> 

Does anyone know how I could accomplish this without overlapping divs?

+42
html css html5 css3 css-shapes
Nov 24 '15 at 8:19
source share
5 answers

Svg

This is also possible with SVG.

The SVG version is very short, since it basically requires the Arc command to control its shape, size and position.

 <svg width="50%" viewbox="0 0 100 50"> <path d="M50,35 a20,20 0 1,0 0,-20 a20,20 0 1,0 0,20z" fill="white" stroke="black"> </path> </svg> 

SVG stands for scalable vector graphics. The web browser views it as an image, but you can add text and regular HTML elements to SVG.

It is well supported in all browsers as visible here: CanIUse

+45
Nov 24 '15 at 9:17
source share

Border Usage: Recommended

You can do this the same way as in the second fragment and use positioning as in the fragment below to avoid overlapping two div elements. Here the circles are created by pseudo-elements, and the overlapping part is cut out using overflow: hidden for their parents.

It should be noted here that any hover effect should be added to the pseudo-elements, and not to the parent elements. This is due to the fact that if :hover attached to the parent, then it will work even if it falls outside the circle (since the parent object is still a square).

Of all three solutions presented in this answer, this is the one that has the best browser support and will work even in IE8. Therefore, it is recommended.

 .left, .right { position: relative; float: left; height: 200px; width: 200px; /* border: 1px solid; uncomment to see that they aren't overlapped */ overflow: hidden; } .left:after, .right:after { position: absolute; content: ''; height: calc(100% - 12px); /* 12px because of 6px border on either side */ width: calc(100% - 12px); /* 12px because of 6px border on either side */ border-radius: 50%; border: 6px solid gray; } .left:after { right: -20px; } .right:after { left: -20px; } 
 <div class='left'></div> <div class='right'></div> 



Using radial gradients:

If you don’t want to use pseudo-elements and overflow: hidden for the parent, you can also use radial-gradient background images to create a circle and arrange them so that they ultimately produce the desired effect. Below is an example of a fragment of this approach.

The disadvantage of this approach is the low browser support for radial-gradient . This will not work in IE9 and below. In addition, circles formed by radial gradients usually have jagged (rough edges), and when we change the stop position of the color to make it smoother, it is slightly blurred.

 .left, .right { float: left; height: 200px; width: 200px; /*border: 1px solid; uncomment to see that they aren't overlapped */ } /* generally the below code should be enough to produce 6px thick circular border .left { background: radial-gradient(circle at 70% 50%, transparent calc(50% - 3px), gray calc(50% - 3px), gray calc(50% + 3px), transparent calc(50% + 3px)); } .right { background: radial-gradient(circle at 30% 50%, transparent calc(50% - 3px), gray calc(50% - 3px), gray calc(50% + 3px), transparent calc(50% + 3px)); } */ /* but it produces jagged edges and so we can change the color stops a bit like below this produces smoother circles but the disadvantage is that they'd look a bit blurred */ .left { background: radial-gradient(circle at 70% 50%, transparent calc(50% - 4px), gray calc(50% - 2px), gray calc(50% + 2px), transparent calc(50% + 4px)); } .right { background: radial-gradient(circle at 30% 50%, transparent calc(50% - 4px), gray calc(50% - 2px), gray calc(50% + 2px), transparent calc(50% + 4px)); } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script> <div class='left'></div> <div class='right'></div> 



Using clips (CSS / SVG):

Another approach that can be used is to use clip-path . The advantage of this approach is that hover effects will only work when the cursor is within the circle (as can be seen from the fragment). This is due to the fact that unnecessary parts are cut off.

Downside again is poor browser support . The CSS version of clip-path supported only in Webkit, but not in Firefox, IE, while the SVG version (using the built-in SVG) is supported in Webkit, Firefox, but not in IE.

 .left, .right { float: left; height: 200px; width: 200px; border-radius: 50%; border: 6px solid gray; } /* CSS Clip Path - not supported by FF and IE */ .left.css-clip { clip-path: polygon(0% 0%, 80% 0%, 80% 100%, 0% 100%); } .right.css-clip { margin-left: -86px; /* 20% width * 2 (which is the clipped space) - border width */ clip-path: polygon(20% 0%, 100% 0%, 100% 100%, 20% 100%); } /* SVG Clip Path - supported by Webkit, FF but not IE */ .left.svg-clip { clip-path: url(#clipper-left); } .right.svg-clip { margin-left: -86px; /* 20% width * 2 (which is the clipped space) - border width */ clip-path: url(#clipper-right); } /* Just for demo */ h3{ clear: both; } .left:hover, .right:hover{ background: red; } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js"></script> <h3>CSS Clip Path</h3> <div class='left css-clip'></div> <div class='right css-clip'></div> <h3>SVG Clip Path</h3> <div class='left svg-clip'></div> <div class='right svg-clip'></div> <!-- Inline SVG for SVG Clip Path --> <svg width='0' height='0'> <defs> <clipPath id='clipper-left' clipPathUnits='objectBoundingBox'> <path d='M0,0 .8,0 .8,1 0,1z' /> </clipPath> <clipPath id='clipper-right' clipPathUnits='objectBoundingBox'> <path d='M.2,0 1,0 1,1 .2,1z' /> </clipPath> </defs> </svg> 
+41
Nov 24 '15 at 8:31
source share

Here's a solution using only one <div> .

  • .shape is a transparent circle with a red 10px border.
  • .shape::before - an opaque white circle with a red border 10px .
  • .shape::after - an opaque white circle (no border).

 .shape { margin: 6px auto; } .shape, .shape::before, .shape::after { display: block; position: relative; width: 160px; height: 160px; border-radius: 160px; } .shape, .shape::before { border: 10px solid #f00; } .shape::before, .shape::after { content: ""; background-color: rgba(255, 255, 255, 1); } .shape::before { top: -10px; left: -150px; } .shape::after { top: -180px; } 
 <div class="shape"> </div> 
+12
Nov 24 '15 at 20:07
source share

Here is a quick example that I came up with. I have not tested it in different browsers, but it should be well supported.

HTML:

 <div class="one"></div> <div class="two"></div> 

CSS

 div { background: #fff; border-radius: 50%; float: left; height: 100px; position: relative; width: 100px; } .one:after, .two:after{ /* adjust this to set the border color */ background: #666; border-radius: 50%; content: ""; position: absolute; z-index: -1; /* adjust these to set the border width */ top: -5px; right: -5px; bottom: -5px; left: -5px; } .two { /* adjust this to set the overlap of the circles */ margin-left: -20px; } 

Live demo

+8
Nov 24 '15 at 16:59
source share

I come back to this question (after 6 weeks), because the voice with the highest voice aroused my academic curiosity in svg , which I rarely met and never studied.

Since I am studying svg , this question (which sent me to my search to find it in the first place) was an ideal challenge with which to try new skills.

So here is an alternative svg solution equivalent to my only <div> css solution above:

 svg { width: 310px; height: 180px; } svg circle { stroke: rgb(255,0,0); stroke-width: 10; fill: rgb(255,255,255); } svg circle:nth-of-type(3) { stroke: rgb(255,255,255); } 
 <svg viewbox="0 0 310 180"> <circle cx="90" cy="90" r="80" /> <circle cx="220" cy="90" r="80" /> <circle cx="90" cy="90" r="70" /> </svg> 
+2
Jan 6 '16 at 11:40
source share



All Articles