Skip to content

[CSS Anchored Positioning] KISS ideas #576

Open
@ddamato

Description

@ddamato

Hi folks, I just reviewed the spec and my knee-jerk reaction is that we're introducing a lot of additional terms into the ecosystem and I wonder if we could leverage things we already have to achieve similar results.

Today

We already have a quick & dirty approach to creating flyouts using CSS techniques today.

.parent {
  position: relative;
}

.child {
  position: absolute;
}

This allows us to position the .child relative to the .parent, either by using top / left / right / bottom or transform properties. We can also use margin to help with offsets.

There's two problems with the above approach:

  1. The .child could be visually obscured (ie. clipped) when an ancestor has overflow: hidden; applied.
  2. The .child should have the possibility of repositioning in the event clipping may occur.

Possibilities

Note: I'm not tied to the names I'm suggesting; just the concepts.

I think the first point is possibly the more straight-forward solve. We need a way to identify when an element should not clip. The greater challenge is if it should ever clip. I can imagine scenarios where we might want a flyout to be visible in one ancestor but clip in another. For this perhaps we might need a new overflow value.

.ancestor {
  overflow: static;
}

Which would mean only apply overflow rules only to static elements, not elements with something like position: absolute positioning which would allow them to flow outside of this ancestor. This would allow other ancestors to still use overflow: hidden; for expected clipping behavior. This might not be the best name for the value since I think I would like to see position: relative; elements also clip as explained below.

For the second point, I'd like to consider the way that position: sticky; behaves as a hybrid. Here's the MDN description:

Sticky positioning can be thought of as a hybrid of relative and fixed positioning when it nearest scrolling ancestor is viewport. A stickily positioned element is treated as relatively positioned until it crosses a specified threshold, at which point it is treated as fixed until it reaches the boundary of its parent.

So, perhaps a flyout element could be positioned in its preferred spot (using top / left / right / bottom etc) and then change when criteria are met. Remember from above we want to allow clipping when expected so this might also be informed by the new overflow value.

.ancestor {
  overflow-y: static;
}

.parent {
  position: relative;
}

.child {
  /* This doesn't say this is the anchor but it is positioned using an "anchor"; the .parent above */
  position: anchor;
  /* Makes the child appear visually above the .parent */
  bottom: 100%;
}

In the above, the position: anchor; would indicate that this element behaves like position: absolute; but will also reposition based on other factors; in a similar way to how position: sticky; changes. The overflow-y: static; indicates that when a non-static (excluding position: relative;) element would clip in the y-axis, it must instead reposition itself along the y-axis by the amount of clipping that would occur.

The difference between position: anchor; and other position values would be that when used with overflow: static; (which is the property/value pair that turns on repositioning) the size of the position: relative; element parent would be added in the axis of overflow clipping when clipping occurs.

If you use position: absolute; instead, this would have the possibility of obstructing the position: relative; ancestor as it can today (to allow for MacOS-style <select> elements centering the selected option over the anchor). In other words, the size of the position: relative; ancestor would have no effect on the child. The only position adjustment would be done by the offset clipping amount from the overflow: static; ancestor.

If a position: relative; element with a position: anchor; child inside appears outside the boundary of a overflow: static; container (ie. completely visually hidden), the position: anchor; element resets back to the original (ie. preferred) position (as if the overflow: static; was not applied). In other words, the offsets applied by the overflow: static; to the position: anchor; element would be removed and the position: anchor; child would behave as if it was position: absolute; today.

I think a missing piece to my approach is the transform property which we often use to center a tooltip visually. I imagine that the clipping algorithm wouldn't be able to take transforms into account so a method of centering a .child without transform would be very helpful. Perhaps when turning on position: anchor;, positioning properties could become relative to the position: relative; ancestor and unlock something like left: auto; right: auto; to center horizontally against the anchor.

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions