Add :truncated to CSS pseudo selector specification


#1

When using text-overflow: ellipsis; it is impossible to determine in CSS whether text has been truncated or not. Although possible with Javascript it’s still non-trivial.

A :truncated pseudo selector, especially when combined with :hover, would allow for a variety of UI interactions that would only be required under that condition.

Considering the following example…

<span data-tooltip="Dynamic string of text that may or may not get truncated">
    Dynamic string of text that may or may not get truncated
</span>

[data-tooltip]:truncated:hover::after {
    content:attr(data-tooltip);
}

#2

Whether or not text is truncated depends on layout, and layout depends on selector matching. Therefore, we unfortunately can not make selectors depend on whether the text is truncated without running into all kinds of circular definition issues. Consider, for example:

<style>
p { font-size: 20px; width: 200px }
p:truncated { font-size: 10px }
</style>
<p>This text is about 14em wide.

If the text is not truncated, 14em is 280px which is more than 200px so the text is truncated. If the text is truncated, 14em is 140px which is less than 200px so the text is not truncated.


#3

Ah, the old circularity excuse ;). We should come up with an answer instead of using that. I’m not an expert, but e.g. saying that it setles after one circle would be fine for me.


#4

Ahh, interesting paradox!

The problem you describe could also be created with the following though…

<style>
    p { display:block; }
    p:hover { display:none; }
</style>
<p>Sad face</p>

Demo here — http://jsfiddle.net/tLe19252/

I would argue that dismissing things because they might be used poorly isn’t a great approach.


#5

What’s the use case? What would you do with this pseudo-class? Let’s start from that.


#6

Well the initial problem that lead me to think of this was while creating a list of report titles. The design called for a fixed width and height of each list item, and the majority of titles fitted within that. However, for the edge cases where title would get truncated we wanted to reveal the full text in a tool tip on hover. It seems distracting and unnecessary to show a tooltip on each item, the user only needs them under a certain condition.

As a work around we had to clone each element, set white-space:normal; and then compare the sizes, remove the clone and conditionally add a .is-truncated class. Clunky and expensive to say the least.

We also have similar problems with large amounts of data in tables. Being able to detect where text is truncated would allow for a more progressive disclosure of content.

In the future I can also see this becoming more useful if the webkit-line-clamp makes it into standards…

p { -webkit-line-clamp: 3; }
.read-more { display: none; }
p:truncated + .read-more { display: block; }

#7

Not an excuse, a reason.

Yes, this is circular, and it’s also really frustrating to deal with because of the unpredictable flickering. (It’s one of only two areas where things are circular in CSS, the other being scrollbar generation for non-overlay scrollbars.) We’d like to avoid adding more, as it requires special handling to break these loops (or just looks terrible, such as in Chrome, where your example flickers).

I would argue that dismissing things because they might be used poorly isn’t a great approach.

That’s not what was said. It’s not that it might be used poorly, it’s that if it is used in this way, there’s no correct answer as to what to do. We can’t define CSS that only works in some situations; we have to have at least some answer for every situation.


#8

Thanks for the clarity, I understand what you’re saying.

This is obviously a huge issue as :hover can be applied to all elements and potentially start infinite layout loops.

I’m far from an expert in internal browser mechanics, but would it not make sense for CSS to define a way that browsers should handle these loop situations if they arise?

The alternative route is to say that you can only change values that don’t effect layout of the element itself. eg, color, box-shadow, and change values on other elements that won’t effect the layout of the truncated element eg, siblings or absolutely positioned pseudo elements / children. Although this feels like it’s starting to get unnecessarily complex.


#9

[quote=“MerlinMason, post:8, topic:621”] This is obviously a huge issue as :hover can be applied to all elements and potentially start infinite layout loops.[/quote] Yes, but importantly, :hover is limited by the speed at which you detect user interaction. For example, you could “fix” it by only checking for :hover states on a mousemove event, so the :hover would trigger, then stay triggered even if the element was no longer under the mouse. When the loop is instead triggered purely by internal processing, it can cycle much faster, and it’s much harder to break or slow loops by rate-limiting parts of the algorithm.

Also, the :hover flicker is extremely annoying, so authors avoid doing it as soon as they encounter it.

Detecting loops is actually rather expensive; it’s much better to avoid making them possible in the first place. We do allow for the possibility of loops in some cases (for example, @counter-style rules can depend on other @counter-style rules; a loop causes them to all break their dependencies), but finding and dealing with loops in layout is, as far as I can tell, too expensive to be worth doing.

More importantly, it doesn’t actually help. :slight_smile: You can’t use the “just don’t use properties that would affect the selector” approach, because as soon as you add a second selector with a different set of properties, the two can communicate: in a rule with Selector 1, you can use a property that affects Selector 2, then in a rule with Selector 2 set up to respond to that, you can use a property that affects Selector 1, thus bypassing the protection and reintroducing the cycle.


#10

What if we restrict :truncated to be taken into account only when coupled with a :hover? Most of the use cases would be about making it possible to reveal truncated text on mouseover. The cycle issue is already handled by the :hover part. It’s simpler with a separate pseudo selector I guess.

It would match only on

  • :hover AND
  • if the element is truncated without :hover

#11

Wondering if :truncated could be added into the JS only part of the selector spec? I think there’s definitely a strong case for needing to find these elements and be able to do something with them and it feels natural as part of a selector.

This keeps any loops out of CSS and in JS, a space where hopefully a developer is more aware of these sorts of issues. The sorts of interactions one might want to have with a truncated element are also more complex so you’d likely be wanting to be in JS anyway to handle them.