Friday, May 10, 2013

While writing my guide to hexagonal grids I ran into some html+css+js issues that I need to spend more time learning about. Here are a few things that are on my mind.

Responsive layout

I got a little frustrated with the layout options I had in HTML+CSS. I want to write HTML one way, then use CSS media queries to reformat the layout to work with wide desktop, narrow desktop, and mobile widths.

For some of my previous articles, I used floats. It works nicely in the simple case.

narrow
A
B
wide
A
B

However, for this article I often found that the best layout for narrow would be to put diagram B in the middle of the text A+C:

narrow
A
B
C
wide
A
C
B

But now the diagram is aligned with C; I want it to be aligned with A. I don’t know the best way to do this. I ended up using three different patterns.

  1. When A and C were taller than B, I used absolute positioning to take B out of the flow and line it up with A:
    narrow
    A
    B
    C
    wide
    A
    C
    B
  2. When A and C were shorter than B, I didn’t have a good solution, so I moved C’s content into A’s and used floats. This hurt the layout on narrow devices, where it ended up in the wrong order:
    narrow
    A
    C
    B
    wide
    A
    C
    B
  3. Occasionally I just wanted things to be side by side but not floating, so that I could get this:
    narrow
    A
    B
    C
    wide
    A
    B
    C

In the end I wasn't happy with the different CSS rules that I used, but they seem to work. I could have reformatted with Javascript but kept hoping CSS alone would do the trick. Flex boxes don't seem to help here (unless I'm missing something). It's possible CSS Regions would do what I need; it's not widely supported yet. I'm a novice with floats; it's quite possible with some cleverness I could've gotten what I wanted.

Update: [2013-05-29] With help from Jimminy on Friendfeed, I was able to simplify all of the above into one set of rules that handles all three cases. Anything that will be potentially in two columns goes into a div with clear:both. The left column elements are all float:left;clear:left. The right column elements are all float:right;clear:right. On a narrow browser, the containing div will be one column wide, so all the floats are in order. On a wide browser, the containing div will be two columns wide, and the left/right floating elements go in the left and right columns. Much simpler!

Browser compatibility

Some things that bit me:

  1. In WebKit I can use SVG’s baseline alignment to vertically center text. This becomes very handy when I want to write generic code that places text no matter what size the hexagons or what size the text. However in Gecko, I can’t use this. Instead I need to adjust the text position downwards, which depends on the size of the text. But I don’t know the size of the text in the generic code because it’s set later by the CSS on the page. So I fudged it. Also see Nelson Minar’s post on this topic.

  2. In WebKit I can use the DOM node’s .clientWidth and .clientHeight to get the size of the SVG. I then use that to center the diagram in the SVG frame. In Gecko these were returning 0, so I ended up reading the width= and height= attributes of the SVG instead.

Performance

I wrote the animations in a straightforward way but there are way too many animations running at once. I have a single toggle for the orientation (pointy top vs flat top) of all the diagrams on the page. When you change the orientation it rebuilds all of the diagrams. This is slow.

I guess I was hoping requestAnimationFrame would magically solve everything. But it doesn’t. It doesn’t know where the output will be on screen, and therefore whether the code needs to be called. So I need to do that. I need to look at each diagram, figure out whether it’s on screen, and decide whether to change it immediately or to delay it. But if I delay it, and you toggle it back, then I have stacked timer handlers to deal with. So I haven’t finished implementing this.

A simpler approach would be for me to not link the orientations together, so you’d separately toggle it for each section of the page.

Touch screens

Although I did a little bit of testing on touch screens, I didn’t spend enough time getting the interactions to work well with touch events. Instead I’m (mostly) relying on the emulation of mouse clicks. There’s a ~300ms delay for this emulation though, so it doesn’t feel smooth. There’s a library to fix this but I haven’t tried it. It’d also be nice on touch screens to tap and drag to select multiple hexagons, but I didn't implement click and drag either so I'm consistent in my not supporting the nicer UI.

Labels:

0 comments: