Tips for creating animated arc fills using CSS

Can we gradually fill the color of a CSS semi-circle in a counterclockwise direction, similar to a progress bar?

Here is the code for the semi-circle: https://jsfiddle.net/sonymax46/wqfovdjh/7/.


.cc{
    background-color: transparent;
    overflow: hidden;
    width: 80px;
}
.curve {
    height: 60px;
    width: 100%;
    background-color: none;
    border-radius: 50%;
    border: 2px solid blue;
    transform: translateX(50%);
}

I would like the current blue color to be replaced with green upon triggering an event. How can this be achieved using CSS or SVG?

Thank you in advance.

Answer №1

Option A involves using a container that cuts off a circular element and a pseudo-class as a "mask" over the circle. A gradient background then reveals a different color when the element is rotated.

The main downside to this method is that you need a solid color background for the overlay to match visually.

.wrapper {
  margin: 20px;
  width: 200px;
  height: 200px;
  overflow: hidden;
  /* just to show the box could be transparent */
  background-color: lightgray;
  cursor: pointer;
}

.arc {
  position: absolute;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  position: relative;
  /* Use relative on parent so mask aligns */
  left: 50%;
  /* Move the circle 'outside' the wrapper */
  background: linear-gradient(90deg, rgba(55, 238, 79, 1) 0%, rgba(55, 238, 79, 1) 50%, rgba(0, 212, 255, 1) 50%, rgba(0, 212, 255, 1) 100%);
  transition: transform 1s ease;
}

.arc:after {
  /* this creates the 'mask' */
  content: '';
  position: absolute;
  width: 90%;
  height: 90%;
  top: 5%;
  left: 5%;
  background-color: white;
  border-radius: 50%;
}

.wrapper:hover .arc {
  /* rotate the full element because we can't transition backgrounds */
  transform: rotate(-180deg);
}

.gradientExample {
  /* just to show the gradient */
  height: 20px;
  width: 200px;
  margin: 0 20px;
  background: linear-gradient(90deg, rgba(55, 238, 79, 1) 0%, rgba(55, 238, 79, 1) 50%, rgba(0, 212, 255, 1) 50%, rgba(0, 212, 255, 1) 100%);
}

p {
  font-family: Sans-Serif;
  font-size: 14px;
  margin: 20px 20px 0 20px;
}
<p>Hover over the arc</p>
<div class="wrapper">
  <div class="arc"></div>
</div>
<div class="gradientExample"></div>

Option B suggests using a clip-path instead of overlapping elements. This option is more efficient, but it requires creating an SVG object for the arc, which can be challenging in terms of sizing.

.wrapper {
  margin: 20px;
  width: 200px;
  height: 200px;
  overflow: hidden;
  background-color: lightgray;
  cursor: pointer;
}

.svgArc {
  width: 100%;
  height: 100%;
  position: relative;
  clip-path: url(#svgPath);
}

.svgArc:after {
  /* have to use a pseudo element because we can't rotate the background */
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, rgba(55, 238, 79, 1) 0%, rgba(55, 238, 79, 1) 50%, rgba(0, 212, 255, 1) 50%, rgba(0, 212, 255, 1) 100%);
  transition: transform 1s ease;
}

.v2:hover .svgArc:after {
  transform: rotate(180deg);
}

p {
  font-family: Sans-Serif;
  font-size: 14px;
  margin: 20px 20px 0 20px;
}
<p>Hover over the gray square</p>

<div class="wrapper v2">
  <div class="svgArc">

  </div>
</div>

<svg width="0" height="0" viewBox="0 0 200 200">
    <defs>
        <clipPath id="svgPath">
<path fill="#000000" stroke="#ffffff" stroke-width="1" d="M100,0 L100,10 L100,10 C50.2943725,10 10,50.2943725 10,100 C10,149.705627 50.2943725,190 100,190 L100,200 L100,200 C44.771525,200 0,155.228475 0,100 C0,44.771525 44.771525,0 100,0 Z"></path>
        </clipPath>
    </defs>
</svg>

Option C presents the idea of creating an SVG circle and animating the offset-path. For more details and an example, refer to this link: How to make linear css transition to SVG path?

Answer №2

Consider using CSS custom variables for this?

const Root   = document.documentElement
  ,  btColor = document.getElementById('bt-color')
  ;
btColor.onclick=_=>
  {
  Root.style.setProperty('--bColor', 'green')
  }
:root {
  --bColor  : blue;
  }
.cc{
  background-color: transparent;
  overflow: hidden;
  width: 80px;
  }
.curve {
  height: 60px;
  width: 100%;
  background-color: none;
  border-radius: 50%;
  border: 2px solid var(--bColor);
  transform: translateX(50%);
  }
<div class="cc">
  <div class="curve"></div>
</div>
<br>
<button id="bt-color">change color</button>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

How can I include a path prefix to globs provided to gulp.src?

Consider the contents of these two essential files: settings.json { "importFiles": [ "imports/data.js", "imports/functions.js", "imports/styles.css" ] } builder.js var build = require("builder"), combine = require("combine-files"), ...

