Dynamically showing and hiding table rows

This is really just a reminder for myself. When using the DOM to dynamically hide and show table elements (like a table row), you can't use display = "block" to bring a table row back to life in Firefox; although, it works okay in IE. It's best to simply use display = "" so that Firefox correctly resets it to table-row and IE can still do what it does.

I imagine other browsers behave similarly to Firefox.

Published February 28, 2005 · Updated September 17, 2005
Categorized as HTML and CSS
Short URL: https://snook.ca/s/343

Conversation

55 Comments · RSS feed
Garrett said on March 08, 2005

In my upcoming update for YTS, I've got a script that dynamically shows/hides rows based on whether JavaScript is enabled.

And this problem drove me absolute nuts when I was building it. Where was this post 2 months ago?

Good call though.

Evan said on March 15, 2005

This drove me nuts as well. I was trying to dynamicly hide/display <tr>s dependant on what options the user chose. I ended up adding the following block to my javaScript function:

if(navigator.appName.indexOf("Microsoft") > -1){
var canSee = 'block'
} else {
var canSee = 'table-row';
}

Then I can use the variable 'canSee' instead of 'block' to show hidden <tr>s. <td>s can be hidden by replacing 'table-row' with 'table-cell'.

Tony Weeg said on March 21, 2005

man, thank you for the tip on hiding/showing tr's in firefox, to mimic IE's laziness :)

it worked perfect!
tony

Evan said on March 31, 2005

Another cool use of this I found is with <tbody> tags. Use 'table-row-group' instead of 'table-row' & you can hide/show multiple rows at a time without creating a million document.getElementById() calls.

Tony Weeg said on March 31, 2005

thank you evan... ill have to try!

Ryder said on April 01, 2005

Thank you very much!

ani said on June 10, 2005

How about making it compatable with Netscape? Any solutions for that? I am using the display="" and still does not work.

Evan said on June 10, 2005

the solution posted on 03/15 will work on for Micorsoft Based (Internet Explorer) or Gecko Based Browsers (Netscape, Mozilla, Firefox...).

As far as rendering the element 'invisible', all you have to do is set the display="none". Hopefully this should help.

Pisu said on September 26, 2005

Great, i think you, I found this article with Google and it solved my problem with Firefox compatibility!

Hillel said on November 24, 2005

Man... It's 7AM and I've been banging my head against this for the past 4 hours. I just came across ths article now.

Deceptive little problem cause you don't immediately notice that the working snippets on other peoples' sites are showing/hiding entire tables and not table elements.

I was trying to enclose a row in DIV tags, then hide/show that... but even with Evan's snippet, that didn't work. Finally assigned an ID to the row tag, added the snippet, and got firefox to roll over.

So thanks Evan.... just wish I found this sooner. I'm going to sleep.

Skillsy said on December 11, 2005

Well done Evan et al,
A hard problem to google but its probably down to testing in IE and hoping the rest of the browsers are as lask as IE in renedering cr&p HTML/CSS.
You have saved me hours - once again well done!

Skillsy

said on January 04, 2006

xvvxcvcvxcv

EyePulp said on January 04, 2006

Thanks for the helpful note. Sorry about the junk comment above, I was admiring your comment form. =)

ManiaC said on March 17, 2006

great solution - i have been looking for this for months now

Nitin said on March 27, 2006

Oops :( The solution isn't working for me. I have exactly the same problem i.e. to hide a row or set of rows in a table. I know I am making some mistake but still...

Here is the sample html:

<div id="d">
  <tr>
     <td>Name</td>
     <td>Id</td>
  </tr>
  <tr>
     <td>Nitin</td>
     <td>1234</td>
  </tr>
</div>

Here is the Javascipt method I used after reading your post:

function toggleLayer(whichLayer, iState) {
  if (document.getElementById) {
    // this is the way the standards work
    var style2 = document.getElementById(whichLayer).style
    //style2.display = iState ? "block" : ""
    style2.display = iState ? "table-row" : ""
  }
}

Javascript call to the method is:

toggleLayer('d', 1)
OR
toggleLayer('d', 0)

Please tell me what's wrong am I doing. I have already spent hours to find out what you are saying.
I am currently using a bad solution of making separate table with div around it for each row.

Hillel said on March 30, 2006

I was making the same mistake at first. You need to just stop using DIV's for this. Include an ID attribute inside the TR tags, and go from there. For instance:

>table>
> tr id="toggleRow1">
> &nbsp td> content to show/hide &nbsp /td>
> &nbsp td> content to show/hide &nbsp /td>
>/tr>
> tr id="toggleRow2">
> &nbsp td> content to show/hide &nbsp /td>
>/tr>
>/table>

Only downside is that for you, you now have to show/hide each row individually. They're not grouped by the DIV tags anymore, each row needing its own unique ID. A minor inconvenience though.

Evan said on March 30, 2006

Hillel hit it on the head... to to hide multiple groups, <tbody> tags & substitute 'table-row-group' for 'table-row'

- E

Hasse said on April 20, 2006

Thanks Evan! You're a genius!

baseline said on May 11, 2006

good fix thanks

said on June 07, 2006

Just wanted to reply to this and with the function that I came up with to hide a table row. I have tested in IE 6 and Firefox 1.5

I had to use this code to hide/show rows in Firefox:
style2.display = iState ? '' : 'none'

And This to hide/show in IE:
style2.display = iState ? 'block' : 'none'

iState is set to 0 to hide and 1 to show.

Tabraiz said on June 08, 2006

hi,
I have been rolling now for 2 days in this show/hide kinda stuff. From DIV to iFrame to tBody (learnt right here ;) ) I have given every thing a try. Now this is what I have come up with, this objective is same: Show/Hide table rows.. working perfectly fine on IE, but in Firefox the table formatting is ruining and a bit of space is shown between rows that I really don't want. Here is the example page.

http://ramadan-blessings.com/tab/tr_mania.htm

Any ideas or solution for fixing it... please guide .. thanks
note: I am now using tbody to group rows.
-----------------------------------------------

function showTR(id){
if (document.getElementById && document.createTextNode)
{
var tr=document.getElementById(id);
if (tr) {
if (tr.style.display == 'none') {
// we set style to block for IE
// but for firefox we use table-row
try {
tr.style.display='table-row';
} catch(e) {
tr.style.display = 'block';
}
}
else {
tr.style.display = 'none';
}
}
}
}

----------------------------------------

Evan said on June 09, 2006

The root of your problem lies in the use of a Try/Catch. the code you're using won't throw any errors, hence the misrenderings. instead, use the browser detector below:

if(navigator.appName.indexOf("Microsoft") > -1){
var canSee = 'block'
} else {
var canSee = 'table-row';
}

This will determin whether if the end user is using IE or something else (Opera, Firefox, Safari ... ). & then use the approprate code.

Hope this helps.

- Evan

said on June 14, 2006

I can't hide multiple rows in IE.

Ernest said on July 06, 2006

That worked really well. Found it pretty quickly in google too.

Thanks for the fix.

chris said on July 16, 2006

Hiding a row can throw off formatting in FF if rowspan is used in the table.

As in:

<html>
<head>

<style>
.show {}
.hide {display:none}
</style>

<script>
function on(i) { document.getElementById(i).className="show"; }
function off(i){ document.getElementById(i).className="hide"; }
</script>

</head>

<body>
hover the mouse on the table and see the 1st row's test2 box (dis)appear.<br />
In ff, the table will grow forever with each mouse on/out cycle.<br />
<table border=1>

<tr onmouseover='on("more1")' onmouseout='off("more1")'>
<td rowspan=2>left</td>
<td>top right</td>
</tr>
<tr id=more1 class=hide><td>bottom right</td></tr>
<tr class="this extra TR is not required in IE to keep the formatting right"><td></td></tr>

<tr>
<td rowspan=2>left</td>
<td>top right</td>
</tr>
<tr><td>bottom right</td></tr>

</table>
</body>

Any idea how to best counteract this?
Cheers, Chris

chris said on July 17, 2006

sorry about the error, my previous example should use
.show {display:block}

in any case, as mentioned in the page's intro, the problem is corrected when using
.show {display:}

but i still wonder if this is normal behaviour.

Also, pls note the extra TR which is only req'd for FF, not IE, to keep formatting ok when the other TR is hidden.

Darren Line said on July 21, 2006

I've been struggling with this little problem for a while now, maybe somebody here can help...

I am using a recordset to display a set of tables. I am dynamically setting the id of these values to 0, 1 and 2.

I am after an IE solution to show/hide all tables that meet a certain criteria that the use selects from a radial button.

Using the getElementById I can make it show/hide the first table ID that meets the criteria. But I am trying to do it for ALL the tables that have that ID.

I know getElementById will only do it on the first element, so how do I do it for them all?

Evan said on July 21, 2006

I'll assume that the tables reside within a <form> field. Name the tables in each grouping with the same name and then call the elements by their name (ie: formName.tableName). Hopefully, this'll resove your issue.

- Evan

Evan said on July 21, 2006

Whoa!!! I mispoke on the last posting... (Must drink my coffee before answering my email). Use "document.getElementsByName(tableName)" in lue of formName.tableName. sorry about that.

- Evan

said on July 21, 2006

The code I am using is something like this...

function toggleDn(DnRecNo){
if (DnRecNo==0) {
document.form1.tbl_2.style.display = 'none';
document.form1.tbl_0.style.display = 'inline';
}
}

but I am getting is "document.form1.tbl_2.style' is null or not an object.

The table generation is produced by a recordset loop, therefore I will have multiple ID's set to tbl_0 or tbl_2

said on July 21, 2006

That was pretty much what I was using before.

When you say the tableName, do you mean the ID? If so, that is pretty much what I have been doing (except not in a form).

This is my test page...
http://sdsl.ganedatascan.com/test.asp

Evan said on July 21, 2006

Not the ID, the NAME of the element (<Table cellpadding="0"cellspacing="0" border="0" NAME="tableName">). Multiple elements can use the same name. By using the document.getElementsByName(tableName) function, you can call as many elements as you want, as long as they have the same name & change the display value of it, or what ever else you'd like to alter via the DOM.

- Evan

Sourabh said on August 08, 2006

Evan, awesome tip on using <tbody> to hide show multiple rows.
-Sourabh

Valerie said on September 01, 2006

Thank you - I was having a hard time getting firefox to display correctly - saved the day!

Happy Programmer! said on September 06, 2006

Thanks heaps for the advice on table-row. I was trying to figure out why firefox was being stupid. You've saved me a lot of hair pulling and wasted time.. Thanks!

ItsMeAgain said on December 05, 2006

Hi Hillel,
This is a great link....I was also struggling the same way..........now its JUST NEAT!!!. Thank you man and all the people who have put postings in this forum....

rl said on February 27, 2007

How can you do a similar thing using CSS only? I am applying styles based on a class on the tr. In this case I want to hide all rows except those that are in error:

div.fullerror tbody tr td
{
	display: none;
}

What do I put into this rule to override the display: none? I can't put "", and display doesn't take auto, normal, or default. Can I just put display: ; ?

div.fullerror tbody tr.error td
{
/*display: auto;
display: normal;
display: default;
*/
}
</ore>

rl said on February 27, 2007

I achieved the same thing through IE's conditional comment so that IE gets specific styles that no other browser needs.

	<!-- Conditional Comment for Internet Explorerer.  Any IE-specific css will go into this stylesheet -->
	<!--[if lt IE 7.0]>
	<style type="text/css">
		@import "Styles/IE.css";
	</style>
	<![endif]-->

And then my default.css that sets the tr to table-row:

div.fullerror tbody tr
{
	display: none;
}

/* See IE.css - IE requires display: block instead of display: table-row */
div.fullerror tbody tr.error
{
	display: table-row;
}

And the IE-specific IE.css that sets it to block instead of table-row:

/* See default.css - all other browsers need this to be display: table-row */
div.fullerror tbody tr.error
{
	display: block;
}

After this change it works in IE6, Opera 9, and FireFox2.

Hillel said on March 03, 2007

Hi again, it's been a while. I'm wondering if you have any ideas for how to show/hide a row without using the ID attribute. As you probably know, IE has some kind of issue with returning strange results from a getElementByID(), which I've been avoiding by using getElementsByName()[0] instead wherever possible. However table rows don't have a 'name' attribute (at least as far as I know), so that workaround is no good for toggling row visibility. I was praying I would never have to worry about this, but I just came across it: IE returns 'error: object expected' for getElementByID(myrow). Any ideas? And thanks again.

matthew setter said on March 13, 2007

just wanted to say that i was having an issue with IE working fine showing/hiding a few div's but firefox (2.0) would break the layout when showing again, then increasingly add blank space whenever the show/hide fired again.

The display = "" works just great.

ernest leitch said on March 18, 2007

This is a nice tip. That saved me quite a bit of time

Sachin Patke said on March 28, 2007

Evan/Hillel/Sourabh,
Since you have already worked on it, Can either of you please put the function and the corresponding table in code to show as an example. I am using a table within div tag that I need to hide/show, its the div tag I am hiding/showing, and it works for IE, of course, but not in firefox. Code sample would greatly help. Sincere thanks.

Kirack said on March 29, 2007

WOW!!!! saved my precious hair on my almost bald pate.
Thanks

Kevin Jensen said on April 24, 2007

Thank-You! Couldn't figure out why it wasn't working.!

web technologiest said on April 27, 2007

wonderful fix , its so insane to see that we all as consumers of technology need to keep fixing bugs with these so called big shot companies who think they have invented the next big thing.....

hedKase said on May 17, 2007

Stumbled on this article today, and wow, what a big help. I was trying for about an hour to use a DIV to hide a table row but it was just frustrating me.

I built a function that may be of some help to you. It works with both TR and table groupings (TBODY). If no second argument is passed to it it simply tries to reverse it's current state (so if it's hidden it will show it, if it's visible it will hide it). If the second argument is specified as TRUE it will show it, if it's specified as FALSE it will hide it. Pretty straight-forward, seems to work in both Internet Explorer and Firefox well.

<textarea cols="60" rows="8">function ToggleTableRow ( id ) { var obj = document.getElementById(id); var state = (arguments.length >= 2 && typeof(arguments[1]) == "boolean" ? arguments[1] : (obj.style.display.length && obj.style.display.toLowerCase() != "none" ? false : true)); if (obj) obj.style.display = (state ? (navigator.appName.indexOf("Microsoft") >= 0 ? "block" : (obj.nodeName && obj.nodeName.toLowerCase() == "tbody" ? "table-row-group" : "table-row")) : "none"); }</textarea>

Someguy51 said on May 29, 2007

This worked for me. When you hide the table row, the table shrinks and when you show the row the table grows. I successfully tested it in both FireFox 2 and IE 7.

Here's my JavaScript:


  function hideShowHTMLItem(itemID, iState) {
    htmlItem = document.getElementById(itemID);
    if (htmlItem) {
      if (iState == 0) {  // hide
        htmlItem.style.display = 'none';
      } else {  // show
        htmlItem.style.display = '';
      }
    }
  }

Here's some html to test it with:

<table>
<tr id="testrow">
<td>my caption</td>
<td><input id="testinput"></td>
</tr>
<tr>
<td align="center" colspan="2">
<button type="button" onClick="hideShowHTMLItem('testrow', 0);">Hide</button>
<button type="button" onClick="hideShowHTMLItem('testrow', 1);">Show</button>
</td>
</tr>
</table>

WildRabbit said on June 26, 2007

You can of course implement this into "adding" rows to a table. Say for if you would like to add upload fields etc. or just extra information fields this can be easily done with just making a big table with all the information extras, maybe 20-30 fields that are hidden and add a javascript link/button that executes a snippet of code that changes the class of the rows that are hidden.

var currentFieldNumber = 2
function addOneField()
{
document.getElementById('rowField' + currentFieldNumber).className="show";
document.getElementById('linkAdder' + (currentFieldNumber-1)).className="hide";
noAddressFields++;
if (currentFieldNumber == N)
{
document.getElementById('linkAdderN').className="hide";
}
}

+
for instance...

great help though, thanks alot

Frosty said on July 10, 2007

@ Post 37 from Someguy51

----------------

Awesome post, but is there a way to apply this to multiple table rows with a single click?

Frosty said on July 11, 2007

Okay, never mind, I found a way to do it just by using <tbody> tags around the rows and referencing the tbody id.

Thanks for the help.

Mike said on August 01, 2007

Thanks, this thread solved the getting Firefox and IE table rows to disappear and appear correctly. Something I'd spent lots of time on my own not solving.

Garry said on August 10, 2007

Go to this url for a cool solution

http://www.clearwaterclinical.com/cwc/example_code/dynamic_tables.html

MikeP said on August 29, 2007

I'm having a problem with IE 6/7 that when I show/hide rows that have the rowspan attribute. When I show the rows, then the header columns' widths lose their widths and seem to double in width. When I hide the rows, they go back to the correct widths. Anybody have any clue about this issue?

Phil said on September 20, 2007

Genius!

Thanks again!

Phil

Nitin said on March 08, 2011

I am having problem making a tablerow visible using Javascript. The Javascript code that i am using is something like this:-

<script language="javascript" type="text/javascript">
if(navigator.appName.indexOf("Microsoft") > -1){
var canSee = 'block'
} else {
var canSee = 'table-row';
}
</script>

In the TableData i am adding the following attribute:-

onclick="toggle(this);"

It's not working..what could be the reason?

Sorry, comments are closed for this post. If you have any further questions or comments, feel free to send them to me directly.

Want to learn about scaling CSS for large projects?

I'm available for full and half-day workshops on scalable CSS architecture. I can provide on-site training for your team. Interested?
Get in touch.