Search code examples
htmlcsscss-shapes

How to implement a circular border?


I've been creating this "ticket-like" border next to my images, and got the border-bottom working just fine (see the image below).

Functioning border-bottom

It is necessary (I think) to implement the border with ::after pseudo class, due the offset that border must have. Here is the code that's currently working for the bottom border:

#imagePanel .panel {
  background-color: #28c3d7;
  position: relative;
  text-align: center;
  height: 100%;
  padding-bottom: 80px;
}
#imagePanel .panel > div:first-child:after {
  position: relative;
  display: block;
  width: 100%;
  height: 22px;
  margin-top: -11px;
  content: '';
  border-top: 22px dotted #fff;
  z-index: 2;
}
<div id="imagePanel">
  <div class="panel panel-blue">
  <div class="blueBorder>
    <div>
      <img alt="image" src="https://via.placeholder.com/365x204" style="width: 365px; height: 204px;">
    </div>
    </div>
  </div>
</div>

The Question is; how can I apply the same kind of border to the right side of image? It will be important once the page width exceeds a certain point, as I'll have to manipulate the styling with media queries and put the image to the left side and the other content with the blue background to the right side.


Solution

  • Here is an idea with multiple background

    .box {
      position:relative;
      display:inline-block;
    }
    .box:after {
      content:"";
      position:absolute;
      bottom:0;
      left:0;
      right:0;
      height:50px;
      padding-top:10px; /* same as the radius */
      box-sizing:border-box;
      background:
        radial-gradient(circle 10px /*10px of radius*/,blue 98%,transparent 100%) 
        -10px 0 /* Control the initial position*/
        /40px 20px /* 40px to control the distance between the circles, 20px = 2*10px */ 
        repeat-x,
        blue content-box;
    }
    
    img {
     display:block;
    }
    <div class="box"><img alt="image" src="https://via.placeholder.com/365x204" ></div>

    That you can easily make on the left or the right:

    .box {
      position:relative;
      display:inline-block;
    }
    .box:after {
      content:"";
      position:absolute;
      left:0;
      top:0;
      bottom:0;
      width:50px;
      padding-right:10px;
      box-sizing:border-box;
      background:
        radial-gradient(circle 10px,blue 98%,transparent 100%) 
        100% -10px
        /20px 40px 
        repeat-y,
        blue content-box;
    }
    
    img {
     display:block;
    }
    <div class="box"><img alt="image" src="https://via.placeholder.com/365x204" ></div>

    You can also add CSS variables to easily control everything:

    .box {
      position:relative;
      display:inline-block;
      --r:10px; /* Radius */
      --d:10px; /* Distance between circles*/
      --h:50px; /* Height of the border */
      --c:blue; /* Color */
    }
    .box.left:after,
    .box.right:after{
      content:"";
      position:absolute;
      left:0;
      top:0;
      bottom:0;
      width:var(--h);
      padding-right:var(--r);
      box-sizing:border-box;
      background:
        radial-gradient(circle var(--r),var(--c) 98%,transparent 100%) 
        100% calc(-1*var(--d)/2)
        /calc(2*var(--r)) calc(2*var(--r) + var(--d)) 
        repeat-y,
        var(--c) content-box;
    }
    .box.right:after {
      left:auto;
      right:0;
      transform:scaleX(-1);
    }
    
    .box.bottom:after,
    .box.top:after{
      content:"";
      position:absolute;
      bottom:0;
      left:0;
      right:0;
      height:var(--h);
      padding-top:var(--r);
      box-sizing:border-box;
      background:
        radial-gradient(circle var(--r),var(--c) 98%,transparent 100%) 
        calc(-1*var(--d)/2) 0
        /calc(2*var(--r) + var(--d)) calc(2*var(--r))  
        repeat-x,
        var(--c) content-box;
    }
    
    .box.top:after {
      bottom:auto;
      top:0;
      transform:scaleY(-1);
    }
    
    
    img {
     display:block;
    }
    <div class="box left">
    <img alt="image" src="https://via.placeholder.com/200x200" >
    </div>
    
    <div class="box right" style="--r:20px;--d:30px;--c:red;">
    <img alt="image" src="https://via.placeholder.com/200x200" >
    </div>
    
    <div class="box bottom" style="--r:5px;--h:60px;--d:10px;--c:green;">
    <img alt="image" src="https://via.placeholder.com/200x200" >
    </div>
    <div class="box top" style="--r:25px;--h:40px;--d:10px;--c:yellow;">
    <img alt="image" src="https://via.placeholder.com/200x200" >
    </div>

    CSS border with circles

    If you want the distance to be automatically calculated in order to avoid having partial circles you can try the below where you have to define the number of circles instead.

    .box {
      position:relative;
      display:inline-block;
      --r:10px; /* Radius */
      --n:8; /* number of circles*/
      --h:50px; /* Height of the border */
      --c:blue; /* Color */
      
      --d: calc((100% - var(--n)*2*var(--r))/(var(--n) - 1)); /* the distance*/ 
    }
    .box.left:after,
    .box.right:after{
      content:"";
      position:absolute;
      left:0;
      top:0;
      bottom:0;
      width:var(--h);
      padding-right:var(--r);
      box-sizing:border-box;
      background:
        radial-gradient(circle var(--r) at 50% var(--r),var(--c) 98%,transparent 100%) 
        100% 0
        /calc(2*var(--r)) calc(2*var(--r) + var(--d)) 
        repeat-y,
        var(--c) content-box;
    }
    .box.right:after {
      left:auto;
      right:0;
      transform:scaleX(-1);
    }
    
    .box.bottom:after,
    .box.top:after{
      content:"";
      position:absolute;
      bottom:0;
      left:0;
      right:0;
      height:var(--h);
      padding-top:var(--r);
      box-sizing:border-box;
      background:
        radial-gradient(circle var(--r) at var(--r) 50% ,var(--c) 98%,transparent 100%) 
        0 0
        /calc(2*var(--r) + var(--d)) calc(2*var(--r))  
        repeat-x,
        var(--c) content-box;
    }
    
    .box.top:after {
      bottom:auto;
      top:0;
      transform:scaleY(-1);
    }
    
    
    img {
     display:block;
    }
    <div class="box left">
    <img alt="image" src="https://via.placeholder.com/200x200" >
    </div>
    
    <div class="box right" style="--r:20px;--n:4;--c:red;">
    <img alt="image" src="https://via.placeholder.com/200x200" >
    </div>
    
    <div class="box bottom" style="--r:5px;--h:60px;--n:10;--c:green;">
    <img alt="image" src="https://via.placeholder.com/200x200" >
    </div>
    <div class="box top" style="--r:25px;--h:40px;--n:3;--c:yellow;">
    <img alt="image" src="https://via.placeholder.com/200x200" >
    </div>

    enter image description here

    Here is a codepen to play around with the code