skip to Main Content

I have an html table where I want to, using only CSS:

  • show the last td of each row when hovering on the row, and
  • show the last td of each column when hovering on that column.

This is my solution for rows:

/* Hide last cell in each row by default */

tr td:last-child {
  display: none;
}


/* Show last cell in row on row hover */

tr:hover td:last-child {
  display: block;
}
<table>
  <tr>
    <td>1</td>
    <td>2</td>
    <td>3</td>
  </tr>
  <tr>
    <td>4</td>
    <td>5</td>
    <td>6</td>
  </tr>
</table>

But for the life of me I cannot make it work for columns.

NOTE: Any method to show/hide cells is game (display/visibility, etc)

2

Answers


  1. You can use the :has() rule (currently not supported by FF) to show the last td in a column, if one of the td elements in that column id hovered. You’ll need to supply a specific rule for each column:

    /** rows **/
    tr:not(:hover) td:last-child {
      visibility: hidden;
    }
    
    /** column 1 **/
    table:not(:has(tr td:nth-child(1):hover))
      tr:last-child td:nth-child(1) {
        visibility: hidden;
      }
    
    /** column 2 **/
    table:not(:has(tr td:nth-child(2):hover))
      tr:last-child td:nth-child(2) {
        visibility: hidden;
      }
    <table>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>4</td>
        <td>5</td>
        <td>6</td>
      </tr>
      <tr>
        <td>7</td>
        <td>8</td>
        <td>9</td>
      </tr>
    </table>

    If you have a large amount of columns, or the number of columns is dynamic, you can generate the rules for the columns using JS:

    const generateColumnRules = numOfColumns => {
      const style = document.createElement('style');
      style.type = 'text/css';
      style.innerHTML = Array.from(
        { length: numOfColumns },  
        (_, i) => `
          table:not(:has(tr td:nth-child(${i + 1}):hover))
            tr:last-child td:nth-child(${i + 1}) {
              visibility: hidden;
            }    
        `
      ).join('n');
      document.querySelector('head').appendChild(style);
    }
    
    generateColumnRules(2);
    /** rows **/
    tr:not(:hover) td:last-child {
      visibility: hidden;
    }
    <table>
      <tr>
        <td>1</td>
        <td>2</td>
        <td>3</td>
      </tr>
      <tr>
        <td>4</td>
        <td>5</td>
        <td>6</td>
      </tr>
      <tr>
        <td>7</td>
        <td>8</td>
        <td>9</td>
      </tr>
    </table>
    Login or Signup to reply.
  2. A way to do this with JS code, working on ALL browsers (FireFox doesn’t support CSS :has())

    Less than ten lines of JS code (and 2 lines of css)

    const
      myTable  = document.querySelector('#my-table tbody')
    , last_TDs = myTable.querySelectorAll('tr:last-child td')
      ;
    myTable.onmouseover = ({target:TDx}) =>
      {
      last_TDs.forEach(td => td.classList.remove('showIt'))
      if (!TDx.matches('td')) return;  
      last_TDs[TDx.cellIndex].classList.add('showIt');
      }
    myTable.onmouseout = () =>
      {
      last_TDs.forEach(td => td.classList.remove('showIt'))
      }
    /*-- cosmetic part -- */
    table {
      border-collapse  : separate;
      border-spacing   : 1px;
      background-color : darkblue;
      margin           : 1em;
      color            : black;
      font-size        : .8rem;
      --showCol        : 2;
      }
    table td {
      background-color : whitesmoke;
      padding          : .2em .6em;
      min-width        : 2em;
      text-align       : right;
      }
    /*-- cosmetic part -- [end] */
    
    
    tr td:last-child       { color: whitesmoke;  }
    tr:hover td:last-child { color: black; }
    
    tr:last-child td        { color: whitesmoke;  }
    tr:last-child td.showIt { color: black;  }
    <table id="my-table">
      <caption> horizontal/vertical sums</caption>
      <tbody>
        <tr><td> 1</td><td> 2</td><td> 3</td><td> 6</td></tr>
        <tr><td> 4</td><td> 5</td><td> 6</td><td>12</td></tr>
        <tr><td> 7</td><td> 8</td><td> 9</td><td>18</td></tr>
        <tr><td>12</td><td>15</td><td>18</td><td>  </td></tr>
      </tbody>
    </table>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search