Merging an AppBar and Drawer in Material UI for a seamless user interface design

I am working on integrating an AppBar component with a drawer feature. Here is the code for the AppBar: import React from "react"; import PropTypes from "prop-types"; import { withStyles } from "material-ui/styles"; import AppBar from "material-ui/AppBar" ...

Ways to organize interconnected form elements on a PHP webpage

On my PHP page, I have a form designed to gather user information for job recruitment. This form consists of multiple input fields and can be considered as a candidate's resume. One section of the form requires users to enter their skill set in the f ...

A step-by-step guide to setting up a custom splash screen for React Native

Looking for assistance in setting up a splash screen in react-native specifically for Android devices. I've managed to successfully implement one for iOS, but I'm encountering difficulties when it comes to getting one to work on Android. I' ...

Typescript: Add a new variable preceding a specified string

fetchArticle(articleId: string): Observable<any> { return this._http.get(`${this._url}/${articleId}`) .map((response: Response) => response.json()) .do(value => console.log(value)) .catch((error) => Observable.throw(err ...

Can jQuery help me identify which <input type='image> was clicked within a form containing several submit images?

Consider this hypothetical scenario: <form> <input type="text" name="some_name" value="val" id="some_name"> <input type="image" value="action" alt="Add To Cart" name="add" src="/images/submit.gif"> <input type="image" value="act ...

What specific quirk in Firefox is responsible for this behavior, and is there a way to replicate it in standards mode?

In Firefox, this particular document displays differently in standards mode compared to quirks mode. When in quirks mode, the div fills the entire screen, but in standards mode it does not. I went through the MDN quirks list and couldn't pinpoint a sp ...

The component is no longer able to locate the imported element when it is being shared

Recently, I imported a component into the shared module in order to use it across 2 different modules. However, upon recompiling the app, an error message appeared stating that the jodit-editor, which is utilized by the shared component, is not recognized ...

Assistance with the Chakra UI Range Slider in React

I could use some help figuring out where exactly to implement my OnChange and Map functions for mapping JSON data into a Range Slider. Everything seems to be rendering correctly, but I keep encountering an error when I try to move the slider: Unhandled Ru ...

FlexNav excluding

I have implemented FlexNav for my website navigation. The demo I used sets the width of top-level menu items to 20%, which works well with five menu items. .flexnav li { . . . width: 20%; } However, in my menu, the text lengths of the top ...

During development, getStaticPaths and getStaticProps successfully function, however, the prop during build time becomes undefined

I am currently working on developing an eCommerce platform utilizing Next.js. One of the challenges I encountered was in the product page where dynamic routes are used. Specifically, I implemented getStaticProps to fetch the product and getStaticPaths to g ...

How can I make a div move to the position of another div and stay with it when the screen is resized?

In my card game project, I am dealing with an issue where cards are not aligning properly with the designated "dropZonePositions" when the screen is resized. Despite creating animations for the card movement that I'm satisfied with, the problem arises ...

Dawn Break Alarm Timepiece - Online Platform

My buddy recently purchased a "sunrise alarm clock" that gradually brightens to mimic a sunrise and make waking up easier. I had the thought of replicating this effect with my laptop, but I've been facing issues with getting the JavaScript time funct ...

I am unable to determine if I have already selected a List Item

My goal is to have a functionality where clicking on "Download Drivers" will open the list, and clicking again will close it. This should be achieved with onclick events only, no hover effects. Additionally, I want the list to remain open even if I click o ...

Is there a way to align these blocks in a single row?

Having trouble aligning these buttons horizontally. Any suggestions? I've been tinkering with this for a couple of hours now, so decided to seek help here. The desired effect should resemble the image below, but it's not quite there yet. Thank yo ...

What is the purpose of using a visually striking and prominent HTML tag?

After 15 years of working in html development and managing multiple websites, I have come to realize that bold and italic tags essentially serve the same purpose. I can apply CSS styles to both to achieve similar effects. I have even experimented with maki ...

Tips for ending a page prematurely

I am currently facing an issue with hosting images on my webpage where the bottom of the images are uneven, creating a messy look at the bottom of the page. https://i.sstatic.net/N3XvJ.png Normally I would attempt to align them in a perfect square layout ...

Navigating the issue of updateMany not functioning properly in mongoose and nodejs

I need assistance with updating the author name of a post whenever the user updates their profile name. My code is as follows: router('/:id', async (req, res) { if (req.body._id == req.params.id) { try { const user = await ...

How can I incorporate dashed borders between images using CSS?

New to the world of HTML and CSS, I'm trying to replicate a design I came across online for some practice. The website layout includes images separated by borders, and I'm unsure if this particular design can be achieved using regular CSS alone o ...

Tips for adjusting the placement of enlarged images within colorbox

I recently discovered colorbox and decided to use it as my lightbox solution. However, I encountered a challenge with positioning the background (#cboxOverlay). I wanted to move it 120px to the left so that some content from the original page would still ...