Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Flexible data tables with CSS Grid (adamlynch.com)
304 points by adamlynch on May 18, 2019 | hide | past | favorite | 62 comments


Now we’ve gone full circle from using tables for layout, to using layout for tables.


This made me laugh. To be fair, the article talks about restyling <table> and related elements using grid instead of table display, rather than building tables using a bunch of <div> elements, which was a real thing I saw people advocate for during the whole anti-layout-table backlash.


It can be better to use divs instead of tables in some situations, especially when you want to display thousands of rows inside of a relatively complex DOM structure. All browsers seem to render them faster, but in Chrome specifically there are bugs like this: https://bugs.chromium.org/p/chromium/issues/detail?id=461877 and one that can trigger a huge cascade of recursive style recalculations (which in practice freezes browsers for a few seconds). Virtual scrolling is another way of avoiding this problem but it can be tricky if you don't know the height of the rows.


Last year I had to build a UI with several thousand rows in a data grid. Of course I used a table for this, since tables are for displaying tabular data! Once I got a full set of production data into it, scrolling the page absolutely crushed the browser, running at about three frames per second. I believe the issue was actually caused by a parent element with overflow: scroll-y, but switching to divs made it run smooth as butter.



I am unable to properly select the text in the “tables” in the OP in Safari on iOS. Don’t know if this is due to a problem with Safari or with the way OP did their stuff but either way it is really annoying.


Selecting works in Firefox. It even behaves as you would expect if you copy-paste to e.g. Libreoffice, because the markup is still a table.

The only thing that doesn’t work is selecting cell ranges in the browser. At least in Firefox, for regular tables, you can do that by holding ctrl or shift while selecting. I guess you could restore this behavior with some Javascript.

Also no idea how this impacts any a11y related things.


They use `display: content` which many assistive technologies will incorrectly remove from the accessibility tree (or at least they used to). So it is not currently recommended to use this this value if you want the content to be accessible.

https://hiddedevries.nl/en/blog/2018-04-21-more-accessible-m...


I'm thinking if you strip away the js and css, it's just a plain ol' table in the html .. wouldn't have thought it'd be an issue, accessibility-wise.


Actually when you have a `display` of something else then `table` you will strip away the table semantics from the accessibility tree (unless you add `role="table"` etc on the table elements).

https://developer.paciellogroup.com/blog/2018/03/short-note-...


I would hope so, but you never know.


Great writeup. I found the defensive FAQ at the end funny -- really speaks to the prematurely critical culture of software dev in these forums.

On related note, does anyone else prefer panning desktop-sized pages on mobile devices? Given that they're usually touch devices it feels natural to pan around the regular desktop-sized page and pinch in to zoom on parts you're interested in. Like in this case I'd probably prefer panning to the single row collapsing and taking most of the screen space on mobile. Generally mobile/tablet screens feel like they're really good at exploring a larger-than-device canvases so its not obvious to me why so much effort goes into mobile-only views.


Completely agree. There’s also the issue of users who browse the web at more than 1x zoom. Zooming triggers breakpoint changes and we’ve received a ton of user feedback claiming they prefer to scroll horizontally in general (not just tabular data), as opposed to getting a mobile “optimized” view.


That is a nice tool you have built there. It is important to remember that people who will be looking at this screen every day are expert users, they will have dual screen desktops with a mouse, not be fumbling on a phone having not seen the interface before. You did well to make it so they can perfect the information they have on their screen and these efforts will be appreciated in day to day usage.

Also it is cool that you have stuck with the semantically correct element in a table.

What you can also do with CSS Grid is a table that does not have the extra markup for empty cells, i.e. a sparse table. With some autoflow for the columns and an element name or class setting a column number, you can make a table from other data such as a definition list with the 'display: contents' trick giving grid access to the content in a data definition elements. So you can fully model a contact card for someone using the same markup for pretty contact cards or in the 'table view'. You can also do all of the column reordering without changing the document, the rows or cards can always be written in the same logical order, regardless of whether the columns are rearranged or hidden.

