Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to increase margins of containers for pending floats ? #4052

Open
verdy-p opened this issue Jun 22, 2019 · 13 comments
Open

How to increase margins of containers for pending floats ? #4052

verdy-p opened this issue Jun 22, 2019 · 13 comments

Comments

@verdy-p
Copy link

verdy-p commented Jun 22, 2019

It's impossible to define a correct left or right margin for a container, when there are conditional floats pending (on the left or right) and defined outside the new container.

We should be able to increase the margin to take into account the maximum width and margins specified by any pending floats (as they can exist even outside the container itself).

If the computed "minimum width" of the container cannot fit in these increased margins, then it will "clear" vertically automatically after the first float (still pending on the left or right of the container, not necessarily all the same width) that leaves enough space for putting the content.

In frequent cases, (e.g. with floatting illustration images or lateral navboxes used in Wikipedia articles), it is impossible to predict where these floats will end, and

  • having to specify a "clear:left/right/both" for the container is just a nuisance when the content can perfectly fit.
  • we could specify a left/right margin in % or pixels to keep space available for floats, but here also it will not adapt to the situation where there's actually no floats and it will then generate undesired excessive lateral margins left completely blank.

So I suggest "margin-keep: floats/float-left/float-right" (possibly also "float-begin/float-end" to take into account Bidi and notably direction of the parent, independantly of the directionality of the container itself and of its content children).

Or alternatively:

  • new values for "margin-left/right:" to make them relative (and collapsed) to the lateral margins of pending floats, like "margin-right: +10%" (or "+150px") to indicate we want a right margin to be at least 10% of the parent width (or 150px respectively), measured either from the "relative" parent content-box (in which floats may be positioned and margins are measured by default, but only when there's no such float present taking space) or otherwise from the inner lateral side of the border-box of the float (if there's at least one float taking space): this "+" indicates that behavior. In all cases, if the new computed margin would exceeds the parent's contentbox, a vertical "clear" will occur to pass these floats.

Note as well that floats attached one side may also exceed their "relative parent" content width. and we should be able to limit their default width (unless this width is already their minimum width, in which case they will still overflow their "relative parent", which may then have to either "hide" the excess or use automatic horizontal scroll to allow seeing the float completely on a interactive output, or to render their excess on separate pages with a printed or non-interactive output with static page width).

All this is needed to correctly adapt also to various output devices (notably narrow screens on smartphones, where it is also essential to not "waste" the horizontal space available, whose usage should be maximized, otherwise the output is just hard to read and navigate with excessive vertical scroll and line breaks occuring too often when margins are too high with the conventional solutions).

This suggestion is independant of "margin-trim:" for the layout of content children of the container itself.

@SelenIT
Copy link
Collaborator

SelenIT commented Jun 24, 2019

Doesn't establishing the new Block Formatting Context (either by explicit setting display:flow-root or implicitly as a side effect of overflow and some other properties, here is a CodePen example) result in the behavior you need?

@verdy-p
Copy link
Author

verdy-p commented Jun 24, 2019

None of the 10 proposed solutions are what I expect. All of them still leaves the float going "inside" the block (that they cover).
What I mean is jist allowing the container to have its margins increased so that the floats remain completely outside of it (even if this means that any blanks space left below the float will not be used by the new container, unless, it includes internal floats that ''may'' go in that margin (but only if they fit, but I think it complicates things).

What is sufficient is that, when increasing automatically the margins due to external floats still needing space, the minimum width for the new container will be respected; otherwise a vertical clear will occur along each successive floats pending vertically until there's space, or all floats have been cleared.

When such clear will occur, this will just increase the top margin of the new container, but the border, background, and content of the new container will be also moved vertically. As this leaves some space above the container, some of the pending floats may be placed there instead of stacking vertically. The renderer could automatically select the floats that best match that empty space.

The block formatting context does not help here.

And as I said the typical usage is for illustrations added in Wikpedia articles: there's no easy way to place them in the article, including when their vertical height is variable, and even ajustable (e.g. my collapsing/expanding a floatting infobox). As well we cannot predict the effective rendering display width, the article being read on narrow smartphones or large desktops.

It's a common problem in articles: it's difficult to find the appropriate place where to include these floatting illustration. So finally we use too many "clears" and space is wasted on all screens.

Note that the situation is simpler when all floatting illustrations or lateral notes will go to a dedicated and cumfortable lateral margin, but this is only used for output printed on paper with known page sizes.

Floats were initially intended for lateral ilustrations, and this is still the majority of use of them in Wikipedia articles (also with lateral infoboxes, or floatting TOC's which are collapsible). But finally we have to group all the floatting illustrations and boxes at top, an not in the relevant sections they should illustrate, so that they can stack correctly, and then we can remove all clears: this works well for dektop screen rendering but not so well for small mobile displays (notably those held in portrait mode), and that was the reason for creating another layout for the mobile version of the wikis.

@Loirooriol
Copy link
Contributor

None of the 10 proposed solutions are what I expect. All of them still leaves the float going "inside" the block (that they cover).

This doesn't seem right, see https://www.w3.org/TR/CSS22/visuren.html#floats

The border box of [...] an element in the normal flow that establishes a new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap the margin box of any floats in the same block formatting context as the element itself.

So please clarify why "The block formatting context does not help here". An example with code would be useful.

@verdy-p
Copy link
Author

verdy-p commented Jun 28, 2019 via email

@verdy-p
Copy link
Author

verdy-p commented Jun 28, 2019 via email

@astearns
Copy link
Member

@verdy-p I wonder if this case could be solved with grid layout instead of floats. You could define a column on the left where you position the content that would have gone to the floats, and the next column would take up the "Inner Content Box" content. The left column's width could fall to zero if there is no content for it, and the start edge of the right column's content would always adjust to the left column's maximum width.

@Loirooriol
Copy link
Contributor

|<----------PAGE WIDTH------------------->|
|          :                     :        |
|< MARGIN >:<   CONTENT BOX     >:<MARGIN>|
|          : TEXT HERE...        :        |
|          +-------+ ...TEXT HERE:        |
|          | INNER +-------------|        |
|          | LEFT  |  INNER      |        |
|          | FLOAT |  CONTENT BOX|        |
|          +-------+             |        |
|          :       |             |        |
|          :       +-------------+        |
|          :                     :        |
|<----------PAGE WIDTH------------------->|
|          :                     :        |
|< MARGIN >:<   CONTENT BOX     >:<MARGIN>|
|          : TEXT HERE...        :        |
|          +-------+ ...TEXT HERE:        |
|          | INNER |             |        |
|          | LEFT  | cleared     |        |
|          | FLOAT |             |        |
|          +-------+-------------+        |
|          | INNER CONTENT BOX   |        |
|          +---------------------+        |
|          :                     :        |

@verdy-p IMO that seems perfectly doable with a BFC root. Example

Instead of your margin: 2em+0.5em, just use a BFC root to avoid overlapping the float, then you don't need the 2em. And if you want extra margin when there is a float, set it as a margin-right: 0.5em to the float.

@verdy-p
Copy link
Author

verdy-p commented Jun 28, 2019

No, I don't want the grid layout, because the floats have sizes completely independant of the inner box I want to place and completely unpredictable: these floats are generated externally and there's not even any way to know when they exist.
As well the flex layout would not work: it would force the floats (from anywhere before) to use the whole vertical size of the inner box, or would force the inner box to fill the while vertical size of the float.

A typical usage is when the inner box shows a notication box or an horizontal navbox that should be completely opaque and not being covered by any prior floats. And the presence of these floats must not cause the inner boxes to have their content size expanded vertically.

Finaly note: the inner box may also have their own floats: but because the margins was expanded, they can continue to be aligned vertically with the prior floats (i.e. outside the inner box, unless the inner box is a new "relative" parent for containing these inner floats. In the inner box, the inline content can still wrap around the inner floats when needed, for example when the inner floats are larger than the prior floats). As well the inner floats will fit below prior floats, stacking vertically as necessary, they won't cause additional "clears" of the contents of the inner box.

This proposal is consistant with simple formatting of articles with illustrations or lateral notes placed in floats.

Counter example

@verdy-p
Copy link
Author

verdy-p commented Jun 28, 2019

note that your example with BFC is not consistant: you've broken the two parts of the "TEXT HERE... TEXT HERE", but this is the SAME inline content flowing around the prior float.
And your test should include further "TEXTHERE" content after the inner box.

As well the inner box may contain their own floats (that will also align vertically normally with the prior float), stacking vertically normally.
All that I need is to make sure that a designated part of the parent content becomes a true rectangle not covered by any prior floats

And this rectangle is were we can also place bulleted lists (for now this never works, the list items are incorrectly aligned because the bullet margin collapses into where the prior float are placed: they are aligned to the margin of the parent box, and not aligned with the margin of the prior floats where "normal" text flows.

Text indentation in the content also does not work (it is broken by the presence of prior floats: we should be able to isolate them within inner boxes where the margins are increased). So the inner box can be:

  • a list item (including its bullet or number)
  • a full paragraph
  • a borderedand/or filled area that should remain rectangular (except their inner own floats that can flow outside the rectangle to fill the margin not used by prior floats.

@Loirooriol
Copy link
Contributor

Loirooriol commented Jun 28, 2019

you've broken the two parts of the "TEXT HERE... TEXT HERE"

Irrelevant, that's outside the inner box BFC root

And your test should include further "TEXTHERE" content after the inner box.

This was not in your graphics, but also irrelevant

As well the inner box may contain their own floats

OK, that's the real reason that prevents you from using a BFC root. You should have said this from the beginning instead of insisting that BFC roots don't work.

It seems what you need is a feature that prevents block boxes from overlapping floats (as if they were BFC roots) but without establishing an independent formatting context, to avoid containing inner floats. To me this seems more reasonable than margin: 2px+0.5em.

Though it would be kind of circular if the size of this container could be reduced by inner floats, since inner floats could be sized with percentages relatively to this container. So it seems complicated.

@verdy-p
Copy link
Author

verdy-p commented Jun 28, 2019

Now the example modified shows other problems caused by incorrect margins (for bulletted items in the inner box).
I changed a bit the metrics to be more realistic, but also to view it completely (the test page uses too much space and leaves little to the rendering.

You can see that only item 3 is correctly positioned in the inner box, but items 1 and 2 are not relative to a normal float: these items need to be embedded as well (individually or the full "ul" list) within their own inner box, to be correctly positioned relative to prior floats.

That's one of the many quirks we see. But your proposal using BFC roots is almost usable.
One last thing: the inner floats (i.e. floats inside the inner box) cannot flow in the margin of the outer box. This is the practical case for all illustrations, that they line up on the same margin and use them as much as possible, instead of taking space in the inner box (unless the innerbox is a new "relative" parent but as the inner box has a "display:flow-root", it is always a new relative parent.

So there's no way for inner floats to align with outer floats: they will all take all their space in the inner box (which is opposed to the fact that we want to avoid the inner box to clear down, as much as possible because it has insufficient width. But putting the inner floats completely inside the inner box then makes non-sense, they should still flow like outer floats.

Is there an alternative to "display:flow-root", so that it will apply to the box itself and its normal content flow, except its floats content which will continue to use the margins inherited from the parent?
And how can we fix the incorrect horizontal alignment of bulleted/numbered lists or indented text, relative to prior floats (i.e. their own margin?) if we have to transform each list item or indented paragraph into an "inner box" (flow-root) that will have a serious impact on the content (notably when it is generated and we still dont know if there are prior floats before.

I proposed the augmented margin values because it was in fact not changing the formatting context, and the inherited margins were still there: all that is needed is to specify alternate margins in case of presence of floats, and that will replace the normal margin for the normal content (text, for bullet/numbered lists, or indented text, like for BFC "display:flow-root"), but will not affect the placement of floats in that content, that will cointinue to use the inherited margins.

So may be a "display:flow-content-only" ?? "display:flow-except-floats" ?? (I'm concerned by the placement of the green-colored inner float, which should not be inside the inner box but just below the existing magenta outer float that already created the necessary margin for it and that will still use the inherited margins of the yellow outer box, the same margins used by the prior magenta outer float.)

And how to resolve the existing bug for list items and indented text? (see the bullets incorrectly placed)

And because the BFC solution forces ALL the content of the inner box to be on the right of the prior float, we can't use it to place bulleted items, or individual paragraphs or other blocks. We need another solution: the BFC establishes a new context that applies to only clearly delimited boxes (with background, borders)

We still need to find a way to correctly position the hr rulers so that they will also not be overlapped by prior floats, but will use their own BFC context.

For now I see no simple solution, except what I propose with augmented margin values, that replace normal margins when there's a float beside the block.

If changing the syntax of "margin: values" is too complicate, may be be can have a separate "margin-with-float: values" for any content box, and that will apply individually to all its child blocks (including list items or "dd" items in definition lists for their bullet/number/indentation margin) in presence of a prior float taking space in the content box, except child floats and positioned elements, that are still rendered within the margins of their nearest "relative" or "absolute" ancestor context.

If there are no longer any floats taking space in the content-margins, the standard "margin: values" will still apply to all children, except floats also using the margins of the inherited relative or absolute content.

@verdy-p
Copy link
Author

verdy-p commented Jun 28, 2019

Note that when playing with ways to solve the problems for the placement of bullets and their margin, I discovered a probable bug in my browser: when the list item has a "opacity:1" (the default), the bullet is drawn over the float that covers it (so it appears as plain black, the default foreground colon); but when "opacity:" has any other value<1, it is drawn under the floats that covers it (because that float is maggenta, the bullet appears as dark magento with "opacity:0.8"
In both cases however it is incorrectly position (its 2em left margin is collapsed with the padding parent and not relative to the inner context ).
This is not the same subject, but may be related to the fact that placement of margins for list items mùay have been incorrectly described in existing specifications. Homever the value of opacity should not have the effect of hanging the "z-order" (or may be this is a legacy "quirk" which should not apply to HTML5).

@verdy-p
Copy link
Author

verdy-p commented Jun 28, 2019

Also my question is more general:

  • can we change the behavior of "margin-*:" with a computed value (i.e. an expression) where we can access to the width of prior floats at start of the context ?
  • can we get access to the preexisting content-width of the parent block or the width of another element selected by id or to other size measurements (includin the height, font-size, line-height) and use them in an expression value ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants