1

I'm using a table layout for data representation:

Table layout screenshot

The problem is that according to the design, i must put these separation borders between the cells.

I saw no way of accomplishing this, other than through the use of div elements within the td elements (which - correct me if i'm mistaken - shouldn't pose a problem).

Example

<table>
    <tr>
       <td>
          <div class="inner">
             Content
          </div>
       </td>
    </tr>
</table>

CSS

table td {
    padding: 15px 10px;
    border-bottom: 1px solid #e5e5e5;
}

table td div.inner {
    padding: 10px 25px 10px 0;
    border-right: 1px solid #e5e5e5;        
}

It works fairly well - what you see in the shot is the actual rendering in the browser.

But when you take a close look, you'll notice that the vertical lines (the border-right property of div.inner have varying heights. This, of course, makes sense and i understand why it happens. The content within div.inner will cause it to grow in height, adding the padding.

I tried setting a fixed height to div.inner which would be ok for my table, because i know exactly how much data i will represent and that it will never exceed a certain height. But when doing this, all content within div.inner becomes vertically aligned to the top, meaning that the naturally applied vertical-align property of my td elements is no longer affecting the content inside div.inner.

I tried applying display: inline-block to div.inner to trigger vertical centered alignment, which then caused the widths to vary. So i added width: 100% as well, which then resulted in misalignments on the horizontal axis (text overlapped borders) and finally didn't show the desired result regarding the vertical alignment. So this approach is fruitless.

How could i make those vertical separator lines be of equal height?

Or, alternatively, ...

How could i force vertical alignment of all content, when using a fixed height on div.inner?

Please note: Using line-height in any way to achieve the result (or attempt to) is not an option for me. As you can see in the screenshot, i am displaying a progress bar. This incorporates further elements within div.inner.

SquareCat
  • 5,699
  • 9
  • 41
  • 75
  • Why use a div again? Can't you achieve what you want by adding a border to the td? Or is it because you want the padding – Leeish Dec 25 '13 at 22:19
  • Yeah, exactly. I need the padding. I tried this with `cellspacing`, but to no avail - the borders would end up at the exact end of the `td` space, so it was of no use to me. – SquareCat Dec 25 '13 at 22:21

3 Answers3

1

I do not know what kind of browsers do you have to support for, but my solution requires browser support for the :before or :after pseudo elements, as well as support for the :last-child (or any CSS3) selectors.

Currently the global stats points to:

  • 84.9% total support + 7.56% partial support for CSS generated content. Source
  • 84.79% support for CSS3 selectors. Source

Therefore it is important that perfect cross-browser compatibility is impossible to be achieved, especially when considering antiquated browsers, but it only affects the layout, not the functionality of your site ;)

My solution is to set the position of each table cell to relative, and then add a pseudo-element that has a right border of 1px in width that is positioned absolutely within each cell:

table td {
    padding: 15px 10px;
    position: relative;
    border-bottom: 1px solid #e5e5e5;
}
table td:before {
    border-right: 1px solid #e5e5e5;
    content: ""; /* Need to declare content, even when empty! */
    position: absolute;
    top: 10px;
    bottom: 10px;
    right: 10px;
    width: 0;
}
    /* Optional, only if you want to                */
    /* remove border on last td element on each row */
    table td:last-child:before {
        display: none;    
    }

See working fiddle here (tested in Chrome, Safari and Firefox): http://jsfiddle.net/teddyrised/e4LXY/

The merits of this method is that it is widely supported in most modern browsers, and that since the :before pseudo element is added to the table cell instead of the inner div, it will stretch with the final computed height of the row, therefore ensuring that they will be of all equal height. The fiddle demonstrates that the content can be of variable height.

The only demerit is that there is no backward compatibility for browsers that do not support CSS generated content and/or CSS3 selectors. You might want to consider using a fallback style (like, a solid border for the entire table) for visitors on older browsers.

Terry
  • 63,248
  • 15
  • 96
  • 118
1

I had similar problem with menu, this is the CSS magic with which I solved it:

HTML:

<table>
    <tr>
       <td>
          <div class="inner">
             Content
          </div>
       </td>
        <td>
          <div class="inner">
              <span style="font-size:40px;">AAAA</span>
          </div>
       </td>
        <td>
          <div class="inner">
              <span style="font-size:8px;">asd</span>
          </div>
       </td>
    </tr>
</table>

CSS:

   table td {
    padding: 15px 10px;
    border-bottom: 1px solid #e5e5e5;
}

table td div.inner {
    padding: 10px 25px 10px 0;
    position: relative;
}
table td div.inner:after {
    position: absolute;
    top: 50%;
    margin-top: -20px;
    margin-bottom: -20px;
    margin-left: 23px;
    height:40px;
    width: 1px;
    content: "";
    background-color: #e5e5e5;
}

jsfiddle: http://jsfiddle.net/xJj2y/

gadelat
  • 1,390
  • 1
  • 17
  • 25
  • Thank your for providing this. In fact it is the correct answer, but since Terry answered a minute earlier, i accepted his answer as the solution. – SquareCat Dec 25 '13 at 23:00
0

I think setting a fixed height on the div and doing a vertical align middle on the td will fix it. Post a fiddle with some dummy rows and that can help.

Leeish
  • 5,203
  • 2
  • 17
  • 45
  • A `td` element has a 'naturally occurring' `vertical-align: middle` setting. Anyway i also tried adding this to the td explicitely, but to no avail. It doesn't help, neither on the `td` nor on `div.inner`. – SquareCat Dec 25 '13 at 22:22
  • I know I've done this before. I need to remember how. One sec. – Leeish Dec 25 '13 at 22:24
  • There is no proper vertical alignment here. And the content of `div.inner` should not exceed the height of the vertical line. – SquareCat Dec 25 '13 at 22:30
  • http://jsfiddle.net/Ry7aq/1/ As you can see the green divs are properly aligned. The content starts in the same spot. Your issue isn't with div alignment. If you know the height, they will never need to extend beyond it. – Leeish Dec 25 '13 at 22:31
  • The `div` elements are properly aligned, according to what `td` dictates for them to be, but within those blocks there is no proper vertical alignment. [See this](http://jsfiddle.net/Ry7aq/2/). – SquareCat Dec 25 '13 at 22:33
  • But you said you know what was in the divs. If you control that and it's consistent just center the content correctly in the div. Are you asking how to center content in a DIV? You problem sounds more like how to center content vertically in a div – Leeish Dec 25 '13 at 22:34
  • http://stackoverflow.com/questions/8865458/how-to-align-text-vertical-center-in-div-with-css. http://blog.themeforest.net/tutorials/vertical-centering-with-css/. Since your DIV, as show in my Fiddle, is centered correctly and making the borders how you want, I suggest you read up on how to center content within a div as that sounds more like what you need to understand how to do. There are various methods. – Leeish Dec 25 '13 at 22:37
  • As i stated in my question, i tried to apply `display:inline-block` (to trigger vertical centered alignment). I explained in my question what happens when i do that. When i try `display:table-cell` instead, i get the same problem but then i cannot even trigger full widths using `width:100%` – SquareCat Dec 25 '13 at 22:40
  • The DIV IS VERTICALLY CENTERED in the TD. The content in the DIV is NOT vertically centered in the DIV. You need to vertically center the content IN THE DIV. `display:table-cell` will not work as that will break it acting like a block. Just center the content in the DIV and that will work. – Leeish Dec 25 '13 at 22:43
  • No need for caps. I already got your point. Thanks. In order to center the content within the `div` i would have to use one of the usually applied methods, none of which can yield the desired result in the given case. – SquareCat Dec 25 '13 at 22:48