A better alternative than for showing empty HTML table cells? - html

It's a classic problem - when you have an empty table cell the browser doesn't render borders around it. There are also two well-known workarounds. One is to place an in the table cell; the other is to use the empty-cells:show CSS property.
Unfortunately both have drawbacks. is kind of ugly when it comes to selecting text and copy-pasting it. You get a lot of spaces where there shouldn't be any, perhaps even with an exotic Unicode character. empty-cells:show should address exactly this problem, but unfortunately it only works properly in IE starting with version 8 (and then only in standards-compliant mode). It can be made to work in other versions by also specifying border-collapse: collapse, but sometimes this is what is NOT desired. In my case I have a fairly complex table and it relies on border-collapse:separate and would otherwise create quite a messy CSS/HTML soup.
So what are other things that you might put in a table cell that would make IE draw the borders yet not be visible or copyable? For all other browsers the empty-cells:show already does the trick, so I really just need to fool IE.

You can also put invisible br element:
<td><br style="visibility:hidden"></td>
It is ridiculous amount of unnecessary code, but it makes the trick - no additional text added yet cell is displayed.
Note that <br/> is invalid HTML syntax according to the official specifications http://www.w3.org/TR/html401/struct/text.html#edef-BR. It is valid XHTML syntax however.

You can show the cells with this CSS code. I successfully tested it in Safari and Firefox. I guess it works in other browsers as well.
table {
width: 100%;
border: 0;
empty-cells: show;
}
td {
border: 1px solid grey;
}
td:empty:after {
content: '.';
color: transparent;
visibility: hidden;
}
/* alternate background */
tr:nth-child(odd) td {
background: rgba(0, 0, 0, 0.2);
}
tr:nth-child(even) td {
background: rgba(0, 0, 0, 0.1);
}
<table>
<tr>
<td>Row</td>
<td>1</td>
</tr>
<tr>
<td></td>
<td></td>
</tr>
<tr>
<td>Row</td>
<td>3</td>
</tr>
</table>

Related

How to accessibly hide table caption element?

