Search code examples
htmlcsscss-tables

Change table border upon hover


EDIT

To be clearer, the below is what I'm trying to achieve.

enter image description here


I'm trying to create a table where each row has a single pixel border with a radius (mimicking a collapsed border style). Upon hovering over a row, I'd like the selected row's border to change colour. I've almost achieved this with the following code, but upon hovering over a row, the following row drops down 1px to make room for the hover border.

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

td {
    border: solid 1px black;
    border-style: solid none;
    padding: 10px;
    border-bottom: 0;
}

td:first-child {
    border-left-style: solid;
    border-top-left-radius: 10px;
    border-bottom-left-radius: 10px;
}

td:last-child {
    border-right-style: solid;
    border-bottom-right-radius: 10px;
    border-top-right-radius: 10px;
}

tr:last-child td {
    border-bottom: solid 1px black;
}

tr:hover {
    /*background-color: #cad6ed;*/
}

tr:hover td {
    border: 1px solid #12A0F8;
    border-style: solid none;
    padding: 10px;
}

tr:hover td:first-child {
    border-left-style: solid;
    border-top-left-radius: 10px;
    border-bottom-left-radius: 10px;
}

tr:hover td:last-child {
    border-right-style: solid;
    border-bottom-right-radius: 10px;
    border-top-right-radius: 10px;
}
<table>
  <tr>
    <td>One</td><td>Two</td><td>Three</td>
  </tr>
  <tr>
    <td>One</td><td>Two</td><td>Three</td>
  </tr>
  <tr>
    <td>One</td><td>Two</td><td>Three</td>
  </tr>
</table>

Is there a better approach to this?

Many thanks in advance.


Solution

  • Updated better solution

    Don't know why I didn't tackle the core issue from the start but your main issue was the item below was getting pushed down, well you can target the next item and set the border top to none

    tr:hover + tr td {
        border-top: none;
    }
    

    The rest of your original code remains intact

    table {
        border-collapse: separate;
        border-spacing: 0;
    }
    
    td {
        border: solid 1px black;
        border-style: solid none;
        padding: 10px;
        border-bottom: 0;
    }
    
    tr:hover + tr td {
        border-top: none;
    }
    
    td:first-child {
        border-left-style: solid;
        border-top-left-radius: 10px;
        border-bottom-left-radius: 10px;
    }
    
    td:last-child {
        border-right-style: solid;
        border-bottom-right-radius: 10px;
        border-top-right-radius: 10px;
    }
    
    tr:last-child td {
        border-bottom: solid 1px black;
    }
    
    tr:hover {
        /*background-color: #cad6ed;*/
    }
    
    tr:hover td {
        border: 1px solid #12A0F8;
        border-style: solid none;
        padding: 10px;
    }
    
    tr:hover td:first-child {
        border-left-style: solid;
        border-top-left-radius: 10px;
        border-bottom-left-radius: 10px;
    }
    
    tr:hover td:last-child {
        border-right-style: solid;
        border-bottom-right-radius: 10px;
        border-top-right-radius: 10px;
    }
    <table>
      <tr>
        <td>One</td><td>Two</td><td>Three</td>
      </tr>
      <tr>
        <td>One</td><td>Two dfds</td><td>Three</td>
      </tr>
      <tr>
        <td>One</td><td>Two</td><td>Three</td>
      </tr>
    </table>

    Old answer

    You can do it by setting the tr to display block. I used margin-top -1px to hide the extra border. To simplify things, I removed border from td and just put it on the tr since you don't have borders in between tds anyway

    The z-index on hover makes the hovered item popup with the border

    I put the negative margin on all tr but the first, you could probably get away with it on all trs

    table {
      border-collapse: separate;
      border-spacing: 0;
    }
    
    td {
      padding: 10px;
    }
    
    tr {
      border-radius: 10px;
      border: 1px solid #000;
      display: block;
      box-sizing: border-box;
      position: relative;
    }
    
    tr:not(:first-child) {
      margin-top: -1px;
    }
    
    tr:hover {
      z-index: 2;
      border: 1px solid blue;
    }
    <table>
      <tr>
        <td>One</td>
        <td>Two</td>
        <td>Three</td>
      </tr>
      <tr>
        <td>One</td>
        <td>Two</td>
        <td>Three</td>
      </tr>
      <tr>
        <td>One</td>
        <td>Two</td>
        <td>Three</td>
      </tr>
    </table>