-->

How to fix inconsistent rendering of adjacent TD b

2019-04-10 06:51发布

问题:

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 8 and 9 (standards):

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

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.

回答1:

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/



回答2:

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.