Cols, colgroups and css ":hover" pseudoclass
Asked Answered
G

6

40

I'm trying to create a table to display an individual's BMI.

As a part of this, I'd like, on :hover, for the <tr> and <col> (or <colgroup>) to be highlighted also, in order for the intersection to be more apparent.

As the table will feature both metric and imperial measurements, the :hover doesn't have to stop at the cell (from any direction) and would, in fact, be a bonus if it extended from one axis to the other. I'm also using the XHTML 1.1 Strict doctype, if this makes a difference?

So... an example (the real table's... larger), but this should be representative:

<script>

tr:hover {background-color: #ffa; }

colgroup:hover,
col:hover {background-color: #ffa; }

</script>

...

<table>
    <col class="weight"></col><colgroup span="3"><col class="bmi"></col></colgroup>

    <tr>
        <th></th>
        <th>50kg</th>
        <th>55kg</th>
        <th>60kg</th>
    </tr>

    <tr>
        <td>160cm</td>
        <td>20</td>
        <td>21</td>
        <td>23</td>
    </tr>

    <tr>
        <td>165cm</td>
        <td>18</td>
        <td>20</td>
        <td>22</td>
    </tr>

    <tr>
        <td>170cm</td>
        <td>17</td>
        <td>19</td>
        <td>21</td>
    </tr>

</table>

Am I asking the impossible, do I need to go JQuery-wards?

Girish answered 11/5, 2009 at 16:11 Comment(0)
A
72

Here's a pure CSS method using no JavaScript.

I used ::before and ::after pseudo-elements to do the row and column highlighting. z-index keeps the highlighting below the <td>s in case you need to handle click events. position: absolute allows them to leave the confines of the <td>. overflow: hidden on the <table> hides the highlight overflow.

It wasn't necessary, but I also made it select just the row or column when you're in the headers. The .row and .col classes take care of this. If you wish the simplify, you can remove them.

This works in all modern browsers (and degrades gracefully on older browsers by doing nothing).

Demo: http://jsfiddle.net/ThinkingStiff/rUhCa/

Output:

HTML table with highlighted row and column

CSS:

table {
    border-spacing: 0;
    border-collapse: collapse;
    overflow: hidden;
    z-index: 1;
}

td, th, .row, .col {
    cursor: pointer;
    padding: 10px;
    position: relative;
}

td:hover::before,
.row:hover::before { 
    background-color: #ffa;
    content: '\00a0';  
    height: 100%;
    left: -5000px;
    position: absolute;  
    top: 0;
    width: 10000px;   
    z-index: -1;        
}

td:hover::after,
.col:hover::after { 
    background-color: #ffa;
    content: '\00a0';  
    height: 10000px;    
    left: 0;
    position: absolute;  
    top: -5000px;
    width: 100%;
    z-index: -1;        
}

HTML:

<table>
    <tr>
        <th></th>
        <th class="col">50kg</th>
        <th class="col">55kg</th>
        <th class="col">60kg</th>
        <th class="col">65kg</th>
        <th class="col">70kg</th>
    </tr>
    <tr>
        <th class="row">160cm</th>
        <td>20</td><td>21</td><td>23</td><td>25</td><td>27</td>
    </tr>
    <tr>
        <th class="row">165cm</th>
        <td>18</td><td>20</td><td>22</td><td>24</td><td>26</td>
    </tr>
    <tr>
        <th class="row">170cm</th>
        <td>17</td><td>19</td><td>21</td><td>23</td><td>25</td>
    </tr>
    <tr>
        <th class="row">175cm</th>
        <td>16</td><td>18</td><td>20</td><td>22</td><td>24</td>
    </tr>
</table>
Ambidextrous answered 24/6, 2012 at 8:16 Comment(7)
May I respond with a +1 and an acceptance? I played around with the ::before and ::after pseudo elements last night (when I remembered the question), but could quite get them to work as I wanted. Thanks! =)Girish
The fix for firefox is not needed anymore.Tutty
You might be interested to know that there's a css-tricks article that links to your answer here.Bossy
This works great in all the browsers I tested (IE9, IE11, FF, Chrome) - the FF fix seems to be no longer necessary :-)Wobbling
You should ensure that overflow:visible is set on td!Lands
this approach does not work if <td> has background color. Does anyone know what to do in such case?Ricoriki
Does not work if there is a sticky header because of overflow: hiddenPerfidy
D
8

There is a very decent jQuery plugin I've come across located here which does a very good job of this kind of thing with loads of examples. Preferentially I'd use that.

Dependent answered 11/5, 2009 at 16:24 Comment(1)
Wouldn't it be nice, though, to be able to use CSS as it should -in my imagination be able to- be used? =) I'll check out the JQuery, thanks for that!Girish
A
4

AFAIK CSS Hovers on TR's aren't supported in IE anyway, so at best the TR part of that will only work in Firefox.

Never even seen a :hover work on a col/colgroup so not sure if that's possible...

Think you might be stuck with a Javascript implementation.

Theres an example here that works (rows & cols) in Firefox but again its broken in IE... cols don't work.

Amosamount answered 11/5, 2009 at 16:19 Comment(3)
That's definitely consistent with my experiences, if not quite the miracle I was hoping for... =)Girish
Depends on the doctype and the version. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> works in IE7 anyway.Dependent
The :hover state will not only work in Firefox, but every other major non-IE browser (Opera, Konqueror, Safari, et al).Peculiarity
D
3

Live answer (https://jsfiddle.net/craig1123/d7105gLf/)

There are already CSS and JQuery answers; however, I have written a simple pure javascript answer.

I first find all the col and td tags, get the column index of each cell by doing element.cellIndex, and then add a CSS class with a background on mouseenter and removing it on mouseleave.

HTML

<table id='table'>
  <col />
  <col />
  <col />
  <col />
  <thead>
    <tr>
      <th>Name</th>
      <th>Age</th>
      <th>Birthdate</th>
      <th>Preferred Hat Style</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Abraham Lincoln</td>
      <td>204</td>
      <td>February 12</td>
      <td>Stovepipe</td>
    </tr>
    <tr>
      <td>Winston Churchill</td>
      <td>139</td>
      <td>November 30</td>
      <td>Homburg</td>
    </tr>
    <tr>
      <td>Rob Glazebrook</td>
      <td>32</td>
      <td>August 6</td>
      <td>Flat Cap</td>
    </tr>
  </tbody>
</table>

CSS

body {
  font: 16px/1.5 Helvetica, Arial, sans-serif;
}

table {
  width: 80%;
  margin: 20px auto;
  border-collapse: collapse;
}
table th {
  text-align: left;
}
table tr, table col {
  transition: all .3s;
}
table tbody tr:hover {
  background-color: rgba(0, 140, 203, 0.2);
}
table col.hover {
  background-color: rgba(0, 140, 203, 0.2);
}
tr, col {
  transition: all .3s;
}
tbody tr:hover {
  background-color: rgba(0,140,203,.2);
}
col.hover {
  background-color: rgba(0,140,203,.2);
}

JS

const col = table.getElementsByTagName('col');
const td = document.getElementsByTagName('td');

const columnEnter = (i) => col[i].classList.add('hover');
const columnLeave = (i) => col[i].classList.remove('hover');

for (const cell of td) {
    const index = cell.cellIndex;
    cell.addEventListener('mouseenter', columnEnter.bind(this, index));
    cell.addEventListener('mouseleave', columnLeave.bind(this, index));
}

Here is a fiddle

Delayedaction answered 7/3, 2017 at 21:45 Comment(0)
T
2

I came accross this neat way of doing it its from css-tricks.com I also prepared a fiddle whilst messing around with it nothing fancy but u can get the idea its with the same code provided by that css-trick page

//The Html

<table>
    <colgroup></colgroup>
    <colgroup></colgroup>
    <colgroup></colgroup>
    <colgroup></colgroup>
    <colgroup></colgroup>
    <thead>
        <tr>
            <th></th>
            <th></th>
            <th></th>
            <th></th>
            <th></th>
        </tr>
    </thead>
    <tbody>
            <tr>
                <td></td>
                <td></td>
                <td></td>
                <td></td>
                <td></td>
            </tr>
            <tr>
                <td></td>
                <td></td>
                <td></td>
                <td></td>
                <td></td>
            </tr>
            <tr>
                <td></td>
                <td></td>
                <td></td>
                <td></td>
                <td></td>
            </tr>
        </tbody>
</table>

//The Js

$(function(){
    $("table").delegate('td','mouseover mouseleave', function(e) {
        if (e.type == 'mouseover') {
          $(this).parent().addClass("hover");
          $("colgroup").eq($(this).index()).addClass("hover");
        }
        else {
          $(this).parent().removeClass("hover");
          $("colgroup").eq($(this).index()).removeClass("hover");
        }
    });
})

Check out the fiddle here

Teakwood answered 16/10, 2014 at 3:6 Comment(0)
A
2

Inspired by @ThinkingStiff's pure CSS method, here's an approach with the same output based on :has() pseudo-classes (and without needing ::before and ::after pseudo-elements). :has() support here.

Demo: https://jsfiddle.net/x37v/tf2a43k5/

HTML

<table>
  <colgroup>
    <col>
    <col>
    <col>
    <col>
    <col>
    <col>
  </colgroup>
  
  <tbody>
    <tr>
      <th></th>
      <th>50kg</th>
      <th>55kg</th>
      <th>60kg</th>
      <th>65kg</th>
      <th>70kg</th>
    </tr>

    <tr>
      <th>160cm</th>
      <td>20</td>
      <td>21</td>
      <td>23</td>
      <td>25</td>
      <td>27</td>
    </tr>

    <tr>
      <th>165cm</th>
      <td>18</td>
      <td>20</td>
      <td>22</td>
      <td>24</td>
      <td>26</td>
    </tr>

    <tr>
      <th>170cm</th>
      <td>17</td>
      <td>19</td>
      <td>21</td>
      <td>23</td>
      <td>25</td>
    </tr>

    <tr>
      <th>175cm</th>
      <td>16</td>
      <td>18</td>
      <td>20</td>
      <td>22</td>
      <td>24</td>
    </tr>
    </tbody>
</table>

CSS:

table {
  border-spacing: 0;
  border-collapse: collapse;
}

td, th {
  cursor: pointer;
  padding: 10px;
  position: relative;
}

/*  Row rules: Excluding the top row, highlight any row that the mouse is over */
table:has(tr:not(:nth-child(1)):hover) tr:hover,

/*  Column rules: Highlight the respective columns on td:hover and th:hover (omitting the first column) */
table:has(td:nth-child(2):hover, th:nth-child(2):hover) col:nth-child(2),
table:has(td:nth-child(3):hover, th:nth-child(3):hover) col:nth-child(3),
table:has(td:nth-child(4):hover, th:nth-child(4):hover) col:nth-child(4),
table:has(td:nth-child(5):hover, th:nth-child(5):hover) col:nth-child(5),
table:has(td:nth-child(6):hover, th:nth-child(6):hover) col:nth-child(6) {
  background-color: #ffa;
}
Assiut answered 31/1 at 13:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.