21 comments

[ 2.8 ms ] story [ 41.4 ms ] thread
Nice margin notes trick:

  float: right;
  margin-right: -12em;
Author here—it is from Tufte CSS. I have a blog post [1] about how floats work. It is a nice example of there being unintuitive and also more-intuitive ways to achieve things in CSS. These days I believe CSS Anchor Positioning provides a simpler way to do this, but I haven't used it yet.

[1]: https://pavpanchekha.com/blog/css-floats.html

The problem with a constraint system is that it would likely be even more subject to performance problems than the current setup.

IMO what CSS layout really needs is:

1. A "proportion of available space" unit. That is, something like the fr unit in CSS grid except applicable to the width/height properties so it can be used in all layout modes and without an implying content-based minimum size (like fr does).

2. A new "display: stack" (name provisional) layout mode that simply stacks boxes one after the other like "display: block" but that works in both axes, and doesn't have quirks of block layout (margin-collapsing, floats, inline-block splitting, etc).

When combining 1 and 2 you'd have a much more intutive layout system that would still give you most of the power of Flexbox and could be implemented with much better performance.

(and you'd still be able to use the existing layout modes if/when you needed to extra power)

I'm not convinced about the "edge case" at all. CSS made it an edge case for no reason at all, and made a silly default out of it.

If the box isn't big enough to contain center-aligned text, of course it should spill on both sides, because it's both expected and consistent.

And now the author pretends "we left-align text and spill on the right" as the only possible default behaviour that somehow makes constraints impossible/extremely difficult.

If you don't make assumptions and weird defaults in your system, you don't have to fight them and make weird workarounds.

Author here. This specific quirk of CSS is minor, and probably if CSS didn't have this quirk it'd be fine. But I'd guess that you've at least once in your life been on your phone and been browsing a website which used a really long word (or a really long line of code!) in centered text (maybe a heading) and you've scrolled right to read the whole thing. Are you sure your website doesn't have such a thing, if you have centered text somewhere?

So, yes, CSS could have fewer edge cases and workarounds---what I refer to in the post as less implicit knowledge---and then it would be simpler. But the resulting layouts would probably be worse. And a radical simplification like a constraint system would probably be even simpler and the results (I assert) would be even worse. It's fine to want a better life for browser developers, but I don't think it's unthinkable for CSS to create new edge cases and sometimes-surprising behavior if it also results in, typically, better outcomes.

> But with constraint-based systems, the layout might be literally under- or over-determined, in the sense that there might be more than one, or less than one, layouts that satisfy your rules.

This is under the "what's wrong" section but it doesn't actually say what's wrong.

Obviously if over-specified, the extra constraints can't be followed which wouldn't be intuitive (and... css does this constantly, so it doesn't seem relevant). But surely the system could just do one of them and alert the developer which constraints can't be followed?

And for under-specification, it could use 0. Nobody's going to write a specification and then publish a site without looking at it once.

And actually, can't under/over specified constraints be statically checked? Doesn't SolveSpace do this?

Author here. The problem isn't the technical challenge of writing a constraint solver. It's making sure that the resulting layout looks good, despite contradictory guidance from the designer.

Yes, a constraint solver can figure out which constraints it's violating. And for under-specification, it can produce a layout that satisfies the constraints. But the layout the constraint-solver chooses might be really bad—if all the text is placed at 0,0 the result is unreadable. And over-specified constraints might occur for some user on some weird device after deployment, when there's no developer to respond to errors.

Determining whether a set of constraints could be over- or under-specified for some set of parameters is computationally very challenging (this is what SAT and SMT solvers do, basically). But besides the computational challenge, I think it is practically very challenging—this is drawing off my experience doing this for four years—to write non-conflicting constraints for real-world designs. How would you write constraints for text wrapping around a figure? For mixed-font text lining up nicely?

The problem is that CSS is serving multiple masters. It is specifying how the designer is wanting a page to be laid out while doing do in a way that conforms to the way the receiver wants it to be laid out.

I think there is an opportunity for pages to have regions of priority. I thing there would be merit in something where client devices have freedom to decide some parts of the layout but others are ridgidly controlled by designers.

You can kind of do this already with CSS with absolute and relative positioning and calc() for control and flex for, well, flexibility. It's not in a form that particularly facilitates it though. I'd like a better ability to choose whether elements to push the bounds of their containers or whether containers squeeze their content, and what to do when in conflict. scrolling, clipping, exceeding bounds, scaling to fit are all options.

Having read https://every-layout.dev (no affiliation), I cannot help but use CSS as a constraint system (ish).

My site for example, uses four "structural" elements - "the center", "the stack", "the box", and "the cluster".

That's maybe 50 lines of CSS controlling layout of the whole site, in concert with a proportional grid, much like how I do with print layouts. Except, with CSS combinators, flexbox, and semantic HTML. I don't use a "reset" CSS, nor do I use media queries.

Have a look-see. It's entirely hand-rolled CSS:

https://www.evalapply.org/static/css/style.css

nb. I'm mainly a devops/backend person. Any expert critique on said CSS is welcome. (Also site accessibility is a long-pending item... pointers there are welcome too.)

The Python library "enaml", which is kind of wrapper around QT, has a constraint-based layout engine: I think it's successful, I made a fairly complicated GUI and it didn't have any performance issues. Of course I was only developing for desktop...
Nitpick for the author: you've got a few &utm_source= strings in your links, which should probably point at your own site, or be removed.
I love auto-layout in iOS, which is, indeed, a constraint system. It is not easy to get the hang of it, but once one does, it is extremely powerful and delightful to use.
I legitimately find myself wishing I had access to this any time I have to build UI in other languages.

I remember being so skeptical and annoyed when first using it but over the years I became sold on it. It’s the only system I’ve used where I could come back years down the road and figuring out the layout was still straightforward enough debugging wise.

Tailwind utilities related to flexbox/grid solved most of layout issues for me. Usually it's flex-1/flex-none to mark dynamic/static parts and gaps to separate elements. Constraint based systems usually require more input data to maintain.
Grid Style Sheets / GSS was an implementation of this idea. https://gss.github.io/guides/ccss

I saw was because I do not think anyone has used or maintained it since the company behind went belly up. But the code is still out there as open source, probably can be learned from.

Disclaimer: I used to contract for them, but in other areas.

Hello Jon! This is Yarik. Cool to see you doing all this machine learning work these days.
If I am to provide a summary of why layout shouldnt be linear constraints, is that it can't faithfully represent content overflowing onto multiple lines. I.e. it's inherently one dimensional. I.e. you can't really have a layout that adaprts to the screen size without creating a lot of separate breakpoints. This is a big limitation, that for example flexbox doesnt have. When I left Grid i immediately went and reproduced a lot of stuff we've been doing in (new then) flexbox layout engine, and i was like: Oh my god, this is so much more powerful.
Reminds me of Java's GridBagLayout layout manager, which was practically unpredictable in actual use.
Apple's native SwiftUI framework and Google's Jetpack Compose framework stumbled upon basically the same layout system, "Constraints down, sizes up":

1. Proposal: The parent component proposes a size/constraints to the child

2. Measurement: The child component picks its own size based on those constraints

3. Placement: The parent component then positions the child in its coordinate space

It's all done in a single pass. It scales great. It fits great with React-like reactive UI frameworks. (SwiftUI and Jetpack Compose are based on React.)

This is what CSS needs.