There is actually a rendering slowdown with CSS Grid although I have only found this after nesting a few grids and having some transparency on each, going to an older layout technique fixed that. It would be interesting to know if there is a slowdown here, if hundreds of off screen rows are in the document.


I find it hard to differentiate between rows when it is in portrait mode one under another. When I've had to do projects with modular tables ect; I've used an awesomelibary called datatables. They have heaps of plugins that let you do things like load from json, filtering and sorting, pagination, export etc. I've found it a very feature complete product off the shelf.


Datatables actually has a plugin to also vertically space some content with a reveal button on smaller screens.

https://datatables.net/extensions/responsive/examples/initia...

Modern frameworks make a bunch of datatables needless at this point, but I still often use it (with Vue) just because it's so complete with so many plugins.


Designers always a slightly different vision of what data-heavy means...

https://images.app.goo.gl/goKeqhU8oHCTxiHK7


I wouldn’t do this, or at least I’d do a bunch of accessibility testing before implementing this (something which wasn’t mentioned in the article).

Assistive tech allows column and row access to tables that have the default display:table styling. Setting them to display:block (a common approach for mobile historically) typically removes the ability for people to navigate in this way. I would imagine that changing to display:grid does the same.

More info at https://vimeo.com/139062429 as an example.


Would setting the appropriate aria roles help here?


Yes I believe so, there are ARIA roles for tabular data:

https://developer.mozilla.org/en-US/docs/Web/Accessibility/A...


That relies on assistive tech supporting them. I’m not saying they don’t, but historically it’s been lacking. Great if they do, but testing would absolutely be needed.



now that with the first column also fixed. i failed


I don’t see what benefit the table elements are providing. It’s just convoluting the grid with hidden CSS rules. Why not just use a div for the row and spans for columns? The inline and block behavior of those elements is what defines and distinguishes them. Paired with CSS reset there are no hidden CSS rules affecting their behavior.


Semantics. It's still tabular data and divorced from their custom CSS rules, it would still display as a table.


In addition to the other comments, for those few running old enough browsers that none of the new CSS is recognized, the fallback is basic HTML table layout (because at its core, it is still a HTML table).


Accessibility.


As another user pointed out, there are ARIA roles for this. At this point we are way past being forced to use clumsy elements just for accessibility reasons and the roles are preferred by screen readers.

https://developer.mozilla.org/en-US/docs/Web/Accessibility/A...


In my experience developers are really bad at implementing accessible components from scratch. There are a lot of nuanced edge cases that is easy for a mere human to miss. Like:

* Tabbing order, trapping the tab order (but still allow tabbing to the URL bar)

* Keyboard navigation, and keyboard controls, esc and arrow key behavior etc.

* Submit behavior and change events

And many more. Setting the correct `role` only adds the semantics for assistive technologies and is by no means sufficient to make things accessible.

When you just use `<table>`, `<details>`, `<button>`, <select>, `<dialog>`, etc. you get all accessibility correctly implemented for free.

Sure you can find a library that implements the component. But these are too implemented by mere humans and are likely to miss some of the nuanced edge cases. Also by that point you might as well just use the standard elements.


It sounds good, but the examples are not responsive on mobile ... they don't stack as mentioned in the post but instead shrink. Eg: https://s.codepen.io/adam-lynch/debug/XwKWdG

The draggable columns are a nice feature though.


I’d say it’s all working as described and intended: the examples are all simplified examples demonstrating particular aspects of the solution, and none of those examples are of the stacking business.


Not the point of the post, but Adam's site is beautiful to me. Simple, accessible, and yet still handsome. Whenever I try to make a website it ends up looking like a mid-90s burnout. Is there anywhere besides a graphic design school to go about learning some principles of what makes things look good?


I have tried using CSS grid a few times, but my impression of it was... meh. The oppurtunities to use it are few in between, it doesn't bring much more to the table than (nested) flex, and worst of all, I had huge problems understanding what I did a few months later, even though I have tried to do it properly (and after deciphering it, there was nothing that I would change).

Did anyone have opposite experience?

EDIT: OP's experience is of course different, for such customizable tables CSS Grid probably makes sense. My opinion applies more to generic layout.


