Search code examples
c#cssrazorprogress-barbootstrap-5

Bootstrap progress bar with label OVER bar/background to the right


How can I achieve the following progress bar with a label over to the right with a Bootstrap v5.2 Progress Bar?

Style I am trying to achieve

I have tried using negative margins and got close, but I'm having problems when the label gets wider due to the text getting longer:

What I got so far

Here is my code to get the above:

Single row (ProgressBarWithName.cshtml):

@{
    var valuePercentage = (double)Model.Value / Model.MaxValue * 100;
}

<div class="row m-2" style="height: 50px;">
    <div class="col-3 text-white bg-dark h-100 d-flex justify-content-end">
        <div class="font-allan align-self-center"><b>@Model.Name</b></div>
    </div>
    <div class="col-9 h-100">
        <div class="row gx-0 progress-container h-100">
            <div class="col-11">
                <div class="progress h-100">
                    <div class="progress-bar"
                         role="progressbar" aria-label="Example with label"
                         aria-valuenow="@valuePercentage" aria-valuemin="0" aria-valuemax="@Model.MaxValue"
                         style="width: @valuePercentage%;">
                    </div>
                </div>
            </div>
            <div class="col-1 progress-label align-self-center">
                <b class="@if (valuePercentage > 85){ <text>text-white</text> }">@Model.Value</b>
            </div>
        </div>

    </div>
</div>

All rows (CustomBarChart.cshtml):

<div>
    @foreach (var item in Model.Items)
    {
        await Html.RenderPartialAsync("ProgressBarWithName", item);
    }
</div>

And I'm just hard-coding some models for testing purposes:

@{
    var stat = new Stat("Some Stat", 40, 100);
    var stat1 = new Stat("Some Stat1", 84, 100);
    var stat2 = new Stat("Some Stat2", 86, 100);
    var stat3 = new Stat("Some Stat3", 10, 100);
    var stat4 = new Stat("Some Stat4", 100, 100);
    var stats = new Stats(new List<Stat> { stat, stat1, stat2, stat3, stat4 });
    await Html.RenderPartialAsync("CustomBarChart", stats);
}

CSS:

.progress-container{
  margin-right: -60px;
}

.progress-label{
  margin-left: -35px;
  width: 0;
}

Essentially, my problem is that the default style of the bootstrap progress bar puts the label in the filled portion of the bar. What I'm trying to do is put the label on the right side of the entire bar (whether it be the filled portion or the background). I have tried with float, but since I'm using a row/col setup to get that sort of grid style I'm emulating.


Solution

  • Got it:

    <div class="row m-2" style="height: 50px;">
        <div class="col-4 text-white bg-gray h-100 d-flex justify-content-end rounded-2 p-2" title="@Model.Name">
            <b class="font-sans align-self-center mh-100 w-100 overflow-hidden"
               style="text-overflow: ellipsis; white-space: nowrap;">
                @Model.Name
            </b>
        </div>
        <div class="col-8 h-100 progress-label-container">
            <div class="progress h-100">
                <div class="progress-bar"
                     role="progressbar" aria-label="Example with label"
                     aria-valuenow="@valuePercentage" aria-valuemin="0" aria-valuemax="@Model.MaxValue"
                     style="width: @valuePercentage%;">
                </div>
            </div>
            <div class="progress-label">
                <b>@Model.Value @Model.Units</b>
            </div>
        </div>
    </div>
    
    .progress-label-container{
      position: relative;
    }
    
    .progress-label{
      position: absolute;
      right: 7.5%;
      top: 25%;
    }
    

    result