ellipsis multiple lines text doesn't work (i.e. add support for -webkit-line-clamp)
Categories
(Core :: CSS Parsing and Computation, enhancement)
Tracking
()
People
(Reporter: sjochimek, Assigned: heycam)
References
(Depends on 3 open bugs, Blocks 1 open bug, )
Details
(Keywords: dev-doc-complete, perf:responsiveness, Whiteboard: [webcompat:p1], platform-rel-Facebook, [geckoview:p2] [layout:backlog:2019q2:68]][wpt-failing][wpt-new-tests][wptsync upstream])
User Story
Business driver: Facebook Performance. Workaround for this bug is slower on Firefox. [selena] facebook is planning to enable this soon, and frmr Mozillians gave us the heads up. Also, multiple top and long tail site compat. Note: bz suspects safety here.
Attachments
(9 files, 2 obsolete files)
Comment 2•8 years ago
|
||
Updated•8 years ago
|
Comment 4•8 years ago
|
||
Updated•8 years ago
|
Comment 7•8 years ago
|
||
Updated•8 years ago
|
Updated•8 years ago
|
Updated•8 years ago
|
Updated•8 years ago
|
Updated•8 years ago
|
Updated•8 years ago
|
Updated•8 years ago
|
Comment 8•7 years ago
|
||
Updated•7 years ago
|
Updated•7 years ago
|
Updated•7 years ago
|
Updated•7 years ago
|
Updated•7 years ago
|
Updated•7 years ago
|
Comment hidden (advocacy) |
Updated•7 years ago
|
Updated•7 years ago
|
Comment 11•7 years ago
|
||
Updated•7 years ago
|
Comment 12•7 years ago
|
||
Comment 13•7 years ago
|
||
Comment 14•7 years ago
|
||
Comment 15•7 years ago
|
||
Comment 16•7 years ago
|
||
Comment 17•7 years ago
|
||
Comment 18•7 years ago
|
||
Comment 19•7 years ago
|
||
Comment 20•7 years ago
|
||
Comment 21•7 years ago
|
||
Comment 22•7 years ago
|
||
Updated•7 years ago
|
Updated•7 years ago
|
Updated•7 years ago
|
Updated•7 years ago
|
Updated•6 years ago
|
Updated•6 years ago
|
Comment 23•6 years ago
|
||
Comment 24•6 years ago
|
||
Comment 25•6 years ago
|
||
Comment 26•6 years ago
|
||
Comment 27•6 years ago
|
||
Assignee | ||
Comment 28•6 years ago
|
||
Assignee | ||
Comment 29•6 years ago
|
||
Comment 30•6 years ago
|
||
Comment 31•6 years ago
|
||
Updated•6 years ago
|
Updated•6 years ago
|
Comment 32•6 years ago
|
||
Updated•6 years ago
|
Comment 33•6 years ago
|
||
Comment 34•6 years ago
|
||
Updated•6 years ago
|
Updated•6 years ago
|
Comment 35•6 years ago
|
||
Updated•6 years ago
|
Updated•6 years ago
|
Updated•6 years ago
|
Updated•6 years ago
|
Updated•6 years ago
|
Comment 36•6 years ago
|
||
Another issue with tokopedia
https://twitter.com/ReinPre10/status/1090646030134079488
Assignee | ||
Updated•6 years ago
|
Assignee | ||
Comment 37•6 years ago
|
||
Reflecting a couple of off-bug mails back here:
Cameron McCormack wrote:
I think initially I just want to implement line-clamp with the syntax
none | <integer>
and leave the implementation of the component longhands (max-lines, continue, and block-ellipsis) until later. I.e. we only support the effect of { max-lines: none; continue: auto; block-ellipsis: none; } or { max-lines: <n>; continue: discard; block-ellipsis: none; }.
As far as I can tell, the interesting requirements here are:
max-lines applies to a block element, and counts all descendant lines except for those under any independent formatting contexts (like BFCs).
The lines in excess of max-lines are fragmented away into the ether as if they were display:none.
The excess lines do contribute to the inline min-content and max-content size of the elements, but do not contribute to the block component of those sizes.
The fact that we need to consider the excess lines for sizing makes it sound like we need to be creating lines and frames for their content. But where should we be putting them? I see there is an OverflowLines property that holds lines during reflow, so could it make sense to leave them there, or in some other list? Or should I be thinking about a more general mechanism for holding fragmented-away content?
Assignee | ||
Comment 38•6 years ago
|
||
Mats Palmgren:
Cameron McCormack:
I think initially I just want to implement line-clamp with the syntax
none | <integer>
and leave the implementation of the component longhands (max-lines, continue, and block-ellipsis) until later.
OK, sounds good, that's what ISSUE 10 in the spec recommends (i.e. not exposing the longhands for now).
But perhaps we should consider shipping it as -webkit-line-clamp (not an alias), and only support it on display:-webkit-box boxes? I'm a little concerned that the CSS spec isn't compatible with what's implemented in Chrome, and to expose the -webkit- property on other types of boxes (that currently does nothing in Chrome). More on the incompatibilities below...
As far as I can tell, the interesting requirements here are:
- max-lines applies to a block element, and counts all descendant lines except for those under any independent formatting contexts (like BFCs).
I think that's what the current spec says, yes. I seem to recall it was a lot more advanced in an earlier version though, and it's not clear to me whether the current spec reflects what authors actually want. (I'm a bit skeptical about that.) It might just be that it was edited to better match Chrome's broken implementation. https://github.com/w3c/csswg-drafts/issues/2847#issuecomment-401412504
The requirement to not count lines in child BFCs seems a bit too strict to me. As the spec notes, it means it can't be used on column containers for example, which seems a bit sad. It seems reasonable that scroll containers are excluded though, but do they count as a line? e.g.
<div>a<div style="overflow:scroll">...</div>b</div>
To me, that seems like three lines, but if I read the spec correctly it only counts as two towards max-lines.
(Fwiw, I don't see anything in principle that would prevent us from counting rows in grid/flex/tables as "lines" for this property. They all support fragmentation. But perhaps that's something that could be added later on if authors asks for it.)
The lines in excess of max-lines are fragmented away into the ether as if they were display:none.
That's not how -webkit-line-clamp works in Chrome. If the clamped box has overflow:visible then it simply overflows. (see the testcase in my github comment above). The spec says that line-clamp:<integer> implies continue:discard (which would treat them as display:none), but that's incompatible with -webkit-line-clamp (where you'd use overflow:hidden to do the "discarding"). Maybe we should ask for a spec change here (making continue:auto the default). Otherwise, I don't think -webkit-line-clamp can ever be an alias.
continue:auto seems a lot simpler to implement - just flow the block as usual and then set the bsize in ComputeFinalSize to the extent of the Nth line. Perhaps also adjust the reflow status accordingly. The ellipsing can probably be done by reflowing the Nth line again with some children pushed to make room for it. I don't think we need any special child list stuff or continuations for this. (Note that if the block itself also has overflow:hidden then we can probably skip flowing lines after the Nth line, which I think is the optimization Facebook is looking for.)
continue:discard is harder. For this we should probably stop flowing more lines and push the remaining children onto a DiscardedChildrenList or something, and simply not render them. I think the boxes must exist though, and our pull-up code needs to look for them. Alternatively, we could add them to ExcessOverflowContainersList and mark them as "discarded" with a frame bit. And then teach the code dealing with those lists ([Excess]OverflowContainersList) to ignore them.
I think that we need to deal with overflow from a line that is included, e.g.
<div style="max-lines:1; continue:discard"> <img style="height:1000px"><br>b
Here, "b" should be discarded but the <img> will have overflow that should be rendered (I think). So, we'd have both normal overflow containers and "discarded" ones there in this case.
I think ExcessOverflowContainersList might be less work than adding a new child list.
The excess lines do contribute to the inline min-content and max-content size of the elements, but do not contribute to the block component of those sizes.
Yeah, that makes sense to me.
But where should we be putting them? I see there is an OverflowLines property that holds lines during reflow, so could it make sense to leave them there, or in some other list?
I think OverflowLines is for when the block itself is incomplete, which I don't think is the case here.
Assignee | ||
Comment 39•6 years ago
|
||
Mats Palmgren:
The ellipsing can probably be done by reflowing the Nth line again with some children pushed to make room for it.
Actually, that's not what -webkit-line-clamp does in Chrome, e.g.:
<style> .clamp { -webkit-line-clamp: 3; } .box { display: -webkit-box; -webkit-box-orient: vertical; width: 100px; border: 1px solid; } </style> <div style="display:inline-block; border: dotted"> <div class="box clamp" style="height:6em"> 1<br> 2<br> 333333333333333333333333333333333<br> 4<br> 5<br> 6<br> 7<br> 8<br> </div> </div>
So, we can probably reuse our 'text-overflow' code for that.
Assignee | ||
Comment 40•6 years ago
|
||
(In reply to Cameron McCormack (:heycam) from comment #38)
Mats Palmgren:
But perhaps we should consider shipping it as -webkit-line-clamp (not an alias), and only support it on display:-webkit-box boxes?
Maybe. What the spec currently requires obviously isn't exactly what Chrome does, and I suspect that the spec authors are trying to find a definition that is somewhat sensible and satisfies the web compat requirements, since what Chrome does seems pretty weird (to me).
I took a look through all of the webcompat.com issues in the See Also links, and all of them that still reproduce use
display: -webkit-box;
overflow: hidden;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
-webkit-line-clamp: <number>;
which means I think we have some flexibility in terms of what we want to implement here, i.e. if we wanted to follow the spec and make line-clamp set continue:discard, then it's probably fine (even though Chrome/WebKit's effect is like continue:auto) because authors are always setting overflow:hidden anyway.
Assignee | ||
Comment 41•6 years ago
|
||
Although I don't have any data on whether authors are using -webkit-line-clamp on elements that are not display:-webkit-box, and would then suddenly start clamping their lines if we implemented what the spec says, while continuing not to have any effect in Chrome. If that's a real concern then we should also key the behavior off display:-webkit-box, and if we're doing that, we may as well follow the continue:discard-like behavior too.
Another issue is the difference between text-overflow:ellipsis and the block-overflow:ellipsis behavior that the spec defines line-clamp to cause. text-overflow should really only be for inline direction overflow. If we implement the spec's version of line-clamp, we'd need to reinterpret text-overflow to also provide the block-overflow handling. In this example:
<!DOCTYPE html>
<style>
div {
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
background: yellow;
overflow: hidden;
width: 200px;
text-overflow: ellipsis;
}
div.box {
display: -webkit-box;
}
</style>
<div class=box>FIRSTLINEISTOOLONGGGGGGGGGGGGGGGGGGGGGGGGGGG<br>
second line<br>
third line</div>
Chrome only displays the ellipsis on the second line. Removing the .box class causes the first line to get an ellipsis. So that is another hazard in implementing the standards version, I guess.
Assignee | ||
Comment 42•6 years ago
|
||
Regarding text-overflow, turns out that it's the -webkit-line-clamp property that turns on the ellipsis. The presence of text-overflow:ellipsis has no effect here, since that is a non-inherited property and the <div> is a flex container frame and the anonymous flex item child would have text-overflow:clip.
Assignee | ||
Comment 43•6 years ago
|
||
This is a first stab at doing something like Chrome/WebKit, i.e. just use the clamped lines as an input to the intrinsic size of the block, and rely on overflow:hidden actually hiding the overflowing lines. Works only with display:-webkit-box and -webkit-box-orient:vertical. Seems to work on a couple of the linked webcompat.com issues I tested.
Assignee | ||
Comment 44•6 years ago
|
||
Mats, can you let me know what you think of this approach?
One specific thing I want to know is if there's something better to do than search up for the flex container frame's element's primary frame to get the display and -webkit-line-clamp values. Should I be sticking this information on one of the ReflowInput objects instead?
Assignee | ||
Comment 45•6 years ago
|
||
Assignee | ||
Comment 46•6 years ago
•
|
||
Assignee | ||
Updated•6 years ago
|
Comment 47•6 years ago
|
||
This demonstrates the reflow issue I mentioned in the review comment.
STR
- load this testcase
- type F12 to open devtools
ACTUAL RESULTS
at 1: ellipsis is missing
at 2: the block is resized (from 5 lines to 4 lines), and ellipsis is still missing
Comment 48•6 years ago
|
||
I think it's worth adding a couple of basic tests for fragmentation too (and mark them as failing), so that we have some once bug 939897 is fixed.
The columnset box at the top should have four columns, the last two for rendering the overflowing lines. (It appears Chrome creates the right number of columns but fails to render the overflowing text in the last two columns.)
The columnset box at the bottom should have 2 columns.
Comment 49•6 years ago
|
||
(In reply to Cameron McCormack (:heycam) from comment #46)
The one other question I have is whether it makes sense to skip independent
formatting contexts. I think it kind of does (it definitely does if the
formatting context is something non-block, like a flex or grid container),
For '-webkit-line-clamp', yes. For a standardized general 'line-clamp',
it would be a bit sad to not support it, since both grid/flex has a concept
of rows/lines that could be counted, and both support fragmentation.
Likewise for tables.
but it would also mean skipping over an
overflow: hidden
child of a flex
item in a -webkit-line-clamp controlled flex container, which is not
something that Blink does.
I'll try to take a closer look on that and comment later...
Comment 50•6 years ago
|
||
Here's a testcase to highlight a few of the bugs I've found in
Chrome's implementation.
The child in each column has '-webkit-line-clamp: 3' so my expectation is
that an ellipsis should occur next to "3" in each column.
This works fine in the first example, which is just a flat list of text
children. In the remaining columns we a nested block inserted after
different lines and the results in Chrome are wrong IMO.
From left to right, the line with an ellipsis is:
3 (none) 5 (none) 4
In our current WIP implementation we have:
3 5 5 3 4
(which is also wrong)
Assignee | ||
Comment 51•6 years ago
|
||
Updated•6 years ago
|
Comment 52•6 years ago
|
||
Comment 53•6 years ago
|
||
Updated•6 years ago
|
Updated•6 years ago
|
Comment 54•6 years ago
|
||
See bug 1547409. Migrating webcompat priority whiteboard tags to project flags.
Comment 55•6 years ago
|
||
Comment 56•6 years ago
|
||
bugherder |
Updated•6 years ago
|
Comment 57•6 years ago
•
|
||
I've documented this at https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-line-clamp and mentioned it in the release notes for Firefox 68 at https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Releases/68#CSS.
For the browser compatibility info I've created a PR at https://github.com/mdn/browser-compat-data/pull/4142 and for the CSS info https://github.com/mdn/data/pull/366.
It would be great if you could check whether everything's ok.
Sebastian
Assignee | ||
Comment 58•6 years ago
|
||
(In reply to Sebastian Zartner [:sebo] from comment #57)
I've documented this at https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-line-clamp
I suggest adding an overflow: hidden
to the example, unless you deliberately want to show how the effect of -webkit-line-clamp is to affect the height of the element and let the excess lines overflow. Actually it might be worth just pointing out in some prose that it usually needs to be used in conjunction with overflow: hidden
to have the desired effect.
and mentioned it in the release notes for Firefox 68 at https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Releases/68#CSS.
For the browser compatibility info I've created a PR at https://github.com/mdn/browser-compat-data/pull/4142 and for the CSS info https://github.com/mdn/data/pull/366.
That should use "animationType": "integer"
.
Other than that it looks good, thanks!
Comment 59•6 years ago
|
||
(In reply to Cameron McCormack (:heycam) from comment #58)
(In reply to Sebastian Zartner [:sebo] from comment #57)
I've documented this at https://developer.mozilla.org/en-US/docs/Web/CSS/-webkit-line-clamp
I suggest adding an
overflow: hidden
to the example, unless you deliberately want to show how the effect of -webkit-line-clamp is to affect the height of the element and let the excess lines overflow. Actually it might be worth just pointing out in some prose that it usually needs to be used in conjunction withoverflow: hidden
to have the desired effect.
Good point. I've updated the example and the description accordingly.
and mentioned it in the release notes for Firefox 68 at https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Releases/68#CSS.
For the browser compatibility info I've created a PR at https://github.com/mdn/browser-compat-data/pull/4142 and for the CSS info https://github.com/mdn/data/pull/366.That should use
"animationType": "integer"
.
Interesting! That's actually a difference to the implementations in the other browsers. And it actually depends on whether the value is an integer or none
. I've updated animationType
to match the spec.
Sebastian
Updated•6 years ago
|
Assignee | ||
Comment 62•6 years ago
|
||
(In reply to Benoit Girard (:BenWa) from comment #11)
Facebook currently is flushing style+layout to implement this behavior
manually causing a non trivial performance hit. In Chrome we will begin to
use CSS line-clamp to remove this performance hit. We will continue to
support the alternate code path for Firefox users but it would be great to
have a fast solution for Firefox users. This is for shared newsfeed article
titles and description. ni? me if you need more information.
Benoit, now that -webkit-line-clamp has landed in current Nightly, I'm curious whether you plan to use it in Firefox place of the layout-flushing script fallback and if that has eliminated the performance hit you were encountering.
Comment 63•6 years ago
|
||
(In reply to Cameron McCormack (:heycam) from comment #62)
Benoit, now that -webkit-line-clamp has landed in current Nightly, I'm curious whether you plan to use it in Firefox place of the layout-flushing script fallback and if that has eliminated the performance hit you were encountering.
Absolutely. Thank you for implementing this!
Comment 64•6 years ago
|
||
Change is ready but there's a more involved change to the CSS minifier which will take longer. Several news feed story types were affected by this.
Updated•6 years ago
|
Updated•5 years ago
|
Updated•3 years ago
|
Description
•