You need to divide by 2 every values involved, even the clip(); ones (fiddle updated)

#loading {
  width: 50px;
  height: 50px;
  margin: 30px auto;
  position: relative;
}
.outer-shadow,
.inner-shadow {
  z-index: 4;
  position: absolute;
  width: 100%;
  height: 100%;
  border-radius: 100%;
  box-shadow: 1px 1px 1px 1px rgba(0, 0, 0, 0.5);
}
.inner-shadow {
  top: 50%;
  left: 50%;
  width: 40px;
  height: 40px;
  margin-left: -20px;
  margin-top: -20px;
  border-radius: 100%;
  background-color: #ffffff;
  box-shadow: 1px 1px 1px 1px rgba(0, 0, 0, 0.5);
}
.hold {
  position: absolute;
  width: 100%;
  height: 100%;
  clip: rect(0px, 50px, 50px, 25px);
  border-radius: 100%;
  background-color: #fff;
}
.fill,
.dot span {
  background-color: #f50;
}
.fill {
  position: absolute;
  width: 100%;
  height: 100%;
  border-radius: 100%;
  clip: rect(0px, 25px, 50px, 0px);
}
.left .fill {
  z-index: 1;
  -webkit-animation: left 1s linear;
  -moz-animation: left 1s linear;
  animation: left 1s linear both;
}
@keyframes left {
  0% {
    -webkit-transform: rotate(0deg);
  }
  100% {
    transform: rotate(180deg);
  }
}
@-webkit-keyframes left {
  0% {
    -webkit-transform: rotate(0deg);
  }
  100% {
    -webkit-transform: rotate(180deg);
  }
}
.right {
  z-index: 3;
  -webkit-transform: rotate(180deg);
  -moz-transform: rotate(180deg);
  transform: rotate(180deg);
}
.right .fill {
  z-index: 3;
  -webkit-animation: right 1s linear;
  -moz-animation: right 1s linear;
  animation: right 1s linear both;
  -webkit-animation-delay: 1s;
  -moz-animation-delay: 1s;
  animation-delay: 1s;
}
@keyframes right {
  0% {
    -webkit-transform: rotate(0deg);
  }
  100% {
    transform: rotate(180deg);
  }
}
@-webkit-keyframes right {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(180deg);
  }
}
.inner-shadow img {
  margin-left: 8px;
  margin-top: 7px;
}
<div id='loading'>
  <div class='outer-shadow'>
  </div>
  <div class='inner-shadow'>
  </div>
  <div class='hold left'>
    <div class='fill'></div>
  </div>
  <div class='hold right'>
    <div class='fill'></div>
  </div>

</div>

edit: in respond to comment @Filipe

How would the change from clip to clip-path be? I tried (also changing rect to inset), but the animation stops working.

Possible example with clip-path instead clip .

#loading {
  width: 50px;
  height: 50px;
  margin: 30px auto;
  position: relative;
}

.outer-shadow,
.inner-shadow {
  z-index: 4;
  position: absolute;
  width: 100%;
  height: 100%;
  border-radius: 100%;
  box-shadow: 1px 1px 1px 1px rgba(0, 0, 0, 0.5);
}

.inner-shadow {
  top: 50%;
  left: 50%;
  width: 40px;
  height: 40px;
  margin-left: -20px;
  margin-top: -20px;
  border-radius: 100%;
  background-color: #ffffff;
  box-shadow: 1px 1px 1px 1px rgba(0, 0, 0, 0.5);
}

.hold {
  position: absolute;
  width: 100%;
  height: 100%;
  clip-path: polygon(50% 0, 0 0, 0 100%, 50% 100%);
  border-radius: 100%;
  background-color: #fff;
}

.fill,
.dot span {
  background-color: #f50;
}

.fill {
  position: absolute;
  width: 100%;
  height: 100%;
  border-radius: 100%;
  clip-path: polygon(50% 0, 100% 0, 100% 100%, 50% 100%);
}

.left .fill {
  z-index: 1;
  -webkit-animation: left 1s linear;
  -moz-animation: left 1s linear;
  animation: left 1s linear both;
}

@keyframes left {
  0% {
    -webkit-transform: rotate(0deg);
  }
  100% {
    transform: rotate(180deg);
  }
}

@-webkit-keyframes left {
  0% {
    -webkit-transform: rotate(0deg);
  }
  100% {
    -webkit-transform: rotate(180deg);
  }
}

.right {
  z-index: 3;
  -webkit-transform: rotate(180deg);
  -moz-transform: rotate(180deg);
  transform: rotate(180deg);
}

.right .fill {
  z-index: 3;
  -webkit-animation: right 1s linear;
  -moz-animation: right 1s linear;
  animation: right 1s linear both;
  -webkit-animation-delay: 1s;
  -moz-animation-delay: 1s;
  animation-delay: 1s;
}

@keyframes right {
  0% {
    -webkit-transform: rotate(0deg);
  }
  100% {
    transform: rotate(180deg);
  }
}

@-webkit-keyframes right {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(180deg);
  }
}

.inner-shadow img {
  margin-left: 8px;
  margin-top: 7px;
}
<div id='loading'>
  <div class='outer-shadow'>
  </div>
  <div class='inner-shadow'>
  </div>
  <div class='hold left'>
    <div class='fill'></div>
  </div>
  <div class='hold right'>
    <div class='fill'></div>
  </div>
</div>

Answer from G-Cyrillus on Stack Overflow
๐ŸŒ
CodePen
codepen.io โ€บ devilishalchemist โ€บ pen โ€บ oXjYKB
Box border fill animation
We offer two popular choices: Autoprefixer (which processes your CSS server-side) and -prefix-free (which applies prefixes via a script, client-side).
๐ŸŒ
FreeFrontend
freefrontend.com โ€บ css-border-animations
57 CSS Border Animations
2 weeks ago - Each card gets a unique theme via :nth-child and the --cardAccent CSS variable, while multi-layering with z-index positions the glow underneath the main content. ... An animated rainbow border effect with a neon glow, implemented using @property, conic-gradient, and SVG filters.
Discussions

CSS circle border fill animation - Stack Overflow
I have a css file which makes circle border fill animation perfectly. Its in 100px width and height. But i need only in 50px width and height circle with the same animation. I tried many more times... More on stackoverflow.com
๐ŸŒ stackoverflow.com
How to animate border so that it displays slowly from start to finish
I want to animate a border and show it slowly, something like this Codepen, with some differences: Not removing the old line but it needs to be shown something like that. The color should not be ... More on stackoverflow.com
๐ŸŒ stackoverflow.com
animation - CSS animate circle border filling with color - Stack Overflow
I'm new to learning about CSS animations. I have a circle with an arc going around it, but I want to make it leave a trail behind. The idea is I'd use this to visually show how many credits somebod... More on stackoverflow.com
๐ŸŒ stackoverflow.com
html - CSS animation - How to fill in "starting from border"? - Stack Overflow
Quite a simple question, really, however I could not find anything online. Basically, how do you animate a fill-in with a specific color of an element starting at the border? E.g the border gets ... More on stackoverflow.com
๐ŸŒ stackoverflow.com
๐ŸŒ
web.dev
web.dev โ€บ articles โ€บ css border animations
CSS border animations | Articles | web.dev
August 1, 2022 - When setting border-image-slice to fill, the border-image is not painted underneath the set background but on top. This can be troublesome if you want the background to be semi-transparent. Thereโ€™s a multitude of possibilities to animate borders in CSS.
๐ŸŒ
Slider Revolution
sliderrevolution.com โ€บ home โ€บ awesome css border animation examples to use
Awesome CSS Border Animation Examples to Use in Your Websites
January 27, 2026 - The following CSS border animation examples demonstrate how to create engaging interactive elements using modern CSS3 animation techniques. Each example has been tested for cross-browser compatibility across Chrome, Firefox, and Safari to ensure consistent rendering on all major platforms.
Top answer
1 of 2
11

You need to divide by 2 every values involved, even the clip(); ones (fiddle updated)

