Skip to content

[css-values-5] [css-overflow-4]How does line-clamp transition from to auto or none? #10502

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

Open
yisibl opened this issue Jun 26, 2024 · 9 comments

Comments

@yisibl
Copy link
Contributor

yisibl commented Jun 26, 2024

@andreubotella The current implementation of line-clamp in Chrome adds auto values, and the use case here is very much like the height: 0 to auto scenario.

Will the interpolate-size property added a while ago work in this scenario?

Demo: https://codepen.io/yisi/pen/rNgojEx
Explainers: https://github.com/Igalia/explainers/blob/main/css/line-clamp/README.md

cc @frivoal @tabatkins @dbaron @flackr

@yisibl
Copy link
Contributor Author

yisibl commented Oct 15, 2024

cc @andreubotella

@andreubotella
Copy link
Member

I don't know too much about interpolate-size, but the way that property is specified, it wouldn't apply to line-clamp, because the spec text specifically mentions interpolating between a length (such as 3px, but not 3), and an intrinsic size keyword. Although auto is an intrinsic size keyword for the height property because it denotes a size, auto for line-clamp does not denote a size.

Things get more complicated when you consider that the number of lines that auto corresponds to depends on the height and/or max-height properties. If those properties also transition during the line-clamp transition, then the transition will not look smooth. In particular, since the transition from max-height: none to max-height: 200px is discrete, if line-clamp: 3 transitions to line-clamp: auto at the same time, then the number of lines before clamp might very well jump in the middle of the transition.

That said, I'm not familiar enough with transitions to know what the right behavior would be here.

@andreubotella
Copy link
Member

andreubotella commented Oct 22, 2024

Thinking about this again, I wonder what the use case would be to transition from clamping by a number of lines to clamping by a height.

Usually line-clamp indicates hidden content, and transitions based on that would usually expand back to the full size. And that would currently be possible with line-clamp: auto, by transitioning a set height to auto:

.item {
  transition: height 3s;
  interpolate-size: allow-keywords;
  overflow: hidden;
}
.item.collapsed {
  line-clamp: auto;
  height: 4lh;
}
Screencast.from.2024-10-22.11-41-28.mp4

Rather than the lines appearing or disappearing into the hidden overflow, you could also set line-clamp: auto on .item (so it's enabled on both sides of the transition) to change the number of clamped lines as the height animates. (Note that this could cause jank, since every frame would need a separate layout.) This doesn't seem to work currently in my implementation in Chromium, but it's probably a simple layout caching bug. This is what it'd look like:

.item {
  line-clamp: auto;
  transition: height 3s;
  interpolate-size: allow-keywords;
}
.item.collapsed {
  height: 4lh;
}
Screencast.from.2024-10-22.11-43-13.mp4

But maybe there are other use cases for transitioning between a number and auto that I haven't thought of.

@yisibl
Copy link
Contributor Author

yisibl commented Oct 22, 2024

Note that this could cause jank, since every frame would need a separate layout.

Looks good if it fixes the problem.

@yisibl
Copy link
Contributor Author

yisibl commented Oct 22, 2024

There is also a scenario where an internal element contains margin/padding, where lh can't set the exact number of rows needed.

image

data:text/html;charset=UTF-8,>
<style>
.item {
  border: 1px solid green;
  width: 300px;
  height: 4lh;
  line-clamp: auto;
  font-size: 16px;
  line-height: 1.5;
}
p {
  margin: 20px 0;
}
style>
<div class="item">
 <p>
  It allows limiting the contents of a block container to the specified number of lines; remaining content is fragmented away and neither rendered nor measured. Optionally, it also allows inserting content into the last line box to indicate the continuity of truncated/interrupted content.
 p>
div>

@yisibl
Copy link
Contributor Author

yisibl commented Oct 22, 2024

Can we have line-clamp add a unit like lh (e.g. lc)? Making it always calculable as a length would solve the problem of animation calculations?

@andreubotella
Copy link
Member

Can we have line-clamp add a unit like lh (e.g. lc)? Making it always calculable as a length would solve the problem of animation calculations?

I don't think that's possible. There's questions like what does 1.5lc mean, or does 0lc include the initial margin, or what if you have 6lc and you only have 4 lines, or what happens when you set height: 3lc on a grid with multiple columns with differently sized text, or what if you use lc on width rather than height...

But more fundamentally, for a lc value to resolve to a pixel length, you need layout (i.e. you need to figure out which content goes in every line, how to place floats, how to collapse margins...), and the style resolution (which includes resolving units to pixels) needs to happen before layout. Otherwise, you might get into dependency cycles which could be impossible to resolve.

Rather than the lines appearing or disappearing into the hidden overflow, you could also set line-clamp: auto on .item (so it's enabled on both sides of the transition) to change the number of clamped lines as the height animates. (Note that this could cause jank, since every frame would need a separate layout.) This doesn't seem to work currently in my implementation in Chromium, but it's probably a simple layout caching bug.

Sorry to disappoint, but after looking a lot more into how interpolate-size and calc-size work, I realized that this behavior isn't what would automatically fall out of the current spec text – and that is also why it didn't work in the Chromium implementation. I guess it would not be impossible to define line-clamp: auto in a way that it would work, but you would need multiple layouts for each frame, which might make the performance of this unacceptable to browsers.

@tabatkins
Copy link
Member

Right, this definitely doesn't fall out of any existing behavior; if we wanted it, we'd have to define some brand new behavior for it. But as noted, it would be expensive.

Since the obvious use-cases (transitioning the height between auto and a fixed size, and using line-clamp:auto on that) work already, I think we'd need more realistic examples of what other behavior is desired.

@frivoal
Copy link
Collaborator

frivoal commented Jun 6, 2025

The examples in #10502 (comment) rely on the fact that the text is plain and unstyled, and that there's no margin/padding/border disrupting things. If they were, we couldn't use a lh value to achieve that effect. A reasonably obvious use case is the exact same as these two examples, but with enough styling and odd content that lh is not a good fit.

However, solving that seems hard. In a way, we'd need a value (line-clamp: end ?) which computes to the number of line in the element, so as to have no effect, but to provide a point from which animations / transitions could run. However, that doesn't actually make sense, because computed values are determined before layout, and at that stage, you don't know how many lines there will be. A JS-based workaround which waits for layout to be complete, counts lines, and then sets the value to that, is quite achievable, but as a pure CSS solution, it doesn't seem particularly easy to solve.

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
@frivoal @tabatkins @yisibl @andreubotella and others