views:

331

answers:

7

I'm implementing my own Progress Bar using jQuery. My question is how can I fill (for example) only 30% of it with a background ? What are my options ? Basically, the Progress Bar is a simple div with rounded corners (-moz-border-radius). I'm using Firefox 3.6.3.

[Update] I tried this example. How to force the right side of the filled area not to be rounded like in the third example ? The fourth example is problematic though... How would you solve this ?

Thanks !

+5  A: 

A simple option is use a background colour, make sure the outer container width is fixed and then just set the inner div's width to a percentage that's the same as the progress.

Russ C
So you suggest to use 2 containers. I wonder whether the inner container is indeed needed... Maybe there is some option to fill only some part with a background ?
Misha Moroshko
You could do this with one div, and a background image using background position. You know how wide the progress bar is, and the image needs to be at least that wide. Then based on the value of the progress, move the background position to fill the div.
S Pangborn
Its best to use an Outer and Inner so you can set the outer to a static width, say 120px or something that suits your page, then the inner div can be sized with a Percentage and it'll be relative to the outer div.Adirael's example below works nicely for this.
Russ C
Also, JQuery itself has a really easy one, requires jquery.ui.core:http://docs.jquery.com/UI/Progressbar
Russ C
+1 for the jQuery UI progressbar. It's pretty easy to use. However, if you're looking to implement your own, the approach supplied by Russ C and Adirael both work.
S Pangborn
+3  A: 

You can use 2 divs, one inside the other, put the background on the inner one and set it's width with a %, something like this:

<div style="">
    <div style="background: red; width: 50%">&nbsp;</div>
</div>​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​
Adirael
I wonder why this ` ` needed ?
Misha Moroshko
I could give the div a height and not only a width, laziness I suppose! You can change the style to something like "width: 50%; height: 5px" and remove the unbreakable space :)
Adirael
OK, thank you ! I tried your idea, but cannot understand how to force the right side of the filled area not to be rounded like in the third example here: http://jsfiddle.net/EcSzy/ The fourth example is problematic though... How would you solve this ?
Misha Moroshko
You could detect when the progress bar is nearing full, and add the CSS style to make it curved.
S Pangborn
This will not work. See here: http://jsfiddle.net/aXkFS/
Misha Moroshko
Due to a bug in Firefox's overflow clipping, the problem you're seeing in the fourth example simply won't be fixed unless you're using some fairly sophisticated Javascript to add the curved corners to the right side. Calculating the point where you'd do that would have to be based on the corners of the parent element. I'm going to reccomend the jQuery UI progressbar, as they've managed to implement such a method. http://jqueryui.com/demos/progressbar/
S Pangborn
+4  A: 

You could use one div and an image, as I mentioned earlier in a comment. Here's a way you could do it. (Not completely tested, so it may break.)

HTML:

<div id="progressBar"></div>

CSS:

 #progressBar {
   width: 200px;
   height: 20px;
   background: url('http://o.imm.io/x9E.jpg') no-repeat;
   background-position: -200px 0px;
   -moz-border-radius: 10px;
   -webkit-border-radius: 10px;
}

JS:

function setProgress(target,value) {

  var oldPosition = $(target).css("backgroundPosition");

  // Log the old position 
  console.log("Old position: " + oldPosition);
  var newPosition = parseInt(oldPosition) + parseInt(value);

  // Log the new position
  console.log("New position: " + newPosition);
  $(target).animate({backgroundPosition: newPosition + 'px 0px'})
}

Edit: I added the rounded corners and it works exactly as you specified, no issues with the rounded corners.

Edit 2: Check out the JSBin version of this code.

Edit 3: As the OP said, they needed the progress bar to be flexibly sized. This implementation won't do that. I'm going to recommend (as I have earlier) the use of the jQueryUI Progress Bar. It's easy to use, and fairly lightweight.

Edit 4: I've come up with another implementation of this, which requires a bit more Javascript, but you can test it out here: http://jsfiddle.net/ntnz4/7/

S Pangborn
The problem with your code is that the image is good for this specific size of the progress bar. As I mentioned in the question, I'm implementing my own progress bar, i.e. users should be able to set the dimensions of it. Thus, I need a solution for all possible progress bar dimensions. Do you have any idea how to handle this ? Thanks !
Misha Moroshko
True, this is limited to a set size. However, you didn't specify that you needed users to be able to set the width. ;)
S Pangborn
Just added a new version of the progress bar, check out http://jsfiddle.net/ntnz4/7/
S Pangborn
Thanks for your efforts ! One question, if the border radius changed in the CSS, to 20px for example, your code does not take this into account, right ? I'm looking for 100% CSS configurable solution.
Misha Moroshko
It should, the code is grabbing the border width from the CSS attribute. It may need a bit more code to make it more robust, however.
S Pangborn
Here's a slightly improved, more robust version that handles browsers without border-radius a bit better: http://jsfiddle.net/ntnz4/8/
S Pangborn
+1  A: 

I've done what you're doing for a few of my sites, here's what I did:

I first did some basic markup:

<div id="progressBar">
    <div id="progressBarInner"></div>
</div>

And the CSS:

#progressBar {
    width: 200px;
    height: 20px;
}

#progressBarInner {
    background: url('path/to/your/progress/image.jpg');
    width: 100%;
    height: 100%;
}

When this is done, setting the progress is actually really simple. Whatever progress you want to be displayed in the progress bar, you set to the width of the #ProgressBarInner element. For example, if you wanted to show 32%, you'd set this:

width: 32%

for the progressBarInner div.

I don't know how to do this using jQuery off the top of my head, but I do know for a fact you can set CSS properties using it, so this is entirely possible.

Joshua
Thanks for explanation, but my main problem is the rounded corners which I don't understand how to manage.
Misha Moroshko
+1  A: 

HTML:

<div class="progress"><div style="width:30%"></div></div>

CSS:

    .progress {
    width: 300px;
    -moz-border-radius: 5px;
    -webkit-border-radius: 5px;
}

.progress div {
    background: url(background.png);
    height: 10px;
    -moz-border-radius-topright: 5px; -moz-border-radius-bottomright: 5px;
    -webkit-border-top-right-radius: 5px; -webkit-border-top-right-radius: 5px;
}
aRagnis
+2  A: 

Don't know what you are using to animate the progress bar, but if you can change the radius as it approaches the end you can get a smooth transition.

$('#inner4')
    .css('width',25)
    .css('-moz-border-radius-topright','0')
    .css('-moz-border-radius-bottomright','0')
    .animate(
      {
        width:425
      },
      3000, 'linear',
      function() {
          $('#inner4').animate({
            width:450,
            '-moz-border-radius-bottomright':'+=25',
            '-moz-border-radius-topright':'+=25'
          },
          200,'linear',
          function() {}
        );//end inner animate
      }
    );//end animate

Here's an example

Lee
+1 nice try bro! ;-)
aSeptik
A: 

I'm a bit confused on what you want to do regarding the rounded corners on the filled color! But if it's supposed to be advancing straight, not rounded, just set the wrapper div with css overflow:hidden;

With that, the inner div will advance all the way to the 100% and when passing the rounded area will create a cool effect!

Zuul