HTML table row transitions with Vue.js and Velocity.js
Posted by Seb T in blog on
CSS and JS transitions/animations are great for adding subtle (or less so) transition effects to elements in the DOM. But one use-case that requires special attention is tables. In a recent commercial application we needed interactive tables with fine-grained control of the appearance of table rows and cells. In this aticle we provide a simple demo using Vue.js and Velocity/js that shows a simple slideUp/slideDown to highlight row insertion/removal visually. The method illustrated is easily expanded with a sequence of animations and can be used to control complex table layouts with compound row, column or cell animations.
For slides, the usual approach involves overflow:hidden
together with manipulation of an element's height
property over time. A typical approach (eg. with jQuery) would involve some JS to perform a slideUp/slideDown, or using CSS transitions we could apply some CSS classes together with the transition
property. But tables present an edge-case: the browser determines the height of tr
and contained td
elements by content and refuses any attempts to override the height of these elements, either with CSS or inline styles.
Our approach is to ensure that our table cell content is wrapped in a div
, set overflow: hidden
on them, remove any padding on the cells and apply it to the divs instead. We can then animate both the max-height and the padding of the divs and our table rows will automatically expand or contract.
A secondary problem arises from the way transitions are leveraged within Vue.js through the included transition
or transition-group
components. Typically in Vue, where repeating data are concerned, the approach is to render a dataset held in an array as table rows using v-for
in the template, then use a transition-group to define the transition for each element in the list as it appears or disappears. This won't work for table rows, as we'll need to perform transitions on child elements of the table to collapse or expand our rows; we'll leverage some Vue hooks on the transition-group so we can fire our Velocity transitions on child elements when the row is about to appear or disappear.
We assume for our example that some table rows will be initially displayed, and that all rows/cells will have the same height. In so doing, we can read the table cell and padding values from the table and use them for transitions, avoiding the need for hardcoding these values into our Velocity calls.
Lastly achieving the same using pure CSS is possible but not desirable here: it's more work, less semantic and offers us less overall control. We've used Velocity.js to provide the effects themselves, which offers comparable performance to CSS transitions but with greater control of animation specifics. jQuery would work here (though not recommended for animation), as would GreenSock or your own JS.
(See also "Transition-group is not working on tables", Vue Github issue