Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fix inconsistent rendering of adjacent TD borders when they are collapsed?

I have an HTML table with collapsed and adjacent borders and a standard border on all cells and I want to change the border color of a specific row to something else. The problem is that when the borders are collapsed and neighboring cells have different colors (or styles in general I assume) the browser does not render in a visually acceptable manner.

Here's my HTML:

<table>
    <tr><td>Lorem</td><td>Ipsum</td></tr>
    <tr><td>Lorem</td><td>Ipsum</td></tr>
    <tr id="foo"><td>The border of these cells</td>
                 <td>is not uniformly red!</td></tr>
    <tr><td>Lorem</td><td>Ipsum</td></tr>
</table>

The CSS:

table { border-collapse: collapse; border-spacing: 0 }
td { padding: 5px; border: 3px black solid; }
#foo td { border: 3px red solid; }

There is also a JSFiddle of the above.

How different browsers render it:

IE 7 (standards):

IE 7 standards

IE 8 and 9 (standards):

IE 8, 9 standards

Firefox 11 (note the subtle visual artifact on the left red border and the quirky way it chooses to render the corners):

FF 11

Chrome 18:

Chrome 18

The question: What can I do to get a visually acceptable render? Can that render be the ideal of "red borders always take precedence over black ones"?

Clarification:

I am first and foremost looking for a pure CSS solution.

If this is not possible, I would work with something that requires small and localized modifications (i.e. not something I 'd have to do on every table everywhere).

Javascript is acceptable, since in the actual website the styles that control the borders are applied dynamically based on user interaction. The event handlers are set up by code almost identical to this.

like image 238
Jon Avatar asked Mar 29 '12 10:03

Jon


People also ask

Which of the following is used to collapse adjacent cells and make common border?

collapse: It is used to collapse adjacent cells and make common border. initial: It is used to set border-collapse property to its default value. inherit: It is used when border-collapse property inherit from its parent elements.

What is the difference between border-collapse collapse and border-collapse separate?

(See Snippet below to confirm). The border-collapse CSS property determines whether a table's borders are separated or collapsed. In the separated model, adjacent cells each have their own distinct borders. In the collapsed model, adjacent table cells share borders.


2 Answers

I came to this solution without extra-markup : http://jsfiddle.net/fcalderan/PAJzK/12/

the idea is to avoid using border-collapse and using border top/right for table cells and border bottom-left for table element.

tried with IE8, FX11 and CH17, here's the relevant CSS

table {  
    border-spacing : 0;
    border-left    : 3px black solid;
    border-bottom  : 3px black solid;
}

td { 
    padding      : 5px; 
    border-right : 3px black solid; 
    border-top   : 3px black solid;
}

#foo td { border-color:red; }


/* border left red-coloured using :before pseudoelement */
#foo td:first-child:before { 
    content       : ""; 
    position      : relative;
    margin-left   : -8px;
    padding       : 8px 0 8px 5px;
    border-left   : 3px red solid;
}

/* top border of next rows red coloured */
#foo + tr td {  
    border-top: 3px red solid;  
}

here an issue occurs if the highlighted row is the last one: in that case #foo + tr td wouldn't match anything : in that case you could write instead this rule

#foo td:after {
   content    : "";
   position   : relative;
   margin     : 0 0 0 -8px;
   display    : block;
   width      : 100%;
   height     : 3px; 
   padding    : 0 8px;
   top        : 2px;
   margin-bottom : -6px;
   border-bottom : 3px red solid;
}

see example in http://jsfiddle.net/fcalderan/PAJzK/14/

like image 200
Fabrizio Calderan Avatar answered Sep 28 '22 23:09

Fabrizio Calderan


You need extra markup, setting e.g. id=before-foo on the preceding row and id=after-foo on the next, with a style sheet addition like

#before-foo td {
  border-bottom-color: red; }
#after-foo td {
  border-top-color: red; }

Demo: http://jsfiddle.net/8C8Rd/

There can still be issues at cell corners (a corner can be black).

The reason why this cannot be done in a simpler way is that the effect of border collapse had been vaguely defined and inconsistently implemented in browsers. CSS 2.1 drafts even used to leave the color in situations like this browser-dependent. Even though the final CSS 2.1 specification has requirements on this in its border conflict resolution rules, they are not universally implemented—and in this case, they say that the border of the cells of the upper row wins (as in most browsers you tested), so there is no direct way to specify the rendering you describe. That is, you would need to set some styles on the preceding row as well anyway.

like image 40
Jukka K. Korpela Avatar answered Sep 26 '22 23:09

Jukka K. Korpela