Is there any way to accessibly hide a table caption without breaking how screen readers interpret the rest of the table? Hiding a <caption> with typically recommended styles for hiding an element visually breaks the behavior of VoiceOver, causing it to skip the last row in the table when reading through linearly using the "next" keystroke. (It is possible to force VoiceOver into the last row by explicitly navigating down a column, but that requires the user to know to do this.)
I recognize this may be a bug in VoiceOver itself, but if there's a clean workaround, that would be ideal since WCAG requires accessibility with actually available assistive technology.
Here's a minimalist example to demonstrate:
Update: The style rules below are the standard rules used in the Magento framework to visually hide elements while leaving them accessible to screen readers. The key rule causing the VoiceOver behavior is the position: absolute; however, if this is simply removed, the layout flow is impacted.
caption {
border: 0;
clip: rect(0, 0, 0, 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
<table>
<caption>Table of Fruits</caption>
<thead>
<tr>
<th>Fruit</th>
<th>Color</th>
</tr>
</thead>
<tbody>
<tr>
<td>Apple</td>
<td>Red</td>
</tr>
<tr>
<td>Pear</td>
<td>Green</td>
</tr>
</tbody>
</table>
<p>Voiceover will jump straight from "Red" in prior table to this paragraph, skipping the last row.</p>
Well... I see that you are using a caption tag just for accessibility, which means that you don't want to show it visually; I suggest simply not using it and instead use aria-label in your table tag, which will make it accessible for screen readers.
<table aria-label="Table of fruits"> ... </table>
Read the first paragraph of this page to get an idea about aria-label usage.
A Few Discrepancies
<th> Needs <tr> as a Parent to be Valid
The OP (Original Post) code didn't have a <tr> in the <thead> which could be the reason why the last <tr> is being skipped. Invalid HTML has a tendency to confuse applications such as VoiceOver.
Three Methods
Disclaimer: Not Tested - Caveat Emptor
The following demo has three <table>s with identical HTML markup, CSS rules, and text content. Each <caption> has a different .class that employ a specific method of hiding content:
.clipped - Assuming that clipping content needs a length: clip: rect(0, 0, 0, 0); looks dubious. Some other properties and values looked to be ad-hoc as well so try replacing caption {...} rule set with:
.clipped {
position: absolute !important;
height: 1px;
width: 1px;
overflow: hidden;
clip: rect(1px, 1px, 1px, 1px);
}
.transparent - This is simply assigning a transparent color to text. Height is still there (which VoiceOver requires), but it can be adjusted if needed. opacity: 0 is also an option, but there are certain situations in which opacity: 0 is considered the same as visibility: hidden (which VoiceOver ignores).
.transparent {
color: rgba(0, 0, 0, 0);
}
.collapsed - This collapses an element's content but retains its height so VoiceOver might recognize it.
.collapsed {
visibility: collapse;
}
Demo
table {
border: 1px solid #000;
table-layout: fixed;
border-collapse: collapse;
min-width: 200px;
}
th,
td {
width: 50%;
border: 1px solid #000;
}
.clipped {
position: absolute !important;
height: 1px;
width: 1px;
overflow: hidden;
clip: rect(1px, 1px, 1px, 1px);
}
.transparent {
color: rgba(0, 0, 0, 0);
}
.collapsed {
visibility: collapse;
}
<table>
<caption class='clipped'>CAPTION</caption>
<thead><tr><th>TH</th><th>TH</th></tr></thead>
<tbody><tr><td>TD</td><td>TD</td></tr>
<tr><td>TD</td><td>TD</td></tr></tbody>
</table>
<table>
<caption class='transparent'>CAPTION</caption>
<thead><tr><th>TH</th><th>TH</th></tr></thead>
<tbody><tr><td>TD</td><td>TD</td></tr>
<tr><td>TD</td><td>TD</td></tr></tbody>
</table>
<table>
<caption class='collapsed'>CAPTION</caption>
<thead><tr><th>TH</th><th>TH</th></tr></thead>
<tbody><tr><td>TD</td><td>TD</td></tr>
<tr><td>TD</td><td>TD</td></tr></tbody>
</table>
<p>The <abbr title="Original Post"><b>OP</b></abbr> code didn't have a <code><tr></code> in the <code><thead></code> which could be the reason why the last <code><tr></code> is being skipped.</p>
You do not want to hide <caption> visually.
A bit late to the party but I feel an urge to highlight the importance of avoiding to treat disabled users differently. That simply means to prefer solutions that generally work for all users out-of-the-box. Try not reinvent the wheel or over-complicating with screen-reader-only solutions, just leave it as it is and provide the same content to all users. In this specific case I'd either make caption visible for all, or for no one. Why not to show caption to all users? If the table content is so complex that it needs to be described to a screen reader then you might ask yourself whether it's time to optimize the actual content for all users, or describing it to all users, not only screen readers. Because when you make something accessible for a screen-reader-only then likely you made it inaccessible for many other users. Hence you didn't make it accessible.
The worst here is the assumption that only screen-reader users will require some solution. But there are no screen-reader users. Such assumptions about the users should never be made. Accessibility is not screen-readers. There are so many other disabilities, use-cases and assistive technology. Many screen reader users want to share the content and if they "see" (or hear) something that their friend cannot access, it will look weird. Bear in mind also that many screen reader users are not blind. They might be using zooming and will also find confusing the fact that screen reader is reading the content which appears not to exist on the page.
Yes, there are always some exceptions, such would be "skip links" and similar, but all such practices are common and something users are familiar to. Those are usually well thought through for all user groups. Hence "skip links" would become visible when focused etc.
Since position: absolute; is what causes the problem, a pragmatic solution is to skip it and use margin-top: -1px; instead. Tested and verified i Chrome + voiceover.
.clipped {
position: absolute !important;
height: 1px;
width: 1px;
overflow: hidden;
clip: rect(1px, 1px, 1px, 1px);
}
I'm a little late to this discussion, but there is a solution that hasn't been mentioned yet.
You can use the summary attribute on the table element. The summary attribute will not affect your layout, but will be read by the screen reader.
If you use the caption element or aria-label attribute, they will override the summary attribute. So just use summary by itself.
<table summary="Table of Fruits">

A table's <tr> cannot have border, it seems, for IE 7, but I don't see in books that talks about <tr> border either?

This one will show border for Chrome, FF, IE 8 and 9, but it won't show a border for IE 7.
http://jsfiddle.net/y7HWr/10/
(which is to have a border for <tr>). So I think probably IE 7 is at fault? Even though I don't see books talking about borders for <tr> elements (they talk about for <tr> elements usually), but really it should apply to most any elements? (maybe except elements that doesn't make sense to have borders, such as <meta> or <script> or <style>... otherwise most other elements should be able to have a border?
Instead of marking each <td> to be the class .end-of-category, I change it this way so that it works with IE 7... any alternatives or other ideas?
tr.end-of-category td { border: 6px solid #000 }
table { border-collapse: collapse }
table .end-of-category td { border-bottom: 6px solid #000 }
The above should work, or at least achieve the same if you've only got one border involved - I think it's how the different browser handle border-collapsing, but then again maybe it's just IE
Update: yes, it's IE7
using the separate border model (default) means no-one renders the border on the tr
table { }
table .end-of-category { border-bottom: 6px solid #000 }
So it seems like, IE7 had a difference of opinion again LOL!
Using the collapsed table borders it would be very unlikely an effect couldn't be achieved using the TD borders instead, but still!
.end-of-category td { border: 6px solid #000 }
Works in IE7 and IE6.

row border color

I want to set the border of <tr> to yellow. I can set the border of <td> but can't figure how to set border of row <tr>.
How to do this?
Thanks.
This example is working fine on IE8, Chrome 9 and Firefox 3.6 so I really can't see what is the problem.
HTML used in the example:
<table>
<tr>
<td>AAA</td>
<td class="middle">BBB</td>
<td>CCC</td>
</tr>
</table>
CSS:
.middle { border: 2px solid blue; }
tr { border: 2px solid red; }
Result:
No can do, ime, even though css spec ( http://www.w3.org/TR/CSS2/box.html#border-properties ) plainly says border and border-color can be applied to "all elements". Though it might be because <table> might not fall under the box model; I'm not sure about this.
In any case, it's a counter-intuitive, crazy-seeming, page-bloat-inducing pita.
There must be better solutions than bordering every single table cell, which is what I end up doing.
-- pete
It does work, and by the spec.
The problem is that the borders collapse, and you did not expect that.
And by the spec the border for td tends to dominate over the border for tr:
http://www.w3.org/TR/CSS2/tables.html#border-conflict-resolution
Write a CSS rule for the tr element? Something like tr {border: ...} Have you tried this and it's not working? Validate your HTML code first with the W3C markup validator and solve the errors if there are any indicated.
I did it without css.
<TR BORDERCOLOR="RED" BGCOLOR ="PINK">output
works in IE but not firefox,chrome or even edge.

How can I make "display: block" work on a <td> in IE?

Is there anything I can do to make IE display table cells as actual blocks?
Given this style:
table,tbody,tr,td,div {
display: block;
border: 1px solid #0f0;
padding: 4px;
}
And this html:
<table>
<tbody>
<tr>
<td>R1C1</td>
<td>R1C2</td>
<td>R1C3</td>
</tr>
</tbody>
</table>
<div>
<div>
<div>
<div>R1C1</div>
<div>R1C2</div>
<div>R1C3</div>
</div>
</div>
</div>
The table renders exactly the same as the nested divs in both Firefox and Safari/Chrome. But in Internet Explorer (8) the property display: block has no effect. The table renders exactly as if I don't set that property.
My main problem is that the cells don't break; They all render on one line. (The tbody and tr elements don't get any borders nor padding. That is not a problem for me right now, though.)
I haven't found any information on the problem when searching. Compatibility charts on quirksmode and elsewhere states that IE supports display: block since v. 5.5. Any discussion on table display problems seems to be when doing the reverse - giving non-table elements any of the display: table-* properties.
So once again, is there anything I can do to make IE render table cells as block?
(The real table is really a table, with tabular data. I would like to keep it that way, and restyle it unobtrusively.)
I applied float: left to stuff. It kinda works.
Live Demo
The biggest problem is width: 100% combined with the padding is making things too wide.
So:
Live Demo (without the problematic padding)
That looks a bit better, but I'm not sure how you can easily add padding everywhere if you need it.
This fails --> miserably <-- in IE7 (it just won't get over the fact that it's a <table>), and even if you don't care about IE7, it will need tweaking for your use case (if it's usable at all).
IE7:
The following worked for me for IE6+:
tr {
display: block;
position: relative
}
td.col1 {
display: block;
left: 0;
top: 0;
height: 90px;
}
td.col2 {
display: block;
position: absolute;
left: 0;
top: 30px;
}
td.col3 {
display: block;
position: absolute;
left: 0;
top: 60px;
}
Assumptions:
cell height 30px
Drawbacks:
Fixed cell height
Cumbersome specification of top property (maybe generate)
Only works when HTML provides classes for columns
Advantage:
Works in all browsers.
When to use:
When you have no control over HTML, but have control over CSS. Some hosted payment solutions come to mind that display in an IFRAME and offer a custom style sheet.
Just figured it out with a collegue of mine.
ALTHOUGH I STRONGLY RECOMMEND TO NOT SUPPORT IE8 AT ALL ANYMORE!
Since you are facilitating the use of an unsupported and currently unsafe product that is not up to par with current standards and techniques. It would be way better to tell your users to upgrade and give them some browser downloadlinks to choose from.
That being said. The CSS below is the minimum css you need to fix it in Internet Explorer 8.
table {
width: 100%;
}
td {
float: left;
width: 100%;
}
<table>
<tbody>
<tr>
<td>cell-1</td>
<td>cell-2</td>
</tr>
</tbody>
</table>
add this code:
<!DOCTYPE html>
我这里是这么解决的,加上上面那条声明语句,display:block对td就会有效。
you need add this code in the top.
<!DOCTYPE html>
<html>
<head>
<style>
td {
display: block;
}
</style>
</head>
<body>
<table>
<thead>
<tr>
<td>First Name</td>
<td>Last Name</td>
<td>Job Title</td>
</tr>
</thead>
<tbody>
<tr>
<td><div>James</div></td>
<td><div>Matman</div></td>
<td><div>Chief Sandwich Eater</div></td>
</tr>
<tr>
<td><div>The</div></td>
<td><div>Tick</div></td>
<td><div>Crimefighter Sorta</div></td>
</tr>
</tbody>
</table>
</body>
</html>
Add this line of code in the top, but use 'float' and 'width' is very good.
sorry, my english so poor.
make it display:table-row; instead of display:block
It will work like it is supposed to

Hide border on table where no cell exists in Firefox and border-collapse: collapse;

Given the following HTML page a horizontal line appears at the top of the table where the 1st row would have a 2nd and 3rd cell (if they were defined).
<html>
<head>
<Title>Test Page</Title>
<style type="text/css">
table {
margin:10px 0 10px 0;
padding:0;
margin: 0 0 0 0;
border-collapse: collapse;
border: 0;
}
td {
border:1px solid #CCCCCC;
padding:5px;
}
</style>
</head>
<body>
<table>
<tr>
<td>Test Title</td>
</tr>
<tr>
<td>Sub Title</td>
<td>Sub Title</td>
<td>Sub Title</td>
</tr>
<table>
</body>
</html>
I would like the line (highlighted below) removed by modifying CSS only. This line appears in Firefox but not IE6.
Note that I cannot modify the HTML in any way as this is generated by a third party system (the example above is simply to highlight the issue). This third-party system only allows me to modify the CSS.
This will get it to render without the top border in Firefox:
table, td {
border: 1px #CCC;
}
table {
margin: 0;
border-spacing: 0;
border-style: none none solid solid;
}
* html table {
border-collapse: collapse;
}
td {
border-style: solid solid none none;
padding: 5px;
}
It also works fine in IE7 for me. If it breaks in IE6, use conditional comments or css hacks to revert it to the state it was in your own code for IE6 only.
EDIT: Your third party tool is generating bad/invalid markup which will give you a very large browser compatibility/css headache, if it is at all feasible, replace it or generate the html yourself
Technically speaking the first row should be marked up as
<tr>
<td colspan="3">Test Title</td>
</tr>
So I don't think you can acheive that using tables.
A css tip
margin: 10px 0;
Puts 10px at the top and bottom and 0 on the left and right
The empty-cells property may help you in this case.
table {
empty-cells:hide;
}
Then again, maybe not. Can you also explicitly turn off the border of the table rows?
Is using javascript an option? You could inject a non breaking space into the cell, that should draw the border.
Here is the solution for this problem that really works. I found this out after sooo long
The problem is with tbody tag.
Check the solution here:
http://www.dashplanet.com/firefox-displaying-border-top-of-table-how-to-hide-that-1px-top-border-table
From Firefox Colspan Border-COllapse Bug:
The obvious workaround is to just set
the colspan before the DOM has
finished loading, or at minimum,
before the table has finished
rendering. However, this requires that
we clutter our otherwise clean HTML
with inline tags, or have
prior knowledge of the number of
columns at the HTML generation stage.
I hope to find a more elegant
"non-invasive JavaScript" solution in
the future, but at the current time I
don't know of one. Simply setting the
table's "display" style to "none" and
then re-setting it back to "block" did
not do the trick.