My experience is that almost all of the early “CSS Grid lets you do this!” examples were either: ⓐ actually achievable with Flexbox in a non-contrived way; or ⓑ outright weird things that will seldom actually be desired, being more related to art direction than layout or similar.

Since then, I have come across a few cases where Grid was used to advantage in a way that Flexbox couldn’t have matched—I’ve even written a couple myself. The main case I’ve found is responsive layout, where you want to do something like interleaving rather than just stacking of elements, as you scale down a two-dimensional layout. This is the use for one I’ve written: see the responsive design of the hero area on https://www.topicbox.com/ and how the video moves from the right into the middle of the content from the left column, which would be exceedingly painful to handle well without Grid, probably requiring absolute positioning and/or float.

But mostly, I find Flexbox to be sufficient, with Grid very occasionally offering a nicer way of doing something that was already possible.

It’s not uncommon for me to do things with Grid now, for work or in my own projects, but I confess that I normally have to lean heavily on docs on the grid-* properties when I’m getting started, which I don’t for Flexbox. I know its capabilities and thus when it might be applicable, but the actual syntax is too powerful and flexible, with too many ways of achieving similar and different results, and so it will take more use to internalise than most features, but Grid’s just not useful enough that I think most are likely to reach that threshold.


> This is the use for one I’ve written: see the responsive design of the hero area on https://www.topicbox.com/ and how the video moves from the right into the middle of the content from the left column, which would be exceedingly painful to handle well without Grid, probably requiring absolute positioning and/or float.

Wouldn't just flex ordering and wrapping do? like this: https://codepen.io/anon/pen/QRgoOR


It depends on how thoroughly the widths and heights are known. In various constrained cases, what you suggest can work, but it’s always fragile and depends on certain layout constraints being met. I do like your use of the column direction and vertical wrapping; for some reason, I had always had in mind rows, which prevents you from doing things like vertical centring of the columns relative to one another. So I never did try that combination. I think it would narrowly meet our requirements now (which includes other landing pages with somewhat different hero content), but I don’t think it would have the first iteration of the design when I started using Grid, due to greater flexibility and variation of the heights of elements.

At the least, the Grid solution is more robust. But I will downgrade my “exceedingly painful” judgement to “somewhat icky and fairly fragile”.

Thanks for also supporting my point that most cases where Grid is used can be done with Flexbox!


> My experience is that almost all of the early “CSS Grid lets you do this!” examples were either: ⓐ actually achievable with Flexbox in a non-contrived way; or ⓑ outright weird things that will seldom actually be desired, being more related to art direction than layout or similar.

The thing is once you "get" Grid you will never go back to any other layout. Here is one example (an extremely common layout: sidebar to the left stretching from top of the container to the bottom, header on top right, main in middle right and footer at the bottom right):

<style>

  section {
    display: 'grid';
    grid-template-areas:
      "sidebar header header"
      "sidebar main main"
      "sidebar footer footer";
  }
  aside {
    grid-area: sidebar;
  }
  header {
    grid-area: header;
  }
  main {
    grid-area: main;
  }
  footer {
    grid-area: footer;
  }
</style>

<section>

  <aside>Sidebar</aside>
  <header>Header</header>
  <main>Main content</main>
  <footer>Footer</footer>
</section>

Notice how I did not have to define a bunch of "col-" or "row-" or explicitly specify percentages and flex properties to each child markup element to layout my grid? If I need a completely different layout, all I need to do is change the "grid-template-areas" in section style. I can swap the "sidebar" from the left side of the page to the right side without much effort. I don't even need to touch the markup at all (which I would have to if I was using Flexbox)!

Example:

<style>

  section {
    display: 'grid';
    grid-template-areas:
      "header header sidebar"
      "main main sidebar"
      "footer footer sidebar";
  }
</style>

