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.
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)
.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.)
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.)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
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.
.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;
}An interesting thing you can do with grid is align the tracks.
I wrote about this here:
There is also fit-content:
E.g: grid-template-columns: fit-content(150px) …
Tracks is a grid term for rows or columns, as it works in both dimensions.
As you can see, the middle element is not centered.
https://jsfiddle.net/Lah5g3vb/
Changes:
- each col is now 1fr (3 cols, 33% each)
- the child elements align inside the col using `justify-self: start | center | end`
See: https://jsfiddle.net/e0un5Lxk/
The middle content is unnecessarily wrapped into two lines, even though there's plenty of space available.
But this does not keep the center col exactly centered, but it does allow the content to take the free white space and then wrap when needed.
In your original post with Swift, what happens?
I am not familiar with auto layout so I do not know the exact behaviour vs CSS. Do you have a few screen shots of how it would handle different sized content?
Regarding AutoLayout: the six constraints from my original comment, don't say anything about the relationship between the left/middle/right items, so they will simply overlap if there isn't enough space. This can be remedied by adding two extra constraints:
1. left.right < middle.left
2. middle.right < right.left
It's just a bunch of equations. No weird tricks, no special cases, no hacks. You describe what you want with equations, and the solver spits out the solution.
Auto layout does sound neat.
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