2

Consider the following setup:

$(function() {
  var $cols = $("td:nth-child(2), th:nth-child(2)");
  $cols.hover(function() {
    $cols.addClass("highlight");
  }, function() {
    $cols.removeClass("highlight");
  });
});
div {
  background: #edf0f1;
  padding: 20px;
}
table {
  table-layout: fixed;
  width: 500px;
  border-collapse: separate;
  border-spacing: 0;
}
td {
  padding: 10px;
  background-color: #fff;
  border: 1px solid #edf0f1;
  border-right-width: 10px;
  border-left-width: 10px;
}
td.highlight,
th.highlight {
  border-right-color: black;
  border-left-color: black;
}
tr:last-child td {
  border-bottom-width: 10px;
}
tr:last-child td.highlight {
  border-bottom-color: black;
}
th {
  border: 1px solid #edf0f1;
  border-top-width: 10px;
  border-right-width: 10px;
  border-left-width: 10px;
}
th.highlight {
  border-top: 10px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div>
  <table>
    <thead>
      <tr>
        <th>Important</th>
        <th>Information</th>
        <th>Interchange</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>Hello world, how are you today</td>
        <td>again</td>
        <td>and we're done</td>
      </tr>
      <tr>
        <td>More things</td>
        <td>Cow level is real!!1111</td>
        <td>over 9000%</td>
      </tr>
    </tbody>
  </table>
</div>

As you can see, the highlighted table shows ugly "arrows" from the borders upon hover:

Border arrows

How can I get rid of those?

F.P
  • 17,421
  • 34
  • 123
  • 189
  • These off-colored arrows are the ends of the border-tops and border-bottoms of the td cells. You can't paint part of a border one color and part of it another. You will need to rethink your entire HTML layout (do you need tables? Or can divs work?). – TylerH Sep 14 '15 at 14:36
  • I tried divs, but I didn't find a way to make them behave as dynamically to text length changes and breaks as tables. E.g. when a column text becomes bigger than the space it has, the entire row will resize accordingly. The same goes for header columns, etc. From what I found, `div`s cannot change other `div`s height when they change... – F.P Sep 14 '15 at 14:51
  • 1
    The problem is that tables are row-based, and you're trying to achieve a column-based visual effect. It just won't work. The closest you're going to be able to get is something like this: http://jsfiddle.net/gep8c4jq/ unless you write some seriously complex JavaScript (which I don't know) to detect when any of the three elements are being hovered, and then apply appropriate styles to each one. If you add the [tag:javascript] and/or [tag:jquery] tags to your question, you'll probably get some solutions that use those. – TylerH Sep 14 '15 at 15:09
  • FYI in the future there will another option; CSS Grids: https://drafts.csswg.org/css-grid-1/ It will allow you to style and align your content by grid, column, or row, but it won't be available for quite some time. – TylerH Sep 14 '15 at 19:51
  • @TylerH I found a solution. Thanks for your input anyway :-) No need to wait for CSS grids :D – F.P Sep 15 '15 at 10:57

3 Answers3

1

Here, try this.. the larger the border is, the more pronounced the angle is. I changed the border size to 0px

fiddle: https://jsfiddle.net/uqdebsxp/

 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div>
  <table>
    <thead>
      <tr>
        <th>Important</th>
        <th>Information</th>
        <th>Interchange</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>Hello world</td>
        <td>again</td>
        <td>and we're done</td>
      </tr>
         <tr>
        <td>Hello world</td>
        <td>again</td>
        <td>and we're done</td>
      </tr>
      <tr>
        <td>More things to come</td>
        <td>over 9000%</td>
        <td>Cow level is real!</td>
      </tr>
    </tbody>
  </table>
</div>

css

    div {
  background: #edf0f1;
  padding: 20px;
}
table {
  table-layout: fixed;
  width: auto;
  border-collapse: separate;
  border-spacing: 0;
}
td {
  padding: 10px;
  background-color: #fff;
  border: 0px solid #edf0f1;
  border-right-width: 10px;
  border-left-width: 10px;
}
td.highlight,
th.highlight {
  border-right-color: black;
  border-left-color: black;
}
tr:last-child td {
  border-bottom-width: 10px;
}
tr:last-child td.highlight {
  border-bottom-color: black;
}
th {
  border: 0px solid #edf0f1;
  border-top-width: 10px;
  border-right-width: 10px;
  border-left-width: 10px;
}
th.highlight {
  border-top: 10px solid black;
}
Jesse
  • 1,262
  • 1
  • 9
  • 19
  • Okay, but then I don't have a line between the rows, which is required. Like this, you cannot really distinguish between the rows for each column. – F.P Sep 14 '15 at 14:12
  • I found a solution. Thanks for your input anyway :-) – F.P Sep 15 '15 at 10:57
0

You'll need to manually remove borders on hovered items in a columns, using this CSS:

$(function() {
  var $cols = $("td:nth-child(2), th:nth-child(2)");
  $cols.hover(function() {
    $cols.addClass("highlight");
  }, function() {
    $cols.removeClass("highlight");
  });
});
div {
  background: #edf0f1;
  padding: 20px;
}
table {
  table-layout: fixed;
  width: auto;
  border-collapse: separate;
  border-spacing: 0;
}
td {
  padding: 10px;
  background-color: #fff;
  border: 1px solid #edf0f1;
  border-right-width: 10px;
  border-left-width: 10px;
}
td.highlight,
th.highlight {
  border-right-color: black;
  border-left-color: black;
}
tr:last-child td {
  border-bottom-width: 10px;
}
th {
  border: 1px solid #edf0f1;
  border-top-width: 10px;
  border-right-width: 10px;
  border-left-width: 10px;
}

   

/* New CSS */
tbody tr:first-child > td.highlight {
   border-bottom: 1px solid black;
   border-top: 1px solid black;
}
tr:last-child td.highlight {
    border-bottom-color: black;
    border-top: 1px solid;
}
th.highlight {
    border-top: 10px solid black;
    border-bottom: 1px solid;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div>
  <table>
    <thead>
      <tr>
        <th>Important</th>
        <th>Information</th>
        <th>Interchange</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>Hello world</td>
        <td>again</td>
        <td>and we're done</td>
      </tr>
      <tr>
        <td>More things to come</td>
        <td>over 9000%</td>
        <td>Cow level is real!</td>
      </tr>
    </tbody>
  </table>
</div>
robjez
  • 3,740
  • 3
  • 32
  • 36
  • Same problem as with Jesse's answer; the border between rows is required for better visual recognition of the data. Plus, like this the columns jump on hover. – F.P Sep 14 '15 at 14:17
  • 1
    I don't think, what you ask for, is possible without serious modification of your entire code (ie. dropping the table, and moving towards columns based layout), but I modified my snippet, as I think this is as close as you can get. Basically you can't change part of your `bottom/top border`, and this is what you try to do. By adding `highlight`class, you simply modify it's "outer"width of right/left border, and this doesn't affect bottom/top borders at all. You can go for compromise, and change horizontal borders to black respectively, and this is what I suggest. – robjez Sep 14 '15 at 14:34
  • The problem with dropping the table is that `div`s don't change other `div`s height in the same row when their text becomes too long. That's what tables excel in. Besides, the data in the table is definitely best displayed as a table, hence why I chose to do it the "right" way. – F.P Sep 14 '15 at 14:53
  • 1
    I totally understand your rationale - table is for tabular data, and I would stick to that, and probably modify your design decisions, to take into account, the fact that modifying columns (on hover) in row based `html element`, the way you want it, is at least tough. That is why I suggested to opt for black horizontal borders. – robjez Sep 14 '15 at 15:00
  • I found a solution. Thanks for your input anyway :-) – F.P Sep 15 '15 at 10:57
0

Thanks for all the good answers. Being me, I was not satisfied with "it doesn't work" and found a way with only very small adjustments, see below.

$(function() {
  var $cols = $("table [data-col]");
  $cols.hover(function() {
    var colNum = $(this).data("col");
    $("[data-col=" + colNum + "]").addClass("highlight");
  }, function() {
    var colNum = $(this).data("col");
    $("[data-col=" + colNum + "]").removeClass("highlight");
  });
});
div {
  background: #edf0f1;
  padding: 20px;
}
table {
  table-layout: fixed;
  width: 500px;
  border-collapse: separate;
  border-spacing: 0;
}
td {
  vertical-align: top;
  padding: 0;
  background-color: #fff;
  border: 0px solid #edf0f1;
  border-right-width: 10px;
  border-left-width: 10px;
}
td > div, th > div {
  padding: 10px;
  border-top: 1px solid #edf0f1;
  background: none;
}
td.highlight,
th.highlight {
  border-right-color: black;
  border-left-color: black;
}
tr:last-child td {
  border-bottom-width: 10px;
}
tr:last-child td.highlight {
  border-bottom-color: black;
}
th {
  border: 0px solid #edf0f1;
  border-top-width: 10px;
  border-right-width: 10px;
  border-left-width: 10px;
}
th.highlight {
  border-top: 10px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<div>
  <table>
    <thead>
      <tr>
        <th data-col="1"><div>Important</div></th>
        <th data-col="2"><div>Information</div></th>
        <th data-col="3"><div>Interchange</div></th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td data-col="1"><div>Hello world, how are you today</div></td>
        <td data-col="2"><div>again</div></td>
        <td data-col="3"><div>and we're done</div></td>
      </tr>
      <tr>
        <td data-col="1"><div>More things</div></td>
        <td data-col="2"><div>Cow level is real!!1111</div></td>
        <td data-col="3"><div>over 9000%</div></td>
      </tr>
    </tbody>
  </table>
</div>

All that was needed is to wrap the contents into a div and tweak the CSS a little.

This way, I keep the properties of the table (including dynamic row height) but can still highlight per column. Hope it helps someone.

F.P
  • 17,421
  • 34
  • 123
  • 189
  • 1
    Nice one - I was about to suggest that :) But it seemed to me as bit of an overhead. Have you tested this out in all major browsers? Be aware of some issues, mentioned in this thread - http://stackoverflow.com/questions/1110915/is-a-div-inside-a-td-a-bad-idea . It's couple of years old now, so browsers implementations could change drastically. – robjez Sep 15 '15 at 11:06
  • @robjez I tested it in those relevant for my current implementation... If some higher-up decides that IE<10 is relevant for the project, this table will be the least of our team's problems... ;-) – F.P Sep 15 '15 at 12:23