Tips for creating pill progress bars that overlap each other

I am attempting to design a progress bar in bootstrap that displays projected and actual results, with a unique rounded "pill" shape on the right side. Below is the code snippet showcasing my progress:

const data = {
    actual: 1155,
  projected: 1573,
  limits: [500, 1000, 2500]
};

const actualProgress = document.getElementById("actual-progress");
const projectedProgress = document.getElementById("projected-progress");

const barLength = Math.max(...data.limits);
const actualPercentage = (data.actual / barLength) * 100;
const projectedPercentage = ((data.projected - data.actual) / barLength) * 100;

actualProgress.style.width = `${actualPercentage}%`;
projectedProgress.style.width = `${projectedPercentage}%`;
.progress-bar.bg-actual {
  background: #b445f5;
}

.progress-bar.bg-projected {
  background: #d391fa;
}

.progress-bar {
  border-radius: 0 500px 500px 0;
}

.progress {
  border-radius: 500px !important;
  height: 30px !important;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container pt-4">
  <div class="row">
    <div class="col">
      <div class="progress">
        <div id="actual-progress" class="progress-bar bg-actual"></div>
        <div id="projected-progress" class="progress-bar bg-projected"></div>
      </div>
    </div>
  </div>
</div>

I would like to have the lighter purple color fill the small gaps left by the rounded edge of the darker purple, while still maintaining a consistent way to set the width of the bars as a percentage. Any assistance on this matter would be highly appreciated.

Edit:

Credit to Tasos Bu for providing me with an answer that helped me achieve my intended design, covering edge cases and ensuring the actual part of the bar stops at the desired point. The working solution can be found on this JSFiddle link for reference.

Final Edit:

After some additional tinkering, I finally managed to implement the full functionality I was aiming for. For those reading this, you can check out the finalized version through this JSFiddle link.

Answer №1

To enhance the appearance, you have the option to include a pseudo-element before the second bar and eliminate the radius of the first one: Check out this response

UPDATE: Bear in mind that by doing this, it will slightly shift the first bar to the right, so adjustments must be made when defining its width using JavaScript.

const data = {
    actual: 1155,
  projected: 1573,
  limits: [500, 1000, 2500]
};

const actualProgress = document.getElementById("actual-progress");
const projectedProgress = document.getElementById("projected-progress");

const barLength = Math.max(...data.limits);
const actualPercentage = (data.actual / barLength) * 100;
const projectedPercentage = ((data.projected - data.actual) / barLength) * 100;

actualProgress.style.width = `${actualPercentage}%`;
projectedProgress.style.width = `${projectedPercentage}%`;
.progress-bar.bg-actual {
  background: #b445f5;
  border-radius: 0;
}

.progress-bar.bg-projected {
  background: blue;
  position: relative;
}
.progress-bar.bg-projected:before {
  width: 30px;
  height: 30px;
  border-radius:0 500px 500px 0;
  background-color: #b445f5;    
  display: inline-block;
  vertical-align: middle;
  content: '';
}

.progress-bar {
  border-radius: 0 500px 500px 0;
}


.progress {
  border-radius: 500px !important;
  height: 30px !important;
}
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container pt-4">
  <div class="row">
    <div class="col">
      <div class="progress">
        <div id="actual-progress" class="progress-bar bg-actual"></div>
        <div id="projected-progress" class="progress-bar bg-projected"></div>
      </div>
    </div>
  </div>
</div>

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

Tips for toggling the visibility of an element when a button is clicked in React

In my todo list, I need to display the details of each item when clicked on a button. There are two buttons available: "View Details" and "Hide Details". Below is the code snippet: class Todos extends React.Component{ construc ...

The JQuery datepicker fails to function properly when the input field is modified from read-only

Utilizing the datepicker in conjunction with an MVC3 application. I aim to keep the input field as readonly until triggered by an edit button. Upon focusing on the field, I want the datepicker functionality to be activated. The code snippet below functio ...

What are the features of the vertical line with annotation plugin and category axis in Chart.js?

I am currently facing an issue with the vertical line in my chart created using chart.js. Specifically, the problem lies with the category axis where the years are labeled as [year 0, year 1, year 2, year 3..]. Here is an example of a functioning chart ...

css absolute positioning and setting the height of a repeating background

I am facing a challenge with a container that contains a repeating image and I want it to fill 100% of the available height. However, some inner divs have their :after pseudo elements absolutely positioned to achieve the desired borders, which is causing a ...

Adjusting the Aspect Ratio of an Embedded YouTube Video

<!DOCTYPE HTML> <head> <style> body { overflow: hidden; margin:0; } </style> </head> <body> <iframe id="video" src="https://www.youtube.com/embed/U4c9bBeUe4M?modestbranding=1&sh ...

Arranging Boxes side by side

I am struggling to align three boxes horizontally on my website, as they are currently stacking vertically. I have implemented Twitter Boostrap's 'row' class in an attempt to achieve this layout. HTML: .img-box-kai { width: 300px ...

Using the combination of z-index and visibility:hidden makes the button go completely undetect

Can someone please review this code? .parent { visibility: hidden; position: relative; z-index: 1; } .child { visibility: visible; } <button class="parent"> <span class="child">content</span> </button> I' ...

Change the position on the second click

I am trying to implement a manual sorting feature for a table of persons. The idea is to allow users to select a person by clicking on the row, then select another person by clicking on them, and have the two selected rows switch positions without using dr ...

Replacing a string using Regular Expression based on certain conditions

When working with a node.js server, I encountered the need to modify URL addresses using JavaScript in a specific way: For instance: hostX/blah/dir1/name/id.js?a=b --> name.hostY/dir2.js?guid=id&a=b Another example: hostZ/dir1/name/id.js --> ...

Ways to implement two functions within a single onclick event

Is it possible to call two functions with onclick event? <input id = "test" onclick="func1()"> Can I add another function as well? How would I go about doing that? ...

Create a unique jQuery script for a gallery that allows you to dynamically pass a CSS class as a parameter

Hey there! I'm a newbie in the world of JavaScript and programming, and I'm struggling to find an efficient solution for a script that assigns parameters to multiple photo galleries. The script is functional, but I believe it can be simplified to ...

Node.js used to create animated gif with unique background image

As I navigate my way through the world of node.js and tools like express and canvas, I acknowledge that there might be errors in my code and it may take me some time to grasp certain concepts or solutions. My current project involves customizing a variati ...

Utilizing Numerous JavaScript Functions within jQuery

I've been facing a persistent issue and I'm seeking guidance on how to resolve it. I have developed a multipage Jquery similar to the one showcased below. However, whenever I try to reference a .js file that I have saved, the pages either fail t ...

Exploring JSON data with ReactJS

I am experiencing issues with populating a table with data imported from a JSON file. The error message I'm receiving is: Uncaught Invariant Violation: Objects are not valid as a React child (found: object with keys {list}). If you intended to render ...

Communication between Nodemailer and Mailgun

I keep encountering an authentication issue while trying to use Nodemailer with Mailgun. I followed the Nodemailer documentation which states compatibility with Mailgun SMTP, but unfortunately, I am consistently facing this error when executing my applicat ...

Refresh a specific portion of an HTML template following a successful AJAX request

I am facing a challenge in implementing a new feature and I'm unsure of the best approach to take. In my project, I utilize Django for backend logic and templating, as well as the Google Closure JavaScript library for frontend development. Here is th ...

Risk Score Generating Form

As I work on a comprehensive form, there are 5 sections for users to mark if they qualify (using checkmarks). The form consists of approximately 50 questions in total. Each section carries different weights/points (e.g., Section 1 is worth 1 point each, ...

Interactive Vue tree view featuring draggable nodes

I am currently working on creating a tree component in Vue.js, and I am facing challenges with implementing drag and drop functionality in the Tree component. I am unsure where to begin, as I have looked through similar code on GitHub but I am struggling t ...

Converting JSON information into a mailto hyperlink

Can anyone help me figure out how to encode a mailto link properly with JSON data in the query parameters, ensuring that it works even if the JSON data contains spaces? Let's consider this basic example: var data = { "Test": "Property with spaces" ...

WordPress Header Display Issue on Mobile and Tablet Devices: What You Need to Know

I'm facing an issue with the header and footer being cut off on mobile devices. When viewed on a tablet or phone, the header doesn't display across the full width of the screen. This problem arises because the Wordpress theme was created in 2010 ...