Hacker News new | ask | show | jobs
by mitemte 662 days ago
Can you provide some examples of modern layout systems? I’d be curious to see what’s on offer.

I have experience with various iterations of UIKit’s auto layout, Yoga, as well as CSS and some Swift UI. I’ve found CSS to be considerably easier to work with, particularly when using flexbox and grid.

1 comments

Ok, then please implement the following in CSS:

   Outer
   +---------------------------------+
   |                                 |
   | Left        Middle        Right |
   |                                 |
   +---------------------------------+
Everything should be vertically centered. Left should stick to the "left" of the outer div, "middle" should be centered, "right" should stick to the right. Left/middle/right can have different widths and heights.

In AutoLayout this is achieved by 6 constraints:

- left.left = outer.left

- left.centerY = outer.centerY

- middle.centerX = outer.centerX

- middle.centerY = outer.centerY

- right.right = outer.right

- right.centerY = outer.centerY

I'd like to see how you implement it in CSS. (note: extra wrapper divs are not allowed)

Assuming your div has a class of outer it’s:

.outer { display: flex; justify-content: space-between; align-items: center; }

…and that’s it. (This is assuming your items are of equal width of course. It gets a little bit more complicated if not.)

I've literally told you the items can be of arbitrary width and height. `space-between` won't keep the middle item centered.
Chrome just added CSS Anchor Positioning this year. The other browsers also expressed interest in implementing it, with Firefox having announced an Intent to Implement. The feature would likely be available on all major browsers sometime next year.

So here's how your example would work using it:

.outer { width: 100%; height: 400px; background: aliceblue; anchor-name: --outer; }

.left { width: 100px; height: 100px; background: white; position: absolute; position-anchor: --outer; left: anchor(left); align-self: anchor-center; }

.center { width: 150px; height: 200px; background: pink; position: absolute; position-anchor: --outer; justify-self: anchor-center; align-self: anchor-center; }

.right { width: 160px; height: 150px; background: gray; position: absolute; position-anchor: --outer; right: anchor(right); align-self: anchor-center; }

Source: https://developer.chrome.com/blog/anchor-positioning-api

Cool! Is it going to be the sixth or the seventh positioning system in CSS?
.parent { display: grid; grid-template-columns: 50px 200px 80px; justify-content: space-between; align-items: center; }

An interesting thing you can do with grid is align the tracks.

I wrote about this here:

https://cssprinciples.com/3/grid/#justify-and-align

No. You're hardcoding the item widths in `grid-template-columns`. The left/middle/right items should be self-sizing. E.g. consider three divs with arbitrary text content.
Grid allows minmax(a, b) to specify the bounds of tracks. Possible values can be the remaining free space in the parent (fr), or the size of the content in the child.

There is also fit-content:

E.g: grid-template-columns: fit-content(150px) …

Sorry, but I don't understand what you're describing. Can you maybe show it in jsfiddle?
I am just saying the columns of the grid can be dynamically sized depending on their contents.

Tracks is a grid term for rows or columns, as it works in both dimensions.

Either put left, right as absolute (like the following) and leave middle in the flex, or do the opposite. One may decide which option to use based on whether the centre or the left/right is more semantically important in the layout.

We did have to use some CSS "tricks" (transform for absolute centring), but once you've learnt those then CSS is indeed quite sane.

  outer {
          flex-direction: row;
          justify-content: center;
          align-items: center; }
  left, right {
          position: absolute;
          top: 50%;
          transform: translateY(-50%); }
  left {
          left: 0; }
  right {
          right: 0; }
(This kind of layout, which is common in eg top nav bars, is slightly deceptive. robin_reala's solution does not conform to requirements that left and right can be different widths, which would cause middle to be not centred under simple justify-content: space-between.)
Yes, this is the correct solution.

Which underlines the original point, that CSS is a hodgepodge of different ideas with no overarching system behind them. A simple task like this needed 3 different positioning systems:

1. flexbox for positioning the middle item

2. absolute positioning for left/right

3. and the translateY(-50%) trick for vertically positioning the absolute positioned items

Touché. Indeed, CSS forces one to recognise layouts that may not conform to a layout 'flow' in boxes.

In its defence, I suppose recognising this is important, as to make potential box overlaps explicit (which is typically unwanted).

CSS also handles a whole lot of things other than layout, which I'm not well informed of layout constraint systems being able to handle. Being a hodgepodge is an advantage, comparable to how its a great advantage that one can invoke any hodgepodge systems task from bash, as one single tool.

Maybe something like this, which relies solely on flex box for layout.

    .outer { 
      display: flex;
      justify-content: space-between;
      align-items: center;
    }

    .left {
      flex: 1;
      display: flex;
      justify-content: flex-start;
    }

    .middle {
      flex: 1;
      display: flex;
      justify-content: center;
    }

    .right {
      flex: 1;
      display: flex;
      justify-content: flex-end;
    }
Wrong. `flex: 1` will cause the items to have a max-width of 1/3rd the container width. E.g. if the left and right items are small icons, and the middle one is a longer text, then the text will be forced to wrap into multiple lines as soon as it tries to grow beyond 1/3rd of the available space, even though there's tons of wasted space on the left/right.
In this specific example, I am pretty sure margin-right: auto on left and margin-left: auto on right in a flex-box does what you want.
Wrong. The middle item will be misaligned from the center if "left" and "right" have different widths: https://jsfiddle.net/hxe8pcuf/
Does anybody know how you'd solve this in tex (not latex, tex) or in some other constraints-based layout system like Cassowary?