tags:

views:

229

answers:

9

Here is the relevant code (doesn't work):

<html>
<head>
<title>testing td checkboxes</title>
<style type="text/css">
td { border: 1px solid #000; }
label { border: 1px solid #f00; width: 100%; height: 100% }
</style>
</head>
<body>
<table>
<tr><td>Some column title</td><td>Another column title</td></tr>
<tr><td>Value 1<br>(a bit more info)</td><td><label><input type="checkbox" /> &nbsp;</label></td></tr>
<tr><td>Value 2</td><td><input type="checkbox" /></td></tr>
</table>
</body>
</html>

The reason is that I want a click anywhere in the table cell to check/uncheck the checkbox.

edits: By the way, no javascript solutions please, for accessibility reasons. I tried using display: block; but that only works for the width, not for the height

+6  A: 

Labels are inline elements by default, so setting the width and height does nothing.

label { display: block; }

Would do it.

(However, the practice of putting the label around the checkbox it is supposed to be associated with, rather than explicitly using for, doesn't work in IE.)

bobince
display: block works for width, but not for height. But thanks a lot for that IE warning! I guess I can wrap the input element in a label AND put a for attribute in there, right?
Shawn
Yes, you can. Actually having just checked it, this is fixed in IE7; it's only IE6 that would suffer. You can set `height` on a block, but if you set a percentage height, the parent element (to which the percentage is relative) must have a `height` specified itself.
bobince
Well, in this case, the parent element has no height specified.. So what do I do?
Shawn
You would have to specify a height. It doesn't really make any sense to have auto height on the parent but %-height on the child, which is why CSS 2.1 disallows it: it makes the height of the parent depend on the height of the child depend on the height of the parent depend on the height of the child depend on the [STACK OVERFLOW]
bobince
Well, the height of the TD depends on its content. Is there no way for CSS to say: "Once we've determined the dimensions of the TD element, make the label element 100% of the TDs width and height"?
Shawn
No, because the height of the `<td>`'s content area is the height of the `<label>`. Without knowing the height of the static flow content in the cell, you can't know the `auto` height of the cell.
bobince
If I understand what you're saying, the height of the td is determined once all the heights of all the elements in all the tds of that row are calculated. Therefore, if I want the label's size calculated after the td's size, I need to make that calculation once the page is shown, aka use javascript. Or in other words, what I am trying to do is impossible without javascript. Is that right?
Shawn
@bobince: Wrapping a label around a form element does work in IE. It makes the elment accessible to people with motor disabilities. But you still need to have a "label for" around the associated text in order to make it accessible to people with screen readers.
Gert G
@Shawn I think it would look nice visually to have all the tds the same height or at least the clickable area around them the same size by setting the height on the label. You could also add a hover (probably using JS to make it work everywhere) so people can tell they can click any where. Personally, I at least like to add: label { cursor:pointer; }
Darryl Hein
@Darryl Hein: I would rather have the table cell containing the checkbox to act as a label for it.. If I set all the labels to the same size, I have to choose a size that's big enough for the biggest possibility, thus stretching all the smaller ones to that size unnecessarily and making the table larger than it already is (very large already). I do like the cursor: pointer idea very much though. Just added it in :) Thanks
Shawn
A: 

I want a click anywhere in the table cell

<tr onclick="alert('process click here');"> ... </tr>
balexandre
I should have added: "without javascript for accessibility reasons" but thanks anyways :)
Shawn
so, why not playing with tr:hover ??
balexandre
@balexandre: Interesting, but can CSS check and uncheck checkboxes?tr:hover { check/uncheck checkbox }
Shawn
Actually, could you explain what you meant by "playing with tr:hover" ?
Shawn
A: 

HTML:

<tr>
  <td>Value 1<br>(a bit more info)</td>
  <td><label><input type="checkbox" /> &nbsp;</label>
  </td>
</tr>

Javascript/JQuery:

$(document).ready(function(){
   $('td input[type=checkbox]').parent().click(function(){
      //handle click event here
   });
});

pardon any syntax errors if any...

Alexander
Sorry, I should have stated that I was looking for a css-only solution, if possible (for accessibility reasons). Thanks anyways!
Shawn
A: 

Try this CSS for your label

label  {
 border:1px solid #FF0000;
 display:block;
 height:35px;
}

Here is the live Demo http://jsbin.com/ehoke3/2/

Pablo
What if that cell in the middle of the left column had another line of text? Or what if I later decide to change text size? This solution isn't ideal as I can't always know the precise height of the cells.
Shawn
You have two options you either use inline styles OR you should really use JavaScript - I mean why not?
Pablo
I really don't see how inline style will help me. I still can't determine the exact pixel-precise size of the TD at the time I write the code, plus it might change over time. And for javascript, if all else fails I don't mind, but I still feel I should give it a try for those who don't have it (for various reasons)
Shawn
ok, unfortunately things don't work as we want or expect then to. Good Luck
Pablo
A: 

In your row with "Value 1" you don't just have "a bit more info" you also include a break. It seems to me that all you really need to do is include a <br> in any label in the right column for when the content in the left column includes a <br>. Also, obviously <label> needs to have a display CSS attribute set to block.

<html>
<head>
<title>testing td checkboxes</title>
<style type="text/css">
td { border: 1px solid #000; }
label { border: 1px solid #f00; display: block;}
</style>
</head>
<body>
<table>
<tr><td>Some column title</td><td>Another column title</td></tr>
<tr><td>Value 1<br>(a bit more info)</td><td><label><input type="checkbox" /> &nbsp;<br>&nbsp;</label></td></tr>
<tr><td>Value 2</td><td><label><input type="checkbox" /></label></td></tr>
</table>
</body>
</html>

One note: you're not going to get perfect workalike performance in all the major browsers from the last 10 years--cough IE6--without resorting to things like JavaScript. I believe my solution is the best solution without resorting to JavaScript.

artlung
More about the IE6 implicit label bug: http://www.evotech.net/blog/2009/09/ie6ie7-implicit-label-bug/
artlung
I just added the <br> so that the content would use up two lines. There are other ways the content could use up two (or more) lines, such as having a very long string of text which needs to break into two lines to fit in the screen. This means that simply counting the <br>s and adding the same amount in the right column wouldn't always work. But thanks very much for trying.
Shawn
+1  A: 

The way you're applying labels doesn't make the form elements fully accessible. The label should be applied on the text associated with the form element, not just the form element. But there's nothing wrong with adding another label over the form element in order to make the entire area inside the TD clickable. This is actually desirable in order to give people with motor disabilities a bigger area to click. The <label for="whatever">Your label</label> is aimed for people who use screen readers to go through the Web form.

Also, there's nothing inaccessible about using JavaScript for enhancing accessibility. JavaScript can be used as long as it degrades gracefully and doesn't stops screen readers from reading the page. Also, there's no way to use CSS to fill the cell height on the older versions of IE (which are still in use by a big number of users) without royally screwing up the look of the page. This said, you should use jQuery to fill the entire TD. The reason I don't say JavaScript is that jQuery saves you a lot of headaches by hiding a lot of the complex coding that's necessary to make this work across the great majority of browsers.

Here's the fully cross browser accessible jQuery enabled code:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&gt;

<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
  <head>
    <title>Accessible Checkboxes</title>

    <script type="text/javascript" src="js/jquery.min.js"></script>

    <script type="text/javascript">
      $(document).ready(function() {
        $("table > tbody tr").each(function() { // Loop through all table rows
          var Highest=0; // We want to find the highest TD... start at zero
          var ThisHeight=0; // Initiate the temporary height variable (it will hold the height as an integer)

          $($(this).children('td')).each(function() { // Loop through all the children TDs in order to find the highest
            ThisHeight=parseInt($(this).height()); // Grab the height of the current TD

            if (ThisHeight>Highest) { // Is this TD the highest?
              Highest=ThisHeight; // We got a new highest value
            }
          });

          $(this).children('td').css('height',Highest+'px');  // Set all TDs on the row to the highest TD height
        });
      });
    </script>

    <style type="text/css">
      table {
        border: 1px solid #000;
      }

      td, label { 
        height: 100%;
        min-height: 100%;
      }

      th {
        text-align: left;
      }

      td, th {
        border: 1px solid #000;
      }

      label { 
        display: block;
      }
    </style>
  </head>
  <body>
    <form action="whatever.shtml" method="post" enctype="multipart/form-data">
      <table cellspacing="3" cellpadding="0" summary="A description of what's in the table.">
        <thead>
          <tr>
            <th scope="col">Some column title</th>
            <th scope="col">Another column title</th>
          </tr>
        </thead>
        <tbody>
          <tr>
            <td scope="row"><label for="value1">Value 1<br />(a bit more info)</label></td>
            <td><label><input id="value1" type="checkbox" /> &nbsp;</label></td>
          </tr>
          <tr>
            <td scope="row"><label for="value2">Value 2</label></td>
            <td><label><input id="value2" type="checkbox" /></label></td>
          </tr>
        </tbody>
      </table>
    </form>
  </body>
</html>

You'll need to download jQuery and put the jquery.min.js file under a folder named js.

As you can see in the code, the form has been made fully accessible by adding a table summary, thead, th, scope, label for etc. Sure, it wasn't part of what you asked, but I added that as an extra bonus.

Gert G
Now this is an elaborate answer! Thanks very much! I didn't know about the scope attribute nor the summary attribute and you are right about the second <label> with its "for" attribute, of course. For a thead and tbody, I had these already in the original code (this one has been chopped down for clarity). I am curious, however, at how this works. You see, by default, <td>'s heights are all set to match the highest in that row, aren't they? So what does your script add then? Or does specifying the height manually somehow enable the <label> to gain 100% height? Would you mind explaining?
Shawn
No problem Shawn. I've been working in an environment that requires accessibility for some 6+ years. You learn as you go. :) As for the script... Some browsers (*cough* IE *cough*) doesn't set the height of the `TD` to the full height of the `TR` when one `TD` is higher than the other(s). The script corrects this flaw. What it does is that goes row by row and checks which `TD` is the highest for that specific row. Then it explicitly sets all the `TD` heights for that row to the highest value. That way, the `LABEL` cells will be able to span the full height of the cell.
Gert G
I see, thanks for clarifying. And so you would also be of the opinion that what I am trying to achieve is impossible without javascript?
Shawn
Yes, it's impossible if you aim for cross browser compatibility. In this case, the JavaScript (jQuery) will improve the accessibility of your Web page.
Gert G
Impossible? What would you have to say about the solution proposed by FreekOne? It is css-only. Is it cross-browser?
Shawn
Yes. Good CSS. No.
Gert G
From what has come up until now, it seems the ideal solution is a combination of both your solution and that of FreekOne. I'll have to give FreekOne the correct answer for not using javascript (nor JQuery). Then, perhaps I will award the bounty to you for having the most "complete" answer, indicating the impossibility of making this cross-browser AND giving so much "related" accessibility information. Thanks very much to both of you!
Shawn
Thank you, Shawn.
Gert G
+1  A: 

This code does what you want and it's tested on IE7+, FF, Google Chrome, Opera and Safari:

<html>
    <head>
        <title>testing td checkboxes</title>

        <style type="text/css">
            td{border:1px solid #000;width:200px;height:200px;}
            label{display:block;border:1px solid #f00;width:198px;height:198px;}
        </style>

    </head>
    <body>

        <table>
            <tr>
                <td>Some column title</td>
                <td>Another column title</td>
            </tr>
            <tr>
                <td>Value 1<br>(a bit more info)</td>
                <td><label><input type="checkbox" /> &nbsp;</label></td>
            </tr>
            <tr>
                <td>Value 2</td>
                <td><input type="checkbox" /></td>
            </tr>
        </table>

    </body>
</html>

If your problem wasn't solved, hope this solves it! ;)

Zuul
Thanks, but I can't guarantee that my content will always fit in 200px by 200px and I certainly don't want scrollbars to appear..
Shawn
the width and height that I've placed its just for demonstration purposes! It can be change to fit your needs... the goal is to tell you that the width and height must be set or what you want will not work!
Zuul
I understand. Unfortunately, due to the dynamic nature of the content, I cannot know in advance what size of cell is needed for the content.
Shawn
+5  A: 

I have only tested this in IE 6, 7, 8 and FF 3.6.3.

<html>
<head>
<title>testing td checkboxes</title>
<style type="text/css">
tr {
    height: 1px;
}
td {
    border: 1px solid #000;
    height: 100%;
}
label { 
    display: block; 
    border: 1px solid #f00;
    min-height: 100%; /* for the latest browsers which support min-height */
    height: auto !important; /* for newer IE versions */
    height: 100%; /* the only height-related attribute that IE6 does not ignore  */
}
</style>
</head>
<body>
<table>
    <tr>
        <td>Some column title</td>
        <td>Another column title</td>
    </tr>
    <tr>
        <td>Value 1<br>(a bit more info)</td>
        <td><label><input type="checkbox" /> &nbsp;</label></td>
    </tr>
</table>
</body>
</html>

The main trick here is to define the height of the rows so we can use a 100% height on their children (the cells) and in turns, a 100% height on the cells' children (the labels). This way, no matter how much content there is in a cell, it will forcibly expand its parent row, and its sibling cells will follow. Since the label has a 100% height of its parent which has its height defined, it will also expand vertically.

The second and last trick (but just as important) is to use a CSS hack for the min-height attribute, as explained in the comments.

Hope this helps !

FreekOne
+1 great solution.
nickf
Congratulations for a css-only cross-browser solution! I just don't understand how setting a 1px height helps. Obviously, the 1px height is completely disregarded as soon as any content is found in the <tr>, and so the height of the <tr> is determined "dynamically", or rather, accordingly to the content. So what then is the difference between that and just not setting a height at all on the <tr>?
Shawn
The way I always assumed this worked was that it provides an actual value for the <tr>'s children percentage height to work as opposed to not being defined at all (NULL ?). You will notice that as soon as you take that out, the model stops working because the <td>'s height value has nothing to relate to - i.e 100% of NULL is still NULL.
FreekOne
It's not cross browser. It doesn't work in Safari 5.0, Iron 5.0.380 or Opera 9.64.
Gert G
Semi-cross-browser then ? :) On a serious note though, I too believe that the only way to make sure this would work on all browsers (or at least as many as possible) would imply the use of JS to some extent, but then again, that too would completely fail if the user has JS disabled for whatever reason. I guess in the end the "correct" answer depends entirely on what Shawn needs his application to run on.
FreekOne
What do you mean with completely fail? My jQuery solution is a progressive enhancement. The great majority of users (yes, even people with screen readers) has JS enabled. And even for the ones that doesn't, it will fall back on the CSS. But then again... you can disable CSS as well. ;)
Gert G
I meant the JS part would completely fail, not the whole page, of course. To be honest when I first read this question I was all "Oh, this is really easy with jQue ..." until I got to the part where he requested a solution that did NOT use JS :) So if he can live with this only working in a few browsers, I guess this is his solution. Otherwise I agree that he's better off with yours (nice one, btw !) or perhaps even a combination of the two, in case JS is disabled.
FreekOne
Thanks. Your CSS was nicely crafted as well. I agree on that the best solution would be a combination of the both. If the JS is enabled, it's going to work in all browsers... if not, it will work in most of the common ones.
Gert G
I must agree with you both. From what has come up until now, it seems the ideal solution is a combination of both your solutions. I'll have to give FreekOne the correct answer for not using javascript (nor JQuery). Then, perhaps I will award the bounty to Gert G for having the most "complete" answer, indicating the impossibility of making this cross-browser AND giving so much "related" accessibility information. Thanks very much to both of you!
Shawn
Thank you, I'm glad I was able to help !
FreekOne
+1  A: 

This answer is a bit "out there" - for it to be valid HTML you'd have to define your own DTD, and in any case it doesn't work in IE or Opera (works in Firefox). So it's not a viable solution by any measure, but I thought I'd share anyway just for interest:

The HTML:

<table>
    <tr>
        <td>Some content</td>
        <label><input type="checkbox" /></label> <!-- no TD -->
    </tr>
    <tr>
        <td>Some<br />multi-line<br />content</td>
        <label><input type="checkbox" /></label>
    </tr>
</table>

The CSS:

label { display: table-cell; }
nickf
Interesting. I don't know enough about custom DTD's yet (I'm planning to learn one day) to understand this solution fully, but it is an approach I haven't thought of yet (nor seen). Thanks for sharing!
Shawn
Even if you implement a brand new DTD, the support for `table-cell;` is limited and there will most likely be accessibility issues, since screen readers might have problems parsing it in a reasonable way.
Gert G
@Gert, **in theory** screen readers should be checking for the *style* of an element to determine how to handle it, not the *name*. But yes, you are correct: like I said, this really isn't viable given the poor cross-browser support.
nickf
@nickf - Where did you learn this theory?
Gert G
@Gert, lol. The W3C, I guess.
nickf
@nickf - Doubt that. You might want to read up on semantic markup and accessibility.
Gert G