#loading {
  width: 50px;
  height: 50px;
  margin: 30px auto;
  position: relative;
}
.outer-shadow,
.inner-shadow {
  z-index: 4;
  position: absolute;
  width: 100%;
  height: 100%;
  border-radius: 100%;
  box-shadow: 1px 1px 1px 1px rgba(0, 0, 0, 0.5);
}
.inner-shadow {
  top: 50%;
  left: 50%;
  width: 40px;
  height: 40px;
  margin-left: -20px;
  margin-top: -20px;
  border-radius: 100%;
  background-color: #ffffff;
  box-shadow: 1px 1px 1px 1px rgba(0, 0, 0, 0.5);
}
.hold {
  position: absolute;
  width: 100%;
  height: 100%;
  clip: rect(0px, 50px, 50px, 25px);
  border-radius: 100%;
  background-color: #fff;
}
.fill,
.dot span {
  background-color: #f50;
}
.fill {
  position: absolute;
  width: 100%;
  height: 100%;
  border-radius: 100%;
  clip: rect(0px, 25px, 50px, 0px);
}
.left .fill {
  z-index: 1;
  -webkit-animation: left 1s linear;
  -moz-animation: left 1s linear;
  animation: left 1s linear both;
}
@keyframes left {
  0% {
    -webkit-transform: rotate(0deg);
  }
  100% {
    transform: rotate(180deg);
  }
}
@-webkit-keyframes left {
  0% {
    -webkit-transform: rotate(0deg);
  }
  100% {
    -webkit-transform: rotate(180deg);
  }
}
.right {
  z-index: 3;
  -webkit-transform: rotate(180deg);
  -moz-transform: rotate(180deg);
  transform: rotate(180deg);
}
.right .fill {
  z-index: 3;
  -webkit-animation: right 1s linear;
  -moz-animation: right 1s linear;
  animation: right 1s linear both;
  -webkit-animation-delay: 1s;
  -moz-animation-delay: 1s;
  animation-delay: 1s;
}
@keyframes right {
  0% {
    -webkit-transform: rotate(0deg);
  }
  100% {
    transform: rotate(180deg);
  }
}
@-webkit-keyframes right {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(180deg);
  }
}
.inner-shadow img {
  margin-left: 8px;
  margin-top: 7px;
}
<div id='loading'>
  <div class='outer-shadow'>
  </div>
  <div class='inner-shadow'>
  </div>
  <div class='hold left'>
    <div class='fill'></div>
  </div>
  <div class='hold right'>
    <div class='fill'></div>
  </div>

</div>

edit: in respond to comment @Filipe

How would the change from clip to clip-path be? I tried (also changing rect to inset), but the animation stops working.

Possible example with clip-path instead clip .

#loading {
  width: 50px;
  height: 50px;
  margin: 30px auto;
  position: relative;
}

.outer-shadow,
.inner-shadow {
  z-index: 4;
  position: absolute;
  width: 100%;
  height: 100%;
  border-radius: 100%;
  box-shadow: 1px 1px 1px 1px rgba(0, 0, 0, 0.5);
}

.inner-shadow {
  top: 50%;
  left: 50%;
  width: 40px;
  height: 40px;
  margin-left: -20px;
  margin-top: -20px;
  border-radius: 100%;
  background-color: #ffffff;
  box-shadow: 1px 1px 1px 1px rgba(0, 0, 0, 0.5);
}

.hold {
  position: absolute;
  width: 100%;
  height: 100%;
  clip-path: polygon(50% 0, 0 0, 0 100%, 50% 100%);
  border-radius: 100%;
  background-color: #fff;
}

.fill,
.dot span {
  background-color: #f50;
}

.fill {
  position: absolute;
  width: 100%;
  height: 100%;
  border-radius: 100%;
  clip-path: polygon(50% 0, 100% 0, 100% 100%, 50% 100%);
}

.left .fill {
  z-index: 1;
  -webkit-animation: left 1s linear;
  -moz-animation: left 1s linear;
  animation: left 1s linear both;
}

@keyframes left {
  0% {
    -webkit-transform: rotate(0deg);
  }
  100% {
    transform: rotate(180deg);
  }
}

@-webkit-keyframes left {
  0% {
    -webkit-transform: rotate(0deg);
  }
  100% {
    -webkit-transform: rotate(180deg);
  }
}

.right {
  z-index: 3;
  -webkit-transform: rotate(180deg);
  -moz-transform: rotate(180deg);
  transform: rotate(180deg);
}

.right .fill {
  z-index: 3;
  -webkit-animation: right 1s linear;
  -moz-animation: right 1s linear;
  animation: right 1s linear both;
  -webkit-animation-delay: 1s;
  -moz-animation-delay: 1s;
  animation-delay: 1s;
}

@keyframes right {
  0% {
    -webkit-transform: rotate(0deg);
  }
  100% {
    transform: rotate(180deg);
  }
}

@-webkit-keyframes right {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(180deg);
  }
}

.inner-shadow img {
  margin-left: 8px;
  margin-top: 7px;
}
<div id='loading'>
  <div class='outer-shadow'>
  </div>
  <div class='inner-shadow'>
  </div>
  <div class='hold left'>
    <div class='fill'></div>
  </div>
  <div class='hold right'>
    <div class='fill'></div>
  </div>
</div>

2 of 2
0

is this what you expect,hope this will help to you.try this.I only concerned about the circle size of 50 px with inside circle.if this is not the case tell me.

<html xmlns="http://www.w3.org/1999/xhtml">
<head>

<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>jquery</title>

