By Paul Scanlon


At the time of writing this post gatsby-remark-sticky-table is still very much experimental, it is functional and has had mild testing.

So what is it?

It’s a plugin to help make the <table> great again!

demo 🧲

My motivation is that HTML <table> elements used to be all we had, and now i feel they’ve been forgotten a bit, and with the rise of markdown in tech blogs i want to breath some new life in to an HTML element that used to dominate the web!

There are a number of good examples out there that manage tables, most will either use a sticky header or sticky first column but in markdown you can’t really do much…

Well that’s what i thought at first, until i started reading about remark and unist-util-visit which give me a better understanding of how markdown gets transformed into HTML.

I then stumbled upon this great little tutorial in short what it shows is how to grab references to nodes from markdown and then modify them before passing them back as HTML

const visit = require('unist-util-visit');
const toString = require('mdast-util-to-string');

module.exports = ({ markdownAST }, pluginOptions) => {
  visit(markdownAST, 'heading', (node) => {
    let { depth } = node;
    if (depth !== 1) return;
    let text = toString(node);
    const HTML = `
        <h1 style="color: rebeccapurple">
    node.type = 'HTML';
    node.children = undefined;
    node.value = HTML;

  return markdownAST;

In the above code snippet we can “visit” the markdownAST and look for the “heading” node, later on we check to see if the node has a depth of 1, this is an HTML <h1> if we wanted to visit the <h2> element we could look for a depth of 2 … you get the idea.

Once you’ve grabbed the HTML element you want to modify you can do whatever you like with it and then return it as HTML.

This in short is how i’ve created gatsby-remark-sticky-table.

The next bit is really just css. Once i have a reference to the <thead> i can traverse the AST nodes until i find the first <th> and inline apply a small amount of css to it.

position: sticky;
display: table-cell;
width: auto;
min-width: auto;
white-space: nowrap;
top: 0px;
z-index: 2;

This creates the ‘sticky’ header effect i was after but…

..there’s another little trick going on, and that’s to wrap everything related to the <table> in two additional container divs which allows me to set overflows and heights and allows the ‘sticky’ header to stick to it’s nearest relatively positioned parent.

Each element has also been given a class which should be sufficient for anyone using the plugin to style the table any way they wish.

I’d really appreciate issues, comments or stars on Github so if you are using this plugin in your project please do let me know what you think @pauliescanlon


Leave a reaction and let me know how I'm doing.

  • 0
  • 0
  • 0
  • 0
  • 0
Powered byNeon