Carlos Gil
Carlos Gil

Reputation: 605

Sum of percent widths not rounded to 100%

I want to make a multi-segment progress bar. It has to be horizontally centered, with a maximum width, but not a static one, so it can shrink if there is not enough space.

The problem is that sometimes the total progress is at 100%, but the segments could be at 33.33% and 66.66%. The percentages are being calculated based on the width of the document, which may be an odd number, so the bar segments' widths are rounded in a way that leaves one pixel empty on the bar.

HTML

<div class="CENTER">
    <div class="BAR">
        <div class="SEGMENT ONE" style="width: 33.33%;"></div>
        <div class="SEGMENT TWO" style="width: 66.66%;"></div>
    </div>
</div>

CSS

.CENTER {
    max-width: 400px;
    margin-left: auto;
    margin-right: auto;
}

.BAR {
    height: 10px;
}

.SEGMENT {
    float: left;
    height: 100%;
}

.BAR { background-color: #F00; border: 1px solid #000; }

.SEGMENT.ONE { background-color: #FDA; }

.SEGMENT.TWO { background-color: #ADF; }

Play around with the width of the window after it's big enough for the bar to reach its maximum width.

There will be a red one pixel wide section on the right side of the bar.

How can I avoid it?

Example: http://jsfiddle.net/CV6fp

Can you do it using that same HTML and without JavaScript, CSS?

Upvotes: 1

Views: 1512

Answers (4)

David Fleeman
David Fleeman

Reputation: 2638

Here is how I would do it:

http://jsfiddle.net/CV6fp/3/

Basically, drop the width property off the div with class TWO. Then make the same div NOT float left:

<div class="CENTER">
    <div class="BAR">
        <div class="SEGMENT ONE" style="width: 33.33%;"></div>
        <div class="SEGMENT TWO">&nbsp;</div>
    </div>
</div>

And the style change:

.SEGMENT.TWO { background-color: #ADF; float:none; }

This means that second segment no longer floats:left, but I do think this may be what you are looking for.

Update: And finally after much soul searching, a CSS only solution to solve all the issues mentioned on this page:

http://jsfiddle.net/CV6fp/7/

Two changes to CSS: (1) segments set to float:right, and (2) .SEGEMENT.ONE to override that and always float:left

.SEGMENT {
    float: right;
    height: 100%;
}

.SEGMENT.ONE { background-color: #FDA; float:left; }

Upvotes: 2

Carlo Cannas
Carlo Cannas

Reputation: 3262

Maybe with table display?

http://jsfiddle.net/CV6fp/6/

.CENTER {
    max-width: 400px;
    margin-left: auto;
    margin-right: auto;
}

.BAR {
    height: 10px;
    display: table;
    width: 100%;
}

.SEGMENT {
    display: table-cell;
    height: 100%;
}

.BAR { background-color: #F00; border: 1px solid #000; }

.SEGMENT.ONE { background-color: #FDA; }

.SEGMENT.TWO { background-color: #ADF; }

Upvotes: 3

dave
dave

Reputation: 4403

Try: .SEGMENT:last-child { float: none; width: auto !important; }. This should make the last segment to fill the remaining space.

Upvotes: -1

Erik
Erik

Reputation: 12858

In this case you may need to reduce accuracy to the tenth's place and use a ceiling rounding function on the final segment. This way you would get 33.3% and 66.7%.

Upvotes: -1

Related Questions