Search code examples
htmlcsscss-shapes

Limit Shape's Border with CSS


I need to achieve an effect like in this demo.

But the code I used there is too specific and not very clean. As you can see I have used quite a lot of elements and also some transforms with very specific angle calculations.

Is there a way for me to create this shape, keep it responsive but in a cleaner way? Please note that I don't want just half a circle, but a very specific angle that I could adapt. I mean the circle could be more or less inside the rectangle, so the angle of the arc would be more or less big.

CSS:

.rectangle {
  background-color: white;
  width:200px;
  height:200px;
  border:solid 1px navy;
}
.circle {
  position: relative;
  width: 70px; height: 70px;
  border-radius: 50%;
  background: white;
  margin-top:calc(50% - 35px);
  margin-left:calc(100% - 50px);
}
.arc {
  overflow: hidden;
  position: absolute;
  top: -1px; right: 50%; bottom: 50%; left: -1px;
  transform-origin: 100% 100%;
  transform: rotate(115deg);
}
.arc:before {
  box-sizing: border-box;
  display: block;
  border: solid 1px navy;
  width: 200%; height: 200%;
  border-radius: 50%;
  content: '';
}

.arc2 {
  overflow: hidden;
  position: absolute;
  top: -1px; right: 50%; bottom: 50%; left: -1px;
  transform-origin: 100% 100%;
  transform: rotate(155deg);
}
.arc2:before {
  box-sizing: border-box;
  display: block;
  border: solid 1px navy;
  width: 200%; height: 200%;
  border-radius: 50%;
  content: '';
}

HTML:

<div class='rectangle'>
  <div class='circle'>
    <div class='arc'></div>
    <div class='arc2'></div>
  </div>
</div>

Points to Note:

  1. I cannot use z-index, it was my first solution but it causes other problems.
  2. The height of the rectangle can change and so I'd need it to be responsive but the height of the circle should stay the same even if the height of the container gets bigger
  3. I can use SVG if that is an option.

Solution

  • I would generally recommend using SVG for such shapes because it is easier to create and maintain arcs with it. Using SVG would also mean better control over the radius, the arc's start and end angles etc but I don't think we can make part of the shape be responsive (the rectangle) while keeping other part as static (the circle's height) and hence it might be safer to use CSS.

    In CSS also, it is tough to achieve this with a single element because you've indicated that z-index cannot be used. Other approaches (like making the element's width larger than height or using scale) would result in an elliptical arc and it would also require tweaking to positioning attributes when height or width changes.

    Considering all those the below approach using a couple of elements and a pseudo-element could be the best bet. The .inner element is placed on top of the right border of the .rectangle and its width is just enough to get the circle to display. Inside the .inner element, the pseudo element that creates the circle is placed with a negative left offset so that only a part of the circle is visible (due to overflow being hidden on .inner). The output is responsive.

    .rectangle {
      position: relative;
      background-color: white;
      width: 200px;
      height: 200px;
      border: solid 1px navy;
    }
    .inner {
      position: absolute;
      left: 100%;
      top: -1px;
      height: calc(100% + 2px);
      width: 30px;
      overflow: hidden;
    }
    .inner:after {
      position: absolute;
      content: '';
      width: 70px;
      height: 70px;
      border-radius: 50%;
      background: white;
      top: calc(50% - 35px);
      left: -45px;
      border: 1px solid navy;
    }
    
    /* Just for demo */
    
    .rectangle {
      transition: all 1s ease;
    }
    .rectangle:hover {
      height: 400px;
    }
    <div class='rectangle'>
      <div class="inner"></div>
    </div>