<style type="text/css">
  div.circleone{
    width: 50px;
    height: 50px;
    border-radius: 25px;
    box-shadow: 1px 2px 1px black;

  }

  div.circletwo
  {
    width: 25px;
    height: 25px;
    border-radius: 12.5px;
    box-shadow: 1px -1px 1px black;
    position: relative;
    top: 25%;
    left: 25%;


  }

</style>

</head>

<body>

<div class="circleone">
  <div class="circletwo"></div>
</div>



</body>
</html>

Top answer
1 of 3
9

A way of making the border of an element looking animated is to gradually unveil the borders in turn by gradually shrinking a 5px wide (or high depending on which border) 100% wide element that is overlaying each border.

This snippet does this by animating the after pseudo element on the element and at the same time putting one border after another into the required final color.

You can put the class movingBorder from this snippet onto other elements to get the moving border effect.

.movingBorder {
  width: 60vw;
  height: 60vh;
  border: solid 5px lime;
  position: relative;
  background: pink;
  animation: changeBorders 5s linear;
}

@keyframes changeBorders {
  0% {
    border: solid 5px white;
    border-left: solid 5px lime;
  }
  25% {
    border: solid 5px white;
    border-left: solid 5px lime;
  }
  25.02% {
    border: solid 5px white;
    border-left: solid 5px lime;
    border-bottom: solid 5px lime;
  }
  50% {
    border: solid 5px white;
    border-left: solid 5px lime;
    border-bottom: solid 5px lime;
  }
  50.02% {
    border: solid 5px white;
    border-left: solid 5px lime;
    border-bottom: solid 5px lime;
    border-right: solid 5px lime;
  }
  75% {
    border: solid 5px white;
    border-left: solid 5px lime;
    border-bottom: solid 5px lime;
    border-right: solid 5px lime;
  }
  75.02% {
    border: solid 5px lime;
  }
}

.movingBorder::after {
  width: 5px;
  background-color: white;
  height: 0px;
  position: absolute;
  bottom: 0;
  left: -5px;
  z-index: 1;
  animation: movedown 5s linear;
  animation-fill-mode: forwards;
  content: '';
  display: inline-block;
}

@keyframes movedown {
  0% {
    height: calc(100% + 10px);
    width: 5px;
    bottom: -5px;
    left: -5px;
  }
  25% {
    height: 5px;
    width: 5px;
    bottom: -5px;
    left: -5px;
  }
  25.01% {
    height: 5px;
    width: calc(100% + 10px);
    bottom: -5px;
    left: -5px;
  }
  50% {
    height: 5px;
    width: 0%;
    left: 100%;
    bottom: -5px;
  }
  50.01% {
    height: calc(100% + 10px);
    width: 5px;
    left: 100%;
    bottom: -5px;
  }
  75% {
    height: 0;
    width: 5px;
    left: 100%;
    bottom: 100%;
  }
  75.01% {
    height: 5px;
    width: calc(100% + 10px);
    left: 0%;
    bottom: 100%;
  }
  99.01% {
    height: 5px;
    width: 0;
    left: 0;
    bottom: 100%;
  }
}
<div class="movingBorder" style="background: pink; width: 60vw; height: 60vh;"></div>

UPDATE: the above works for a square border but the requirement was for a border with radius set. This snippet puts an after element over the border (which is on the before pseudo element) which has this shape initially:

This moves left gradually revealing the top part of the lime border. Then the left part is set to transparent and the pseudo element moved right, gradually revealing the bottom part of the border.

