Open Bug 740910 Opened 12 years ago Updated 8 months ago

Support cropping in the middle for text-overflow

Categories

(Core :: Layout: Block and Inline, defect)

defect

Tracking

()

People

(Reporter: wesj, Unassigned)

References

(Blocks 2 open bugs, )

Details

XUL used to support cropping strings in the middle. Helpful in a cases (filenames for example) where the front and end of the string are typically more important than the middle. CSS text-overflow support front and end by using two options:

text-overflow: ellipsis ellipsis;

No reason we can't extend this to take more arguments. At the very least a 3rd for the middle? i.e.

text-overflow: clip ellipsis clip;
I don't know why I didn't find this issue before posting my one.

Here's what I wrote in bug 741743 because my request goes a bit more into detail:

According to https://developer.mozilla.org/En/CSS/Text-overflow and http://dev.w3.org/csswg/css3-ui/#text-overflow there's currently only the possibility to clip strings at the beginning and their end.
Though for recognizability it's sometimes better to crop the string in the middle.
Firebug is using that principle for file names and URLs and it works well. Though the strings are not cropped dynamically. So there's a problem when the containing element is resized. See http://code.google.com/p/fbug/issues/detail?id=4864.

Example:
this_is_a_very_long_filename.txt
this_is_a_very_long_filename2.jpg

With the current implementation this would be cropped to something like:
this_is_a_very_lo…
this_is_a_very_lo…

So the file types and names can't be destinguished.

If the truncation could be specified to happen in the middle of the word, this would look like:
this_is_a_…ename.txt
this_is_a_…name2.jpg

Thereby the most characterizing part is obviously the file extension.
So to keep this visible there could be another option to specify the number of characters to prevent from being cropped (at the left and the right side).

So if there's just space for e.g. 5 characters and we specified not to crop the right 3 characters, the result would look like this:
t…txt
t…jpg

I imagine the CSS syntax to be specified like this:
p {
  white-space: nowrap;  
  width: 100%;                     
  overflow: hidden;
  text-overflow: clip ellipsis clip 3;
}

p {
  white-space: nowrap;  
  width: 100%;                     
  overflow: hidden;
  text-overflow-left: clip;
  text-overflow-middle: ellipsis
  text-overflow-right: clip
  text-overflow-left-preserve: 0;
  text-overflow-right-preserve: 3;
}

Sebastian
I think we all agree that this is a desirable feature.

I don't see it as a middle ellipsis though, since you can't have an
ellipsis at the end at the same time.  I think of it more as an end-
ellipsis that has had its position moved, that is, it's still the
overflow at the end that you want to ellipsize, just in a different way.
So I think we should keep the text-overflow property as is and add a new
property to "move" the end-ellipsis from its position at the end.
With for example:
  text-overflow-end-offset: <length>
you could specify a "middle ellipsis" as:
  text-overflow: clip ellipsis;
  text-overflow-end-offset: 50%;

I think we need to keep the current requirement on text-overflow that
it does not influence the layout in any way - the hard part is how to
"move" the stuff after the ellipsis to get the desired rendering.
(both implementing it and writing a spec for it)

An example, where 'd' and 'e' overflows a |block|

  |a b c |d e

with the desired rendering ('X' is the ellipsis marker):

  |a bX e|

maybe we could do it something like this:

We hook in to DisplayLine in the same way we currently do to
implement text-overflow, but instead of analyzing the block edges
we calculate the x-position of 'text-overflow-end-offset' and use
that as the XMost() of the clip rect to analyze, that would give
us something like this, DisplayItem-wise:

  |a b   |
   ^^^
Now do a second pass: calculate the end of remaining content + the
width of the end-ellipsis, take the remaining width to the block edge
and use that for a new clip rect that ends after end of the line (ie,
only clip on the start-side this time).  With the result:

  |      |  e
           ''
Then wrap the items from the second pass in a DisplayItem that
translates them to the left by the appropriate amount and add a
marker for the ellipsis:

  |a bX e|
   ^^^ ''

roc, would something like that work?

Tantek, Elika, has "middle ellipsis" been discussed on www-style?

What's your thoughts?


====

An additional note: an ellipsis in the middle would look a bit odd
in scroll situations, since you would always see the end of the line
and only scroll the part on the start side of the ellipsis.
Component: Layout → Layout: Block and Inline
QA Contact: layout → layout.block-and-inline
I also think the "preserve" part of what Sebastian suggested has merit.
A minimal width to not clip at each end.  To generalize:
text-overflow-min-width: <length> [ <length> ]

So, his example:
  text-overflow-left-preserve: 0;
  text-overflow-right-preserve: 3;
would be:
  text-overflow-min-width: 0 3ch;
> text-overflow-min-width: <length> [ <length> ]
That's better than my idea.

> I don't see it as a middle ellipsis though, since you can't have an
> ellipsis at the end at the same time.
Of course you could have. To stay with my example:

|this_is_a_very_|long_filename.txt => |…is_a_v…ilenam…|

The question is just if that's something desirable.

Btw. the general syntax for my example would be:
text-overflow: ( clip | ellipsis | <string> ){1,3} [ <length>(1,2) ] | inherit

