bigblind
bigblind

Reputation: 12877

Scaling a 1% width div up 100 times doesn't cover the full width of the parent

I'm trying to make a progress bar.

You'd think that a div with a width of 1% scaled up horizontally 100 times would span the width of its parent, but it doesn't. The amount of space left seams to depend on my window size, so I think this might be a rounding issue in the browser. Is there anything I can do to make this work?

I'm changing the progress of this bar quite often, so I don't want to change the bar's width property every time, as that would cause performance issues.

body {
  margin: 0;
  padding: 0;
}
#container {
  background-color: red;
  position: fixed;
  left: 0;
  right: 0;
  top: 0;
  padding: 0;
  margin: 0;
  height: 100px;
}
#progress {
  position: absolute;
  left: 0;
  top: : 0;
  width: 1%;
  height: 100%;
  background-color: yellow;
  transform: scale(100, 1);
  transform-origin: left top;
}
<div id="container">
  <div id="progress">
  </div>
</div>

I also made a codepen to demonstrate this issue: http://codepen.io/bigblind/pen/Zbozjv

Upvotes: 3

Views: 62

Answers (2)

Kristof Mols
Kristof Mols

Reputation: 3557

Problem

Looks to me that there is a rounding issue.

On a 1920 pixel monitor, 1% gets translated to 19.188 pixels which gets rounded down to 19 pixels

19 pixels * 100 = 1900 pixels which leaves a 20 pixel gap.

More information here: http://ejohn.org/blog/sub-pixel-problems-in-css/

Edit: if you rescale your browser, on some widths, the red part is larger, smaller or gone; which confirms the rounding issue.

Solution

Declare a progress bar with a fixed width : 200px
Initialise it to 2px which can't be rounded up/down

Upvotes: 1

Abhitalks
Abhitalks

Reputation: 28437

The amount of space left seams to depend on my window size, so I think this might be a rounding issue in the browser.

Yes. It is.

I don't want to change the bar's width property every time

I am not trying to debate the performance thingy here, but just trying to concentrate on the problem that if not width then what property could be used?

Well, you could just turn your progress on its head. Instead of the #progress div expanding to show the amount of progress, slide it out of the way to reveal the background #container div to show the amount of progress. Use the translate to slide the progress away.

In the demo below, hover to see the transform in effect.

Demo Fiddle: http://jsfiddle.net/abhitalks/y2o7yub9/1

Demo Snippet:

* { box-sizing: border-box; padding: 0; margin: 0; }
html, body { width: 100%; }
#container{
    background-color: yellow; position: fixed;
    left: 0; right: 0; top: 0;
    height: 100px; width: 100%;
    overflow: hidden; white-space: nowrap;
}
#progress{
    position: absolute; left: 0; top: 0;
    width: 100%; height: 100%;
    background-color: red;
    transform: translateX(0%); transition: transform 0.5s;
}
#container:hover > div { transform: translateX(100%); }
<div id="container">
  <div id="progress"></div>
</div>

Upvotes: 3

Related Questions