NOTE: run this snippet in Full page to see the effect. The animation delays for 10 seconds so you have time to do that (otherwise the animation has finished before you've got there).

* {
  margin: 0px;
  padding: 0px;
  list-style: none;
  border: none;
  text-decoration: none;
  outline: none;
}

::-webkit-input-placeholder {
  color: inherit;
  opacity: 1;
}

:-ms-input-placeholder {
  color: inherit;
  opacity: 1;
}

::placeholder {
  color: inherit;
  opacity: 1;
}

html,
body {
  height: 100%;
}

.col-lg- {}

.col-md- {}

.col-sm- {}

.col- {}

.img-fluid {}

.container-fluid {}

.justify-content-center {}

.row {}

.my-auto {}

.p0 {}

.container {
  width: 100%;
  max-width: 1170px;
}

.container-fluid {
  width: 100%;
  max-width: 1440px;
}

@media (max-width: 1199px) {
  .container {
    width: 100%;
    max-width: 100%;
  }
}


/*** ### Section One ### ***/

.section-one {
  position: relative;
  background: #ffffff;
}

.section-one h2 {
  color: #000000;
  font-size: 32px;
  margin: 0px 0px 10px 0px;
  padding: 0px;
  font-family: "AzoSans-Medium";
}

.section-one p {
  color: #000000;
  font-size: 16px;
  margin: 10px 0px;
  padding: 0px;
  font-family: "AzoSans-Regular";
}

.section-one .boxes {
  position: relative;
  margin-top: 75px;
}

.section-one .boxes:last-child {
  margin-bottom: 100px;
}

.section-one .boxes .left-box {
  position: relative;
  margin: 25px 0px 0px 0px;
  z-index: 3;
}

.section-one .boxes .left-box img {
  width: 100%;
}

.section-one .boxes .right-box {
  position: relative;
  margin: 25px 0px 0px 0px;
  height: 100%;
  z-index: 2;
}

.section-one .boxes .right-box:before,
.section-one .boxes .right-box::after {
  position: absolute;
  content: "";
  top: 50px;
  left: -30px;
  right: 0px;
  bottom: 25px;
  z-index: -2;
  /* so we can have another pseudo element overlaying it */
}

.section-one .boxes .right-box:before {
  border: 1px solid lime;
}

.section-one .boxes .right-box.left h2 {
  text-align: left;
}

.section-one .boxes .right-box.left:before,
.section-one .boxes .right-box.left::after {
  left: 0px;
  right: -30px;
}

.section-one .boxes .right-box.left:before {
  border-right: none;
  border-radius: 250px 0px 0px 250px;
}

.section-one .boxes .right-box::after {
  width: 200%;
  height: 100%;
}

.section-one .boxes .right-box.left::after {
  background-position: 0 0, 100% 75%;
  background-size: calc(50% + 30px) 100%, 50% 50%;
  background-repeat: no-repeat no-repeat, no-repeat no-repeat;
  background-image: linear-gradient(white, white), linear-gradient(white, white);
  animation: left 10s ease-in-out;
  animation-fill-mode: forwards;
  animation-delay: 10s;
  /* just to give time to go full screen on SO snippet! */
}

@keyframes left {
  0% {
    background-image: linear-gradient(white, white), linear-gradient(white, white);
    transform: translateX(0);
  }
  49.99% {
    background-image: linear-gradient(white, white), linear-gradient(white, white);
  }
  50% {
    background-image: linear-gradient(transparent, transparent), linear-gradient(white, white);
    transform: translateX(-50%);
  }
  99.99% {
    background-image: linear-gradient(transparent, transparent), linear-gradient(white, white);
    transform: translateX(0);
    opacity: 1;
  }
  100% {
    opacity: 0;
  }
}

.section-one .boxes .right-box.right h2 {
  text-align: right;
}

.section-one .boxes .right-box.right:before {
  border-left: none;
  border-radius: 0px 250px 250px 0px;
}

.section-one .boxes .right-box h2 {
  padding: 50px 0px 20px 0px;
}

.section-one .boxes .right-box p {
  display: block;
  margin: 15px auto;
  width: 100%;
  max-width: 355px;
  text-align: justify;
}

.section-one .boxes .action-btn {
  position: relative;
  text-align: right;
}

@media (max-width: 1199px) {
  .section-one h2 {
    font-size: 28px;
  }
  .section-one p {
    font-size: 15px;
  }
  .section-one .boxes {
    position: relative;
    margin-top: 50px;
  }
  .section-one .boxes:last-child {
    margin-bottom: 75px;
  }
  .section-one .boxes .right-box:before {
    left: -30px;
  }
  .section-one .boxes .right-box.left h2 {
    text-align: left;
  }
  .section-one .boxes .right-box.left:before {
    border-radius: 200px 0px 0px 200px;
  }
  .section-one .boxes .right-box.right h2 {
    text-align: left;
  }
  .section-one .boxes .right-box.right:before {
    border-radius: 0px 200px 200px 0px;
  }
  .section-one .boxes .right-box h2 {
    padding: 50px 0px 15px 0px;
  }
  .section-one .boxes .right-box p {
    display: block;
    margin: 15px auto;
    width: 100%;
    max-width: 355px;
    text-align: justify;
  }
  .section-one .boxes .action-btn {
    position: relative;
    text-align: right;
  }
}

@media (max-width: 991px) {
  .section-one h2 {
    font-size: 25px;
  }
  .section-one .boxes {
    position: relative;
    margin-top: 10px;
  }
  .section-one .boxes:last-child {
    margin-bottom: 30px;
  }
  .section-one .boxes .right-box:before {
    display: none;
  }
  .section-one .boxes .right-box.right:before {
    display: none;
  }
  .section-one .boxes .right-box h2 {
    padding: 0px 0px 15px 0px;
    margin: 0px;
  }
  .section-one .boxes .right-box p {
    display: block;
    margin: 0px auto 15px auto;
    width: 100%;
    max-width: 100%;
    text-align: justify;
  }
  .section-one .boxes .action-btn {
    position: relative;
    text-align: right;
  }
}
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">


<section class="section-one">
  <div class="container">
    <div class="row">
      <div class="col-lg-12">
        <div class="boxes">
          <div class="row">
            <div class="col-lg-6 aos-init" data-aos="zoom-in-right" data-aos-duration="800">
              <div class="right-box left">
                <h2>Heading1.</h2>
                <p>
                  Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla in erat et quam semper convallis. Phasellus vel nisl id leo suscipit molestie. Sed nec dignissim urna. Donec sit amet tortor nulla. Etiam tempus dui id ipsum commodo, et laoreet tortor luctus.
                  Ut dapibus.
                </p>
              </div>
            </div>
            <div class="col-lg-6 aos-init" data-aos="zoom-in-left" data-aos-duration="800">
              <div class="left-box">
                <img src="https://via.placeholder.com/650x430" class="img-fluid" alt="">
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</section>


<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>

Obviously equivalent CSS has to be added for when the text is to the right of the image.

2 of 3
0

You could "trick" the effect if your background-color is going to be white or solid color.

Just put a box above the element with the border slightly wider and higher, then make the animation to move this element away.

Like this:

* {box-sizing:border-box;}
.parent {
  border:4px solid red;
  height:200px;
  border-radius:100px;
  position:relative;
}
.text {
  width:80%;
  margin:0 auto;
  position:relative;
  top:50%;
  transform:translateY(-50%);
}
.div1 {
  position:absolute;
  background-color:#fff;
  border:4px solid #fff;
  height:calc(100% + 20px);
  width:calc(100% + 20px);
  top:calc(0% - 10px);
  left:calc(0% - 10px);
  animation-name: border;
  animation-duration: 5s;
  animation-fill-mode:forwards;
}
@keyframes border {
  0% {
    left:calc(0% - 10px);
  }
  100% {
    left:calc(100% + 10px );
  }
}
<div class="parent"> 
  <div class="text">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut eget ligula dictum, malesuada tortor vel, gravida velit. Pellentesque eget gravida quam. Nam sit amet massa aliquet, auctor libero dapibus, vehicula nunc. Sed ullamcorper, est id luctus facilisis, velit nibh semper nibh, ac tempus arcu velit ac metus. Donec ultricies ex id pellentesque ultrices. Vivamus rutrum, nulla quis bibendum fringilla, augue massa facilisis ipsum, id facilisis metus nisi nec eros.</div>
   <div class="div1"></div>
</div>

You can move the div containing the text below the other div (div1) if you want the text not to be included in the animation.

๐ŸŒ
Let's Build UI
letsbuildui.dev โ€บ articles โ€บ how-to-animate-borders-in-css
How to Animate Borders in CSS
March 21, 2024 - This is all you need to create an animated gradient border in CSS!
Find elsewhere
๐ŸŒ
Devnahian
devnahian.com โ€บ css-border-animations
20 CSS Border Animations (latest) โ€“ Abdullah Nahian
February 2, 2026 - Moving dashed border Animated stroke motion Lightweight CSS animation Great for loaders or highlight boxes Fully customizable border style ... This design features a sleek hover effect where the border expands inward to fill the elementโ€™s background, creating a modern and interactive visual experience.
๐ŸŒ
MDN Web Docs
developer.mozilla.org โ€บ en-US โ€บ docs โ€บ Web โ€บ CSS โ€บ Reference โ€บ Properties โ€บ animation-fill-mode
animation-fill-mode - CSS - MDN Web Docs
December 5, 2025 - The animation-fill-mode CSS property sets how a CSS animation applies styles to its target before and after its execution. It is often convenient to use the shorthand property animation to set all animation properties at once. ... <section class="flex-column" id="default-example"> <div>Animation ...
๐ŸŒ
CSS-Tricks
css-tricks.com โ€บ animating-border
Animating Border | CSS-Tricks
December 6, 2017 - The challenge is simple: building a button with an expanding border on hover. This article will focus on genuine CSS tricks that would be easy to drop into any project without having to touch the DOM or use JavaScript. The methods covered here will follow these rules ยท Single element (no helper divs, but psuedo-elements are allowed) ... I proposed this challenge in the Animation at Work Slack and again on Twitter.
๐ŸŒ
DEV Community
dev.to โ€บ chokcoco โ€บ fantastic-css-border-animation-5166
Fantastic CSS border animation - DEV Community
July 23, 2022 - Then, in this article -- How to Animate a SVG with border-image, it also explains a way to use border- image, which is very cool. Unlike the above example, we just need to make our pattern, move, that is we need a background image like this. Then, we can also get the moving border map, the code is exactly the same, but the border is moving: ... border-image can also be filled with a color or gradient directly, in addition to posting references to url.
๐ŸŒ
GeeksforGeeks
geeksforgeeks.org โ€บ css โ€บ how-to-create-border-animation-using-css
How to Create Border Animation using CSS? - GeeksforGeeks
July 12, 2025 - This technique leverages CSS pseudo-elements, combined with hover selectors, to achieve animated border transformations based on user interaction.
๐ŸŒ
AVADA Commerce
blog.avada.io โ€บ css โ€บ border-animations
35+ Best Shopify CSS Border Animations Themes Free & Premium 2026 &#8211; AVADA Commerce Blog
March 14, 2022 - Let take a try on SVG Ellipse Border Animation to attract your clients. ... With this border's attractive and flexible appearance, it would be a great idea to bring it into your website. This brilliant CSS3 Draw border animation will meet your requirement and satisfy your visitors.
๐ŸŒ
Stackfindover
blog.stackfindover.com โ€บ home โ€บ css border animation [ 25+ best css border effect examples]
CSS Border Animation [ 25+ Best CSS Border Effect Examples]
September 19, 2021 - Border animation using clip path, which was developed by kang. Moreover, you can customize it according to your wish and need. CSS circle border fill animation, which was developed by katmai7.
Top answer
1 of 1
15

There is a very easy to follow, informative and detailed tutorial on exactly how to achieve this (and more) by Anders Ingemann, which can be found here.

Its a fairly complex operation- so I'll simply distil the final stage from the tutorial here

Demo Fiddle

HTML

<div class="radial-progress">
    <div class="circle">
        <div class="mask full">
            <div class="fill"></div>
        </div>
        <div class="mask half">
            <div class="fill"></div>
            <div class="fill fix"></div>
        </div>
        <div class="shadow"></div>
    </div>
    <div class="inset"></div>
</div>

CSS/LESS

.radial-progress {
    @circle-size: 120px;
    @circle-background: #d6dadc;
    @circle-color: #97a71d;
    @inset-size: 90px;
    @inset-color: #fbfbfb;
    @transition-length: 1s;
    @shadow: 6px 6px 10px rgba(0, 0, 0, 0.2);
    margin: 50px;
    width: @circle-size;
    height: @circle-size;
    background-color: @circle-background;
    border-radius: 50%;
    .circle {
        .mask, .fill, .shadow {
            width: @circle-size;
            height: @circle-size;
            position: absolute;
            border-radius: 50%;
        }
        .shadow {
            box-shadow: @shadow inset;
        }
        .mask, .fill {
            -webkit-backface-visibility: hidden;
            transition: -webkit-transform @transition-length;
            transition: -ms-transform @transition-length;
            transition: transform @transition-length;
        }
        .mask {
            clip: rect(0px, @circle-size, @circle-size, @circle-size/2);
            .fill {
                clip: rect(0px, @circle-size/2, @circle-size, 0px);
                background-color: @circle-color;
            }
        }
    }
    .inset {
        width: @inset-size;
        height: @inset-size;
        position: absolute;
        margin-left: (@circle-size - @inset-size)/2;
        margin-top: (@circle-size - @inset-size)/2;
        background-color: @inset-color;
        border-radius: 50%;
        box-shadow: @shadow;
    }
}

Example jQuery (could be substituted with CSS)

$('head style[type="text/css"]').attr('type', 'text/less');
less.refreshStyles();
var transform_styles = ['-webkit-transform', '-ms-transform', 'transform'];
window.randomize = function () {
    var rotation = Math.floor(Math.random() * 180);
    var fill_rotation = rotation;
    var fix_rotation = rotation * 2;
    for (i in transform_styles) {
        $('.circle .fill, .circle .mask.full').css(transform_styles[i], 'rotate(' + fill_rotation + 'deg)');
        $('.circle .fill.fix').css(transform_styles[i], 'rotate(' + fix_rotation + 'deg)');
    }
}
setTimeout(window.randomize, 200);
$('.radial-progress').click(window.randomize);
๐ŸŒ
uiCookies
uicookies.com โ€บ home โ€บ blog โ€บ 36 best css border animation effects in 2025
36 Best Style CSS Border Animation Effects In 2026 - uiCookies
November 3, 2025 - Creative CSS border animations to awestruck your users. Find the best button border animation, simple animation, and a lot more on this list.
Top answer
1 of 2
3

One way you can do this is to animate the stroke-offset of a path. I've included sample code using a circle path. Depending on how big your element is you will need to change your dasharray and dashoffset values.

svg {
  fill: #eee;
  overflow: visible;
  transform-origin:50% 50%;
  transform: rotate(-90deg);
}
.path {
  stroke: blue;
  stroke-width: 4;
  stroke-dasharray: 800;
  stroke-dashoffset: 800;
  animation: borderblueanim 2s infinite;
  
}

@keyframes borderblueanim {
  from {
    stroke-dashoffset: 800;
  }
  to {
    stroke-dashoffset: 0;
  }
}
<svg width="200" height="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg">
<circle class="path" cx="100" cy="100" r="100"/>
</svg>

2 of 2
0

Something like this might work. This uses SCSS

//Colors
$background: #fefefe;
$text: #4b507a;

$cyan: #60daaa;
$yellow: #fbca67;
$orange: #ff8a30;
$red: #f45e61;
$purple: #6477b9;
$blue: #0eb7da;

// Basic styles
button {
  background: none;
  border: 0;
  box-sizing: border-box;
  margin: 1em;
  padding: 1em 2em;
  
  // Using inset box-shadow instead of border for sizing simplicity
  box-shadow: inset 0 0 0 2px $red;
  color: $red;
  font-size: inherit;
  font-weight: 700;

  // Required, since we're setting absolute on pseudo-elements
  position: relative;
  vertical-align: middle;

  &::before,
  &::after {
    box-sizing: inherit;
    content: '';
    position: absolute;
    width: 100%;
    height: 100%;
  }
}



// Border spins around element
// ::before holds three borders that appear separately, one at a time
// ::after holds one border that spins around to cover ::before's borders, making their appearance seem smooth

.spin {
  width: 5em;
  height: 5em;
  padding: 0;
  
  &:hover {
    color: $blue;
  }

  &::before,
  &::after {
    top: 0;
    left: 0;
  }

  &::before {
    border: 2px solid transparent; // We're animating border-color again
  }

  &:hover::before {
    border-top-color: $blue; // Show borders
    border-right-color: $blue;
    border-bottom-color: $blue;

    transition:
      border-top-color 0.15s linear, // Stagger border appearances
      border-right-color 0.15s linear 0.10s,
      border-bottom-color 0.15s linear 0.20s;
  }

  &::after {
    border: 0 solid transparent; // Makes border thinner at the edges? I forgot what I was doing
  }

  &:hover::after {
    border-top: 2px solid $blue; // Shows border
    border-left-width: 2px; // Solid edges, invisible borders
    border-right-width: 2px; // Solid edges, invisible borders
    transform: rotate(270deg); // Rotate around circle
    transition:
      transform 0.4s linear 0s,
      border-left-width 0s linear 0.35s; // Solid edge post-rotation
  }
}

.circle {
  border-radius: 100%;
  box-shadow: none;
    
  &::before,
  &::after {
    border-radius: 100%;
  }
}

html {
  background: $background;
}

body {
  background: $background;
  color: $text;
  font: 300 24px/1.5 Lato, sans-serif;
  margin: 1em auto;
  max-width: 36em;
  padding: 1em 1em 2em;
  text-align: center;
}

.buttons {
  isolation: isolate;
}

h1 {
  font-weight: 300;
  font-size: 2.5em;
}
  <button class="spin circle">Spin Circle</button>

๐ŸŒ
30 Seconds of Code
30secondsofcode.org โ€บ home โ€บ css โ€บ animation โ€บ button transitions
Button border animation - CSS
August 29, 2024 - Simply replace transform: scale(0.8) ... } To create a fill animation on hover, set a color and background and use an appropriate transition to animate changes to the element....
๐ŸŒ
Speckyboy
speckyboy.com โ€บ home โ€บ css โ€บ 8 css code snippets for creating stunning border effects
8 CSS Code Snippets for Creating Stunning Border Effects โ€” Speckyboy
January 2, 2026 - See the Pen -webkit-background-clip:text CSS effect by Jintos ยท Hereโ€™s an example of how a plain old link (or HTML span, in this case) can be dressed up with a border effect. Choose from an impressive list of hover effects, each one adding a stunning animated border.