Как исправить несогласованный рендеринг смежных границ TD, когда они свернуты?

У меня есть HTML-таблица со свернутыми и смежными границами и стандартной границей для всех ячеек, и я хочу изменить цвет границы определенной строки на что-то другое. Проблема в том, что когда границы свернуты, а соседние ячейки имеют разные цвета (или, как я полагаю, стили), браузер не визуализирует визуально приемлемым способом.

Вот мой 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>

CSS:

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

Существует также JSFiddle из вышеперечисленного.

Как это делают разные браузеры:

IE 7 (стандарты):

Стандарты IE 7

IE 8 и 9 (стандарты):

IE 8, 9 стандартов

Firefox 11 (обратите внимание на тонкий визуальный артефакт на левой красной границе и причудливый способ визуализации углов):

FF 11

Chrome 18:

Chrome 18

Вопрос: что я могу сделать, чтобы получить визуально приемлемый рендер? Может ли это быть идеалом "красные границы всегда имеют приоритет над черными"?

Разъяснение:

Я в первую очередь ищу чистое решение CSS.

Если это невозможно, я бы работал с чем-то, что требует небольших и локализованных модификаций (то есть не то, что я должен был бы делать на каждой таблице везде).

Javascript является приемлемым, поскольку на реальном веб-сайте стили, которые управляют границами, применяются динамически в зависимости от взаимодействия с пользователем. Обработчики событий устанавливаются кодом, практически идентичным этому.

2 ответа

Решение

Я пришел к этому решению без лишней разметки: http://jsfiddle.net/fcalderan/PAJzK/12/

идея состоит в том, чтобы избежать использования border-collapse и используя границу top/right для ячеек таблицы и границы bottom-left для элемента таблицы.

пробовал с IE8, FX11 и CH17, вот соответствующий 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;  
}

здесь возникает проблема, если выделенная строка является последней: в этом случае #foo + tr td не будет ничего соответствовать: в этом случае вы можете написать вместо этого правила

#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;
}

см. пример в http://jsfiddle.net/fcalderan/PAJzK/14/

Вам нужна дополнительная разметка, например настройка id=before-foo в предыдущем ряду и id=after-foo на следующем, с добавлением таблицы стилей, как

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

Демо: http://jsfiddle.net/8C8Rd/

Могут быть проблемы на углах ячейки (угол может быть черным).

Причина, по которой это не может быть сделано более простым способом, заключается в том, что эффект коллапса границы был неопределенно определен и непоследовательно реализован в браузерах. Черновики CSS 2.1 даже используются, чтобы оставить цвет в ситуациях, подобных этому зависящему от браузера. Несмотря на то, что окончательная спецификация CSS 2.1 имеет требования к этому в своих правилах разрешения конфликтов границ, они не реализованы повсеместно - и в этом случае они говорят, что граница ячеек верхнего ряда выигрывает (как в большинстве протестированных вами браузеров), поэтому нет прямого способа указать рендеринг, который вы описываете. То есть, вам все равно нужно будет установить некоторые стили в предыдущем ряду.

Другие вопросы по тегам