Thursday, August 12, 2021

old dogs, new tricks: css grid for block schedules (vs absolute positioning and/or flexbox)

Usual disclaimer: In some ways I'm not a great tech blogger because my writing voice is more "well this is what worked for me" and sometimes even "except for this bit which I couldn't quite get where I wanted it." So definitely a bit of seeing how the sausages are made today.

Anyway. 2021's delayed Porchfest season (after 2020's year of cancellations) is approaching - albeit with a little more caution thanks to the Delta variant of COVID.

JP Porchfest, the site that got me starting all my endeavours on porchfest websites, is being run by a new group. One innovation they had (partially as a form of crowd control) is to have the event across both days of the weekend.

You never quite realize how assumptions baked into a system - e.g. "this event is just a one day stretch of time" - until they are challenged and you have to fiddle with code all over the place.

So I've had to scramble and update a lot of stuff. In some cases I've been able to fix some things that were bothering me. (I started doing these websites in 2014, with several generations of code, but sometimes 2014-era technique slips through and calls out to be replaced.) 

The block schedule has always been a challenging thing to make - in many ways having blocks hold positions on a page controlled by times and not their own natural flow goes against the way HTML does layout. Historically I  would do with a big heap of position: absolute divs. My first pass at updating the page to be two-day aware looked like this:


You can see the problem this approach always had, which is that with fixed height rows, performers with long names just didn't fit! Also my approach meant that porches were displayed even if there weren't any performances on that day. To fix both, I would have to go back and adjust the heights and positions of things manually (Earlier I worked up some nested DOM structures so I could read the computed heights) but since changes of heights in earlier rows effects positions of all lower rows... that is ugly capital Ugh!

(I think in previous years I also messed with techniques to experimentally shrink the font-size of any given entry so the name would fit in whatever box it was given... again, super hack-y even by my standards)

I had an idea to try to use flexbox but while that neatly solved the problem of having rows take up their natural height based on the content, I couldn't get the arbitrary positioning needed to represent a performances placement in time without manually setting each row item's height to the tallest object, thus somewhat defeating the purpose!

So my attention turned to css-grid, which is - kind of - a natural candidate for this sort of thing. I renewed my knowledge via CSS Grid Garden. It took a lot of work to rebuild the page, but my first pass at a usable result came out very promisingly:


Since different Porchfests have different run times I have to set up the grid dynamically, something like 

holder.style.gridTemplateColumns = `30px 200px repeat(${MINUTECOUNT}, 1fr)`;

Which holds space for the porchnumber, the porchname, and the breaks the rest up by however many minutes we have.

You can see it's a much more efficient use of space - especially since it's a lot easier to leave out porches that aren't hosting that day. I still don't have a perfect answer for performers like "DonYoyo" doing a 15 minute set. Also things got a little hacky as I put in the dotted line time bars showing each hour... but I can't let perfectionism stop me from getting the rest of the site done. I may swing back to figure out if I was doing something wrong or if there are just some quirks I have to live with (the "1/-1" for the rows of the separators just wasn't quite making them reach all the way to the bottom)

CSS Grid syntax feels very weird to me, like it's drawing from a print tradition or something... like how everything counts from 1 not 0, and you specify what column a thing stops short of at rather than the width or even which is the last column it occupies (so to take up the first 3 columns of 5 column layout it would be the shortcut "grid-column: 1/4", which is also weird because it looks like a fraction!)

Oh also, it's amazing how much more eloquent javascript is now that is ` ${variables} in template strings` and various map/filter/reduce functions, and fat-arrow functions. 

No comments:

Post a Comment