I want to have XHTML+CSS progress bar with contrast colors between filled and empty background areas.
I have a problem with text color. Because filled and empty backgrounds are too contrast (this is a requirement), to remain readable the text should be double-colored to be contrast to both of them. The image should explain it better than words:
Progress bar with dark blue filled area and white empty background http://drdaeman.pp.ru/tmp/20090703/progress-bar-text-example.png Example of the problem http://drdaeman.pp.ru/tmp/20090703/progress-bar-text-problem.png
My current progress bar implementation is trivial, but as example above shows, the text can be hard to read in some cases, which is exactly a problem I want to solve.
My current (simplified) implementation attempt (fails, because overflow: hidden
does not work without positioning div.progress
which I cannot position because of inner span
's width
):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<title>Progress bar test</title>
<style type="text/css">
div.progress_bar {
border: 1px #ccc solid; position: relative;
text-align: center; height: 32px;
}
div.progress_bar .progress {
height: 32px;
overflow: hidden; /* This does NOT work! */
}
div.progress_bar .progress div {
position: absolute; width: 100%; height: 32px;
z-index: 30; overflow: hidden;
background-color: #44a;
}
div.progress_bar span {
position: absolute; top: 0; left: 0; width: 100%;
z-index: 20;
color: #000;
}
div.progress_bar .progress span {
position: absolute; top: 0; left: 0; width: 100%;
z-index: 40;
color: #eee;
}
</style>
</head>
<body>
<!-- Can be of any (unknown) width. Think of "width: auto".
The 400px value is just to keep it small on a big monitor.
DON'T rely on it! -->
<div id="container" style="width: 400px;">
<div class="progress_bar">
<!-- div.progress is a dark filled area container -->
<div class="progress" style="width: 51%;">
<!-- Actually dark filled area -->
<div style="width: 51%;"></div>
<!-- Text (white).
Does not clip, even with overflow: hidden on parent! -->
<span>This is a test</span>
</div>
<!-- Text (black) -->
<span>This is a test</span>
</div>
</div>
</body>
</html>
Live version of the above: http://drdaeman.pp.ru/tmp/20090703/test2.html
Previous attempt: http://drdaeman.pp.ru/tmp/20090703/test.html
The images are GIMP edited prototypes, and not exactly what this code displays.
Add: Thank you all, especially Meep3D, Nosredna and Lachlan! However I still have a problem — in my case progress bar should have no fixed width and take all horizontally available space (width: auto;
or width: 100%
are acceptable). But without width: 400px
rule Lachlan's code breaks. And I'd still like to avoid using JavaScript, if that's possible.
As per Meep3D's suggestion, take 2 copies of the text.
Wrap each in a div of the same width as the container. The "upper" div is wrapped with another div which clips at the desired percentage.
Update: removed the fixed widths.
The "upper" div is sized to the inverse percentage of its wrapper.
<html>
<head>
<style type="text/css">
#container {
position: relative;
border: 1px solid;
text-align: center;
width: 400px;
height: 32px;
}
.black-on-white {
height: 32px;
color: #000;
}
.white-on-black {
height: 32px;
color: #fff;
background-color: #44a;
}
.wrapper {
width: 53%;
overflow: hidden;
position: absolute;
top: 0; left: 0;
}
.black-on-white {
width: 100%;
}
.white-on-black {
width: 188.7%;
}
</style>
</head>
<body>
<div id="container">
<div class="wrapper">
<div class="white-on-black">
<span>This is a test</span>
</div>
</div>
<div class="black-on-white">
<span>This is a test</span>
</div>
</div>
</body>
</html>
What about putting a second copy of the progress bar text inside the div, and set the div's overflow to hidden, so it reveals with it?
--
Update: I am also not a javascript expert, but I am sure that you can find out the width of an object and then set the offset based upon that if the width is flexible as you say.
You could:
[######### ] 50 %
You could use a text shadow for your "percentage" text. The only downside to this is that it would only work in the latest browsers. Only Firefox 3.5, Safari (all versions), and Chrome 2+ support it.
Here is a demo of using text-shadow in a way that would make your progress readable.
http://www.w3.org/Style/Examples/007/text-shadow#white
If you're willing to use more JavaScript, you could try this jQuery plugin:
http://kilianvalkhof.com/2008/javascript/text-shadow-in-ie-with-jquery/
The article says it works in IE only, however it works in Chrome 3 (what I'm using), Firefox 3.5, Internet Explorer, and Safari. It may work in older browsers but I haven't tested it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With