Flexbox feels imperative while Grid feels declarative to me. Why would I want to use Flexbox over the convenience Grid provides? Grid does everything Flexbox does and then some! With Flexbox I would have to do all the calculations myself to achieve a layout that is now set in stone. Any changes would require me to either change the markup or change the calculations in each flex element or both. Grid on the other hand can be changed declaratively! I would just need to specify my layout and the rendering engine takes care of the rest! I don't need to change the markup! After working with Grid for a few months now I have come to the realisation that I have pretty much stopped wasting time on calculating and positioning layout and fiddling with deep nested markup. I can say with conviction that no other feature has given me this level of satisfaction. Kudos to the team that conceptualised Grid! To top it all, Grid takes care of accessibility issues one would face with Flexbox. Maybe you want a Sidebar to the right for people who aren't visually challenged but with Grid you can maintain the hierarchy for visually impaired users who rely on screen readers. For them, the Sidebar would always come before the content and not after. Flexbox is heavily dependent on how you place your markup which sucks from an accessibility point of view. With Grid, the layout declaration is completely dissociated with markup order (which is very important because you don't want to be juggling with both at once while setting your layout). Flexbox is tied to markup order which means any major changes would require you to mess with the CSS styles as well as the markup. If you have deeply nested markup you are in a whole world of pain!

Just my two cents!


> The thing is once you "get" Grid you will never go back to any other layout.

In theory, I agree. Grid is nice for layouts. But in practice, you often can’t actually make that decision, due to browser support requirements. (And I’m not talking about IE11—it’s typically a little painful, but you can get your -ms-grid-* properties equivalent to your grid-* properties with some autoprefixer and a little extra work, when it’s page layout rather than auto content layout that you’re using the grid for.) To use it as an enhancement if present, yes, but it’s often not acceptable to require it. Thus, you need your Flexbox fallback anyway, and if there’s no functional difference between the two, well, why would you put the Grid implementation in? (If you look at the Topicbox hero area example I mentioned earlier you’ll see it handles the absence of Grid support nicely, falling back to the single-dimensional Flexbox layout used on smaller screens. If the Grid layout is different from the fallback Flexbox layout, my remarks do not apply, and using both is reasonable.)

I also observe that two-dimensional layouts are actually not common these days, and almost all of the ones that there are are trivially reducible to nested one-dimensional layouts.

> Flexbox is heavily dependent on how you place your markup which sucks from an accessibility point of view. With Grid, the layout declaration is completely dissociated with markup order (which is very important because you don't want to be juggling with both at once while setting your layout).

When you treat Grid like this, you’re neglecting an important part of accessibility: the DOM order is still very important, because it’s what accessibility tools use, and what things like Tab navigation works on. This is why using `order` to reorder things in Flexbox is normally a bad thing to do, and why you need to be cautious with any sort of reordering with Grid.

So in a way, I argue that Flexbox’s limitations actually tend to help you maintain sanity and accessibility, not break it. It’s not always the case, and it does mean that you often end up with a little presentational markup, but in practice that’s basically unavoidable for anything serious anyway. (I say that as one who spends way too long on keeping his markup unblemished.)


I've had the exact opposite reaction, grid is a godsend. Grid fills a very specific role that flexbox cant: two-dimensional layout. Continue to use flexbox when you only need to control things in a single dimension, but once you need to control both dimensions grid makes things so much easier.


I think grid is something graphic designers and typographers really drove. Grid layout is essentially a modernist typographic convention. Once you know it, it becomes completely logical.


As someone who's always been using InDesign and other graphic design layout principles, CSS grid is pretty much the first time CSS layout and positioning makes sense to me.


Grid gap is a killer feature for dynamic layout. It allows you to place items in a container and have them wrap dynamically when there's not enough space in the container, _with consistent spacing between the wrapped lines_.

Using raw flexbox you'd have to resort to hacks with negative margins on the container (https://stackoverflow.com/questions/30887071/margin-top-only...), which often affects layout of the container in unpredictable ways, making it less than ideal for building reusable layout abstractions.

A popular alternative is to resort to screen size media queries to set margins, but screen size doesn't always match whatever container you have to render content in, so you end up with very brittle layouts that need all their media queries adjusted when you move containers around and add elements that constrain the dimensions of the container like sidebars (or even worse, collapsible sidebars that change width dynamically).


I’ve found grid-template-areas to be a powerful way to layout my page with one fell swoop.


Using Firefoxs grid debugger is supper helpful in figuring out what is going on. I enjoyed my limited use of it.

My main question is how well it prints.


Thanks for the tip, I didn't know that exists! For anyone else who is curious: https://developer.mozilla.org/en-US/docs/Tools/Page_Inspecto...


In my experience, grid is very useful for setting up the overall layout of your page, whereas flex is well suited to the content within each segment.

For example, if you want to move your navigation/controls to the bottom of the screen on mobile devices for better ergonomics, it's far easier with grid than flex because you can specify a completely different layout at each breakpoint. With flex you often have to duplicate content in different areas of the screen, then conditionally hide/show them based on the current CSS breakpoint. This can have a negative effect on page load times, SEO, and overall complexity, as well as just being kinda gross.

Another example: imagine you have a 2x2 layout, say a sidebar and top-bar that join in the top left quadrant. Keeping ([0,0], [1,0]), and ([0,0], [0,1]) the same height and width respectively, without specifying explicit heights or widths, is very difficult without grid. It might be impossible, but I'm not that great at CSS so I'm not 100%.


For the projects I use, Flexbox gets it done 95% of the time. Just occasionally Grid is the better method.

The only thing I can think of off the top of my head is that if you're doing something programmatically and don't know how many items will appear in a grid, then Grid is better because Flexbox doesn't handle orphans well.

Some have suggested using the margin-right: auto; trick, but it doesn't always work if you have your elements even moderately styled with padding and borders and such.

If there was something like justify-content: space-between left-hanging; or justify-content space-between right-hanging; that would be ideal.


What do you use to layout your pages? Do you still use float/clear? Or do you still use tables for layout? Surely you are not trying to use Flexbox since Flexbox is really only designed for a single vertical or horizontal column of content.


I'm not sure what you are talking about, as you can do responsive grids/columns with Flexbox. E.g. Bootstrap uses flex: https://getbootstrap.com/docs/4.3/layout/grid/


That is an example of using a screwdriver to drive nails. Flexbox can be perverted to do grid layout, but it's not the right tool for the job and sooner or later you will hurt yourself.


I have the same reaction as you, not to grid though, to flexbox!

Maybe you're overthinking grid and I'm overthinking flexbox? Cause grid is really simple to me: you define a grid and then you specify which area in the grid you want each child to span.

I love it.


One issue with using use pure CSS for data table layout is if you have to add windowing/virtualized scrolling for very large tables it tends to break down (you need to know the row/column size so you can’t use breakpoints etc).


For the most part I've found flexbox to solve 90% of the pain of working with CSS.


I switched from css grid to absolute positioned layout 2 days before release and it'll take at least 2 years before I give grid another try. Support on Android is spotty.


You chose the second worst option. (The first being tables for layout).


People used tables for layout because it worked.


is there source code for this?

it's a really cool project, but in the end if there's no source code, then the post is just so much of an advert for teamworkCRM.


There’s enough technical detail about how it works that it’s useful—if you will, it’s like a patent drawing that says “this is how you can make such a thing”, and you can copy it. It’s a moderately novel implementation technique, well explained.

Besides which, there is (simplified) code provided.


[deleted]


You'll find that comments like this will attract downvotes here. Even if your perception is valid, expressing it like in these terms is something that HN doesn't tolerate. I'm not sure if there is actually a way to reframe it more constructively in this case. You might just have to grin and bear it.


That's an awful sentiment. You're essentially saying that disagreement is not welcome. Not every community needs to become a safe space. We've seen the chilling result that can have on discourse.


CSS has always been confusing to me. Every year there are a new set of "best practices" that seem to only serve to work around how CSS works (hacks, basically). Now we have CSS grid, which looks like tables, which were supposed to be bad (although I never understood why).

If CSS can't do the layouts we need without a bunch of hacks and bashing your head against the table, why is it still a thing?


HTML tables were not bad. They are fine when used for their appropriate purpose.

Anyway the pure CSS equivalent to tables is display:table, it is not CSS grid. CSS grid behaves quite different from tables. For example CSS grid can adjust the number of columns to the available space. This makes sense for say textual columns but would not make sense for a data table.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: