4

I have an HTML table showing a list of person. For each row, I would like to have a different progressbar-like background. Something like

<table>
  <tr class="progress-full">...</tr>
  <tr class="progress-half">...</tr>
  <tr class="progress-quarter">...</tr>
</table>

With the whole background of the first row in color, half of the secord and 1/4 of the last one (with classes or using directly the percentage in CSS).

I tried using a background with a width (like here) but I didn't succeed. Can I enclose a div inside a tr ? When I inspect the html code (eg: with chrome) the div seems outside of the table.

<table style="width: 300px;">
      <tr style="width: 75%; background: rgb(128, 177, 133);">
        <div style="width: 300px;">...</div>
      </tr>
      <tr style="width: 50%; background: rgb(128, 177, 133);">
        <div style="width: 300px;">...</div>
      </tr>
</table>

Or maybe another method ?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Martin Trigaux
  • 5,311
  • 9
  • 45
  • 58
  • of course, it's not an option to put the background color on the column in the lines? – wazaminator Apr 18 '13 at 14:15
  • A row represent a person and I want to show the progress of that person. I am afraid putting it in only one cell wouldn't be as representative. So it is not out of the question but I would rather not. – Martin Trigaux Apr 18 '13 at 14:19
  • 1
    Create one image that would be the width of the row if it was full. Set this as the background image and use background position to show less. – Jared Apr 18 '13 at 14:24
  • Is it possible to use this method with a variable length table ? Also not mandatory but I would rather be able to change the size of the table without having to change too much pictures and CSS. – Martin Trigaux Apr 18 '13 at 14:30

5 Answers5

5

You could avoid adding any extra markup to your table if you use CSS ::before or ::after pseudo-elements. You can give each table row a transparent background, and give the pseudo-element the width you want.

Here's a jsfiddle example.

enter image description here

HTML:

<table>
    <tr class="progress-full">
        <td>Row 1 Col 1</td>
    </tr>
    <tr class="progress-quarter">
        <td>Row 2 Col 1</td>
    </tr>
    <tr class="progress-half">
        <td>Row 3 Col 1</td>
    </tr>
</table>

CSS:

td { padding: 10px; }

tr.progress-full td:first-child,
tr.progress-half td:first-child,
tr.progress-quarter td:first-child {
    position: relative;
}
tr.progress-full td:first-child::before,
tr.progress-half td:first-child::before,
tr.progress-quarter td:first-child::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    width: 0;
    height: 100%;
    background-color: red;
    z-index: -1;
}

tr.progress-full td:first-child::before {
    width: 100%;
}
tr.progress-half td:first-child::before {
    width: 50%;
}
tr.progress-quarter td:first-child::before {
    width: 25%;
}

This CSS could be slimmed down, depending on how variable the table structure is. I applied the styles onto the first td inside each tr. If you need the progress bar to stretch across multiple tds, use a width of greater than 100%.

mwcz
  • 8,949
  • 10
  • 42
  • 63
  • Firefox seems to be treating the pseudo elements as children of `body` instead of children of each `td`. The `td` elements have relative positioning, so the absolutely-positioned pseudo elements *should* be placed inside them (as seen in Chrome and IE9). Why it doesn't work in Firefox I have no idea. Googling hasn't helped so I'll start a new question about it. – mwcz Apr 19 '13 at 14:14
  • Aha, apparently `td` elements cannot be relatively positioned. Sadly a `div` must be added to my example to make it work. Here is a Firefox-friendly (and standards compliant) version: http://jsfiddle.net/4v9Pq/ – mwcz Apr 19 '13 at 14:32
  • @Oktav the answer is yes, but it involves creating nasty in-line style elements. See http://stackoverflow.com/questions/7731837/using-css-for-pseudo-elements – mwcz Nov 12 '13 at 15:21
  • @mwcz Thanks, I tried that but it only works for `content`, i needed `width`. I ended up creating a dynamic stylesheet, append it to some DOM element and create rules with pseudo classes via `sheet.addRule("selector", "value", index)` – Oktav Nov 12 '13 at 15:33
  • It's also possible to use css3's `attr()` to "pass" values into pseudo-elements' CSS properties, but browser support for it is quite poor. It's definitely the best approach, though. Soon. :) http://www.w3.org/TR/css3-values/#attr – mwcz Nov 12 '13 at 15:35
  • @Oktav Yeah, css2.1's `attr()` isn't powerful enough, but css3's is. I updated my comment. Soon you'll be able to do `width: attr(data-width %);`. – mwcz Nov 12 '13 at 15:36
1

why don't you simply put divs or anyother suitable container inside your tds and assign them width and background-color?

something like below:

<table style="width: 300px;">
      <tr>
          <td>
               <div  class="progress-full" >
                   ...
               </div>
          </td>
      </tr>
      <tr>
          <td >
                <div class="progress-quarter" >
                    ...
                </div>
          </td>
      </tr>
</table>

see this DEMO

Manish Mishra
  • 12,163
  • 5
  • 35
  • 59
  • With your solution, having a long text inside a td is a problem. For instance put "abc def ghi jkl mno" inside "progress-quarter" div. You will get the text over several lines. – Martin Trigaux Apr 19 '13 at 15:46
1

put the percentage width on the div rather than the tr (also you missed the tds)

http://jsfiddle.net/WmESh/3/

<table style="width: 300px;">
  <tr>
      <td>
        <div style="width: 75%; background: rgb(128, 177, 133); overflow:visible;">
            <div style="width:300px;">
                ... 
            </div>        
        </div>
      </td>
  </tr>
  <tr>
      <td>
        <div style="width: 50%; background: rgb(128, 177, 133); overflow:visible;">
            <div style="width:300px;">
                ... testing sdfsdfsdfsd sdfsdsdf sdf sdfsd fsd fsd fsdfsdff sdfsdfsd
            </div>
         </div>
      </td>
  </tr>
</table>

if you do not want the content to be the full width of the table just delete the <div style="width:300px;"></div>

Pete
  • 57,112
  • 28
  • 117
  • 166
0

Using @mwcz answer.

In HTML (I use twig but you can get the idea):

<td class="text-right pie-progress pie-progress-share{{ (count/totalCount)|round }}">{{ count }}</td>

In CSS:

td.pie-progress {
    position: relative;
}
td.pie-progress::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    width: 0;
    height: 100%;
    background-color: #66afe9;
    z-index: -1;
}
td.pie-progress-green::before {
    /* example of other color */
    background-color: #66af66;
}
td.pie-progress.pie-progress-share1::before {width: 1%;}
td.pie-progress.pie-progress-share2::before {width: 2%;}
...
td.pie-progress.pie-progress-share100::before {width: 100%;}
luchaninov
  • 6,792
  • 6
  • 60
  • 75
-1

a way to do it is to make an image with the color you want, the color you want and half blank, the color you want and 3/4 blank, and use bacjground-image.

it's dirty,but simple

wazaminator
  • 245
  • 3
  • 15
  • The problem is that I would have to create 100 different images for each percent :) I want to be able to provide any percentage I want. Also if possible not have a fixed size for the table. – Martin Trigaux Apr 18 '13 at 14:26