43

I have a fairly standard bootstrap-styled <table>. I want to make columns of this table resizable, e.g. by click-and-dragging right border of <th> element. I can't use any jQuery plugins as I'm using Angular and jQuery dependency is not acceptable.

I was thinking that if I could catch the click/mousemove event on the right border of <th> element, I could implement my own resizing logic (monitor horizontal mouse movement and adjust width accordingly), but I don't know how this can be done (there is no such thing as element border-related event as far as I know).

What's the best way to make columns resizable by user? Without jQuery (and preferably - in Angular 2 context).

Titan
  • 2,875
  • 5
  • 23
  • 34
  • There is guide [here](https://medium.com/@rohit22173/creating-re-sizable-columns-in-angular2-d22fbcbe39c9). It uses some jQuery, but nothing that can't be replaced with simple vanilla JavaScript. – Jamie Barker May 04 '18 at 08:57

2 Answers2

70

The resize property does not work with table. That's why you need to put a div inside the table th and td, then resize it.

Try the below snippet

table {
  border-collapse: collapse;
  border-spacing: 0px;
}
td {
  border: 2px solid black;
  padding: 0;
  margin: 0px;
  overflow: auto;
}

div {
  resize: both;
  overflow: auto;
  width: 120px;
  height: 120px;
  margin: 0px;
  padding: 0px;
  border: 1px solid black;
  display:block;

}

td div {
  border: 0;
  width: auto;
  height: auto;
  min-height: 20px;
  min-width: 20px;
}
<table>
  <tr>
    <td><div>one</div></td>
    <td><div>two</div></td>
    <td><div>three</div></td>
  </tr>
  <tr>
    <td><div>four</div></td>
    <td><div>five</div></td>
    <td><div>six</div></td>        
  </tr>
  <tr>
    <td><div>seven</div></td>
    <td><div>eight</div></td>
    <td><div>nine</div></td>       
  </tr>   
</table>
Seth McClaine
  • 9,142
  • 6
  • 38
  • 64
Jishnu V S
  • 8,164
  • 7
  • 27
  • 57
  • This helps. How do I get new widths after resize? – Mamata Hegde Jul 13 '17 at 09:09
  • if you want to know the new width, then you need to use jquery and get width of the div, because new width is not defined – Jishnu V S Jul 13 '17 at 09:15
  • 4
    This does not work for IE 11. Nor does it work for Edge. I suspect that both fail due to lack of support for CSS `resize`. – Zarepheth Jun 18 '18 at 19:06
  • nice example !! – AngelSalazar Oct 04 '18 at 15:28
  • This solution has issues for when you make the table 100% width. The resizing freaks out. – Pedro Jun 02 '21 at 06:58
  • @Pedro Yup. Which makes this trick not usable since most of the time we don't know when the table width is going to be `100%` when using `auto` layout. HTML just sucks to no end sometimes. – m4heshd Jun 24 '21 at 06:21
  • @m4heshd Yep, although I did actually end up managing to make a resizeable 100% width table, it just was a hell of a lot of work. I'll try and see if I can extract the logic into something I can post here. I implemented it in Vue with Vue Styled Components but i should be able to make a JSFiddle with pure vanilla JS and CSS for instructional purposes. Give me a few days. – Pedro Jun 28 '21 at 19:02
  • @Pedro Thank you. Actually I was able to create a fairly simple solution for my case. I too am on Vue. But still I'd like to take a peek at your code. – m4heshd Jun 28 '21 at 20:46
  • @Pedro Did you end up making that js fiddle? – MikeT Jul 10 '21 at 19:15
  • @m4heshd Any hope you'd share a JSFiddle? Simpler is better :) – MikeT Jul 10 '21 at 19:16
  • @MichaelTranchida Not yet sorry, I'm drowning at work. I promise to deliver, just might be a bit. At the very minimum I will provide my git repo – Pedro Jul 12 '21 at 23:44
  • Simpler than I thought but if I keep resizing them here and there, the /// mark at the bottom-right corner does not stick to the bottom-right corder and gets detached and stays in the middle of the cell. How to fix that? Screenshot: https://i.imgur.com/3u6vkxu.png – Damn Vegetables Jul 22 '21 at 18:09
  • @MichaelTranchida Ok, as promised I'm going to provide some code here, unfortunately work still has me dying so I didn't have time to extract *just* the stuff you're interested in nor make a non-Vue specific implementation. So this is massively overengineered compared to what you really need to solve this problem. The link has my entire data table component, but the main part you're going to be interested in for the resizeable cell question is the TableHeader component and the theme.js file for my ThemeProvider https://codesandbox.io/s/trusting-brook-d6e1k – Pedro Aug 04 '21 at 17:09
  • @m4heshd Pinging you so you can see my comment as well – Pedro Aug 04 '21 at 17:10
  • @Pedro Man, feel bad having to say this since you're swamped with work, but one of my requirements is that the table rows don't grow in height when shrinking column width, rather, the content of `td`s in that column just get hidden. I know I had this working in some project, but I was using javascript to achieve it. Think I'm gonna have to hunt down that implementation or reinvent the wheel. Thank you though, and sorry I wasn't clear on what I wanted. – MikeT Aug 04 '21 at 19:50
  • @Michael hey man that’s fairly easy to do with my setup. You just make white-space:no-wrap and word-break: keep-all on the td elements. I can fork the code sandbox with an example after work. – Pedro Aug 05 '21 at 20:30
  • @DamnVegetables my codesandbox listed above has the solution for that, you need to use a resize observer that detects when the resize is complete and sets the resizeable div in the table cell back to 100% width. – Pedro Aug 06 '21 at 01:34
  • @MichaelTranchida I take back what I said earlier, I didn't account for the fact that the css fix won't affect the other resize wrappers in other cells in the header. I don't have time to implement a solution but I believe you could hook into the ResizeObserver call that I have and change the widths of the other resize wrappers in a column in the callback plus the css I suggested to make that happen. Sorry I can't help more at the moment! :( – Pedro Aug 06 '21 at 01:42
  • 1
    @Pedro NP, been playing around with it some more, It's a bit of a frustrating problem. Seems like it should be a standard on tables, but hey, that's me. Thank you for your efforts. Js it is! – MikeT Aug 06 '21 at 22:22
0

Here is some well written sample code for resizeable columns: https://www.exeideas.com/2021/11/resizable-columns-of-table-javascript.html It is different from putting div to every table field, it has much more readable resizable table as result.