Tether elements to each other with CSS anchor positioning
developer.chrome.com
developer.chrome.com
The worst is when you get angry and start blaming the frog for its lies. As if it's the frog's fault...
<div style=”text-align: center;”>
<span>centered element</span>
</div> <span style="display:inline-block">centered element</span>
But in general <center> still cannot be 100% expressed by CSS means.The CSS property display:table gives you the same layout power as tables.
`place-self` still requires the parent to be a flex-box container, though. You can't just apply it to an arbitrary element to make it center in its parent.
`place-self` is just shorthand for setting both `align-self` and `justify-self` in a single proeprty - I don't see how this is necessarily an improvement: CSS is already (unfortunately, necessarily) confusing at it is, so adding a literally redundant CSS property with a distinct name is not going to reduce confusion nor make CSS any more accessible.
CSS's shorthand properties work best when the shorthand version actually aids comprehension, rather than making you think: for example, `border: <width> <style> <color>;` and `margin: <top> <right> <bottom> <left>;` are great examples of how they should be: either because each parameter is unambiguously typed (in `border`'s case: widths, border-style and colors are very distinct) or uniformly-typed but follow a familiar pattern (e.g. `margin:`'s parameters are all length-values but are in a clockwise sequence) - this is not something we see in some of the more modern shorthand properties like `flex` and `box-shadow` where you need to have pre-memorized which parameter corresponds to each longhand property, e.g. it's non-obvious that the `2` in `flex: 1 2 3px` is for `flex-grow` - or that the `3px` in `box-shadow: 1px 2px 3px 4px rgba(0,0,0,0.2);` is for `blur-radius` and not `spread-radius`.
> It’s good to see that the problem of anchoring tooltips is progressing through this process!
I'm also strongly in favour of this CSS feature, it's a long-time coming - BUUUUT I also really would have liked some browser-native tooltip/title feature that allows for rich-content without resorting to hacks like `foo[title]::after { position: absolute; content: attr(title); etc }`
You can with grid-first.
With the proviso that third party components may not work (which is fine, third party components are usually very low quality). I'd recommend, right after your existing:
*,
*:before,
*:after {
box-sizing: border-box;
}
Adding: div {
display: grid;
}
You can now remove:- all margins (there's just padding and gap now)
- margin auto centering hacks
- clearfix hacks
- translateY -50% hacks
- a billion wrappers around every UI element (per all those low quality third party components, particularly common in the react space which seems to have a culture of "add divs until it looks right")
plus a bunch of other code.
In 99% of cases, using grid-first, there will be a 1:1 match of element to UI - getting around the div-soup of older web apps.
The app I'm developing now is 1:1 with the exception of rounded gradient borders, which still needs a hack.
I don't use CSS Reset techniques: don't try to fight the browser.
> div { display: grid; }
I'm concerned this will have a nontrivial impact on browser layout performance. Existing browser layout engines are heavily optimized for flow/block layout, but defaulting every div to grid breaks that major assumption all the browser-makers made and... for what gain? I actually don't want every div to potentially be a grid layout container by default.
> You can now remove $things:
I don't use any of those tricks/hacks anyway - and clearfix hasn't been relevant since IE8 came out.
> rounded gradient borders
Just use border-radius combined with `border-image: some-gradient-function()`. No hacks or tricks required.
>which still needs a hack
Optimising for existing behavior reminds me of when people didn't want to use async/await as V8 'wasn't optimised' for it. await never felt slow in their apps anyway, but now it's similar fast to what callbacks were. Skate to where the puck going to be.
> for what gain? I don't use any of those tricks/hacks anyway
OK. Everyone else does but maybe you're the exception.
> For rounded gradient borders... just use border-radius combined with `border-image: some-gradient-function()`. No hacks or tricks required.
Are you sure? https://stackoverflow.com/questions/51496204/border-gradient... - judging by the views on that question, if you have a codepen there's at least 42,000 people who'd love to see, it my understanding is that the W3C spec says it shouldn't work.
Probably obvious, you sound like you know what you're doing but: adding additional elements, pseudoelements etc counts as hacks.
Here's border-radius combined with `border-image: some-gradient-function()`:
Layout and paint performance is pretty low stakes. Unless you’re doing a lot of painting, or your demographic is surprising, your users are going to be fine.
I've experienced this with iOS Safari. I was experimenting with different layout methods, and at one point a display:grid didn't get deleted, and some days later when I was testing with Safari it was taking at least half a second to render a page. I'm talking 5 paragraphs of text, possibly with subgrid I was experimenting with, nothing crazy. I had no idea CSS could ever get that so slow and I thought it had to be something with React, and it took way longer than it should have to narrow it down to that single property.
(Aside: another technology in the thankfully small know everything before you can do anything set is gradle, a popular build tool in the Java universe. These tools are capable, but quite demanding of the user. Git may also qualify.)
Prior to CSS, it used to be that literally anyone could (and should!) write HTML: web-pages were just simple documents (by design) using only paragraph-flow content with inline objects (like images, Java applets, ActiveX on Windows), and appearance was directly set inline with <font>, <small>, etc. This is fine for web-page documents, but not web-page applications, and it turns out that defining a layout system for a medium as flexible as a web-browser viewport is very, very hard.
It's the same thing with desktop software: previously it was perfectly acceptable for a VB6 application to consist entirely of fixed-size windows with controls placed at fixed-positions, with no resize logic - or to handle re-flow when the text changes, or high-DPI for that matters. Users, today, have much higher expectations, and now it's now basically impossible for a "citizen programmer" to meet the expectations of normal users, and I feel this is a bad trend for everyone: we all love to grimmace at a giant Excel VBA macro doing 20 things at once that still somehow works, but the person or company that actually has that macro really is better-off than someone without it.
-------
The complex layout systems in modern UI frameworks (like WPF/XAML, Cocoa Touch, etc) are converging with CSS (or vice-versa, depending on your experience) in their expressiveness - which necessitates complete abstraction-away from fixed-layout WYSIWYG systems that were the key component of the democratization of desktop computers since the late-1980s, and while HTML was never WYSIWYG an average person could still immediately understand what `<font color="">` did - and could immediately see how their fixed-layout VBA Form would look when it runs.
Unfortunately I don't have a solution to this problem: citizen-programmers are going to need a WYSIWYG fixed-layout design tool, but such a tool is fundamentally incompatible with end-user expectations - and essential things like accessibility and device-portability. I guess we'll be stuck with proprietary, half-arsed, "low-code"/"no-code" tools for a long while.
Supporting all kinds of screen sizes is a dumb idea but we are stuck with it. If you also want to support different languages the screen is mostly empty with logograms and the languageswithgiantwords stick out of the boxes. We are pretty lucky English is a reasonable middle ground.
No, it isn't a dumb idea.
> If you also want to support different languages the screen is mostly empty with logograms and the languageswithgiantwords stick out of the boxes.
...what you're describing only happens if a page/screen/layout is designed without reflow in-mind. Otherwise it will look fine and natural. Every layout system that supports text reflow will support forced hyphenation for dealing with zeverylongcompoundwords in German and other languages.
One could certainly argue that there is no need for such things and that an interface can be (or should be?) equally usable on any kind of screen. To me it stops being art at that point. It reminds me of The Night watch, they "reflow" the painting by cutting parts of. People thought one can just do that. Or perhaps they showed it's not a problem, I dunno. It's not for me.
Even the supposedly favorable case of having a flexbox container with place-self: center in many cases still does not correctly center the child element. For example, a label inside a button. The label is typography, which means it has its own vertical spacing (line-height, top-cap, bottom margin) that may be unevenly distributed. Fixable, but now you're into the 3rd rabbit hole, just to center something.
> margin: 0 auto;
would be the way to go for centering divs...
No luck for elements of unspecified widths, or for inline elements.
It's crazy how many attempts at this have been done over the years. And it worked great in Adobe Flex, back in 2009.
Thanks!
div {
width:max-content;
margin:*;
}
is enough to place block in the middle of its container (vertically and horizontally), see: https://terrainformatica.com/2018/12/11/10-years-of-flexboxi...That is one of our biggest layout PITAs, is the slippery slope of "sticky the table header" ... "and the filtering controls above it" ... "and the page header as well", and these are all across different levels of the DOM / component tree.
We currently solve it with React portals, which lets elements in the component tree "promote up" their localized content to the single/top-level-stickied div, so that within that div they can all flow after each other & not overlap.
- parent div
-- 1st child div, everything that is "stickied" to the top of the screen (really a tree of react components like the header + filters + table actions)
-- 2nd child div, the table itself with a single position: sticky header row
The portal trick/approach is that technically the table is rendered by some leaf-ish component in the 1st child's component tree, but once the leaf components knows "hey I'm the leaf", it uses a portal to push it's content to the 2nd top-level child, which gets it stuck below everything in the 1st child.
It sounds kind of elaborate, but it lets everything in the top div get correctly dynamically sized without any hard-coded offset hacks.
I've been using `thead > tr > * { position: sticky; }` just fine for years, with filtering controls within `<th>`. Don't forget to also specify `scroll-margin:` though, as that's how you get `position: sticky` to play-nice with other potentially-overlapping elements.
header {
position: sticky;
anchor-name: --header;
top: 0;
}
.controls {
position: sticky;
anchor-scroll: --header;
anchor-name: --controls;
top: anchor(--header bottom);
}
th {
position: sticky;
anchor-scroll: --controls;
top: anchor(--controls bottom);
}
Should work, but 'stickiness' is not taken into account in the current build. Not sure why the anchor names are global instead of following the normal cascade. you could just have: .sticky {
position: sticky;
anchor-scroll: --sticky;
top: anchor(--sticky bottom, 0);
anchor-name: --sticky;
}
And .sticky children would stick to the bottom of their .sticky ancestors. As it is it still seems like most practical use cases will wind up needing JS to find and then name the position-anchor.I think it's confusing to introduce an HTML attribute named "anchor" that has nothing to do with HTML anchors.
eg
"Use anchor positioning to tether an element to multiple anchors" https://twitter.com/jh3yy/status/1628127228763537409
Here is what we've got in 10+ tooltip providing experience in Sciter[1] ...
Declarative tooltips support:
<div title="some text" />
<div titleid="dom-element-id" />
<div tooltip="<b>some html goes here</b>" />
Dynamic support, on demand, event handler: element.ontooltiprequest = function(evt) {
evt.relatedTarget = ... some dome element reference ...
}
Dynamic, explicit popup show: anchorEl.popup(popupEl, {anchorPos:..., popupPos:...});
anchorEl.popup(<div>some JSX expr</div>, {anchorPos:..., popupPos:...});
Popups (tooltips included) are shown as out-of-canvas elements - separate desktop windows, that's the must for desktop UI. Check this: https://terrainformatica.com/w3/sciter-tooltip.pngSo far these APIs appear as complete, I do not have other tooltip related requests last 5 or so years.
And finally CSS styling:
anchorselector > popup[role="tooltip"] {
...
}
[1] https://sciter.composition:popup is accompanied with the pair of anchor-position:1..9 and popup-position:1..9 props. For the meaning of these numbers see NUMPAD keys on keyboard. They define attachment of popup to the anchor.
anchor-position:1; popup-position:7; means border-box bottom-left corner of anchor corresponds to top-left margin box corner of popup. That positioning schema defines position of the popup relative to the anchor.
Maybe this is just as simple as it can get? Either way, avoiding a large amount of quite expensive JS is promising. Looking forward to seeing how this goes. Would love to rip out floating ui dependency.
The complexity comes later in the article when they talk about handling details and oddities. Like `position-fallback`.
Again, maybe this is just as simple as it gets since it's just a hard problem. I really would love a CSS-only solution to this. Use cases are everywhere, and I certainly don't have any better ideas.
For years I've been working on a programming language for UI designers, and this was one of the stumbling blocks for me. It's definitely a hard problem.
My solution was to enforce unique names for every element, and then you could use a simple syntax for describing positioning constraints between them. For example:
BlueSquare {
width: 100px
height: 100px
top: 0px
left: 0px
}
RedSquare {
width: 100px
height: 100px
top: @BlueSquare.bottom + 10px
left: @BlueSquare.right + 10px
}
This code would anchor the red square to the bottom/right of the blue square, with a 10px spacing between the two. Super simple! Far more difficult to implement a backend that satisfies this of course, which is why I haven't made much progress lol.2: https://slint-ui.com/releases/0.3.5/docs/rust/slint/docs/lan...
.BlueSquare {
width: 100px;
height: 100px;
top: 0px;
left: 0px;
anchor-name: --BlueSquare;
}
.RedSquare {
width: 100px;
height: 100px;
top: calc(anchor(--BlueSquare bottom) + 10px);
left: calc(anchor(--BlueSquare right) + 10px);
}
https://jsfiddle.net/kbqua1te/We already kind of did that with grid I guess. It feels like one step closer to imperative code in CSS rather than declarative, but I'll take it over JS to achieve this effect.
I would expect there are frameworks out there using “anchor” as a custom attribute that this would break.
Changing the CSS spec is all well and good, but I’d like a slower more considered approach to the HTML spec.
```
.target {
name: myname
}.tooltip: {
left: var(myname.left),
bottom: calc(var(myname.top)-20px)
}```
What's hard about exposing some element properties in var()? Instead of just making specific APIs all the time.
.target {
anchor-name: --myname;
}
.tooltip {
left: anchor(--myname left);
bottom: calc(anchor(--myname top) - 20px);
}
https://jsfiddle.net/3rasnhyp/Can’t wait to see CSS anchoring.
I think it is important for Chrome to keep on innovating, but the community should call them out for assuming a monopolistic position.
It looks like less of a Chrome thing and more of an Edge thing? The Intent to Prototype [1] links to an Edge explainer [2] with Microsoft authors. It doesn't look like anyone has asked Mozilla for a position yet [3] but I expect if they get positive signals from web developers (us!) that will be soon.
[1] https://groups.google.com/a/chromium.org/g/blink-dev/c/vsPdd...
[2] https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/...
[3] https://github.com/mozilla/standards-positions/issues?q=anch...
I've been doing CSS long enough to know that to get things work you often have to work with what you have and that means wrapping things inside (otherwise) redundant containers, etc.
Using a polyfill is less than ideal, but at least I have control over including this. And, it says it is under development, so I didn't even want to use that.
But, asking my users to enable a browser flag? That's a non-starter.
I'll file this under something interesting to revisit in a year or two.
> I'll file this under something interesting to revisit in a year or two.
Correct. However things are moving fast so certain new features become widely available within months.
Unless you need to support iOS... In which case, wait a few years because we can't have the web platform being too effective compared to apps...
But Web Push requires changes from the whole browser, perhaps minor changes to the OS, and probably a whole server side implementation.
And with all that cross-team effort going on, it's very easy for management to deprioritize it.
That's fine to do if you're only interested in "is this a thing I can use now" (no, not yet). But if you care about how the feature is designed and are worried that they might get it wrong, now is the time to read the proposal and speak up!