Two differences to my example though:
1. <length> is used for the preserved part instead of just an <integer>.
2. Defining just one <length> would result in clipping the right and the left side.

"text-overflow-end-offset" would give better control over the position of the end ellipsis. But here the question is, when people would want to put the ellipsis at e.g. 75%?
Another advantage would be that the syntax of "text-overflow" wouldn't have to be touched. Though as you can see in my examples I am seeing "text-overflow" more as a shorthand property. It could consist of:

text-overflow-start
text-overflow-middle
text-overflow-end
text-overflow-min-width

In regard of right-to-left languages I replaced "left" and "right" by "start" and "end".
This would allow more granular control over the different properties.

Sebastian
This would have to affect layout. Maybe we can make the change happen only at rendering time, as you suggest, but that might break things that assume frame geometry is correct...
From the looks of it, this is a feature request / feature enhancement in CSS. 

Wesley, Sebastian: please move the discussion to the www-style@w3.org list. Thanks.
I subscribed to the mailing list yesterday and sent a message there, though it still doesn't appear in the archives at http://lists.w3.org/Archives/Public/www-style/. How long does it normally take until the messages are listed there?

Sebastian
Unfortunately so far nobody responded to my www-style mail.
So I'd appreciate if Mozilla could do the pioneering here by implementing this using prefixed properties.

Sebastian
I think that would be a nice feature. I needed that to clean Gecko's <input type='file'> UI and I had to use xul:label which has a crop attribute that allows to have an ellipsis in the middle (and FWIW, it's not landed yet because using xul:label produces a11y issues).
Such feature in CSS would be great.
Version: unspecified → Trunk
We've implemented text-overflow in a way that doesn't affect layout (nothing is moved); it's completely handled at draw time by just not drawing some glyphs and drawing an ellipsis instead.

Cropping in the center is hard because it can't be handled that way.
Mats' idea of translating the right-hand-side of the line is possible but would lead to weirdness. We'd have situations where an element with a single CSS box would be rendered with one part of the box in one place, another part of the box in another place, and the middle of the box not rendered at all. Then you'd have to figure out how getBoundingClientRect/getClientRects and other CSSOM APIs would work.
If we restricted it to just text nodes somehow, and bailed on lines with mixed-direction text, then we could bake it into nsTextFrame and the difficulty would be greatly reduced.
> Cropping in the center is hard because it can't be handled that way.
Why not?

> handled at draw time by just not drawing some glyphs and drawing an ellipsis 
> instead.
This can be done for centered-cropping, too.

Sebastian
For center-cropping, something has to be moved, probably as Mats suggested in comment #3 moving content from the end of the line left. This can't be done just at draw time, because it must affect the results of APIs like getBoundingClientRect(), must affect which elements are targeted by mouse events, and must also affect various rendering acceleration pipeline things like where video is rendered if there is a video element on the line.
> For center-cropping, something has to be moved
To my understanding it doesn't have to be moved. It would work exactly as cropping at the end or the beginning.

Example (from bug 741743):
this_is_a_very_long_filename.txt
this_is_a_very_long_filename2.jpg

With the ellipsis at the end this would be something like:
this_is_a_very_lo…
this_is_a_very_lo…

If the truncation could be specified to happen in the middle of the word, this would look like:
this_is_a…name.txt
this_is_a…ame2.jpg

No layout changes, no pointer events issues.

Sebastian
In your example, the text "ame2.jpg" has moved.

An even harder example would be this_is_a_very_long_filename2.jpg<img src="thumbnail.jpg">. In that case, the <img> element would move.
(In reply to Sebastian Zartner from comment #17)
> > For center-cropping, something has to be moved
> To my understanding it doesn't have to be moved. It would work exactly as
> cropping at the end or the beginning.
> 
> Example (from bug: 741743):

<snip> 

Sebastian, we'd greatly prefer to iterate on existing CSS property design itself not in bugzilla but rather on w3.org.

Could you:
1. add your proposal/examples/links to images to the W3C wiki, e.g. on http://www.w3.org/wiki/CSS or a subpage thereof. Even just plain text exactly as you wrote here in bugzilla would be fine. Don't worry about structuring.
2. send an email to www-style@w3.org linking to that page and starting a discussion about it.

Thanks!

Tantek
> 1. add your proposal/examples/links to images to the W3C wiki
Added at http://www.w3.org/wiki/Text-overflow_middle_cropping.

> 2. send an email to www-style@w3.org
Done at http://lists.w3.org/Archives/Public/www-style/2013Jul/0451.html.

Sebastian
> Even just plain text exactly as you wrote here in bugzilla would be fine. Don't 
> worry about structuring.
I did structure the text a little bit and enhanced my proposal by some parts discussed here.

Sebastian
Hi, what can I do to move this along.
> Blocks: 1336680

Middle-cropping is unfortunately not (yet) part of any standard. I'd be happy if it were, though.

Sebastian
See Also: → 1335316
See Also: → 1446830

text-overflow-middle: ellipsis should have been the default in the first place.

Blocks: 1620231
Severity: normal → S3
See Also: → 1844148

For what it's worth, the latest discussion for standardizing a way to do this happens in https://github.com/w3c/csswg-drafts/issues/3937.

Sebastian

You need to log in before you can comment on or make changes to this bug.