line-height (CSS) is not applied on ::first-line pseudo element

NEW
Unassigned

Status

()

Core
Layout: Block and Inline
20 days ago
5 days ago

People

(Reporter: Nicolas Escoffier, Unassigned)

Tracking

57 Branch
Points:
---

Firefox Tracking Flags

(Not tracked)

Details

Attachments

(1 attachment)

(Reporter)

Description

20 days ago
User Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36

Steps to reproduce:

(Can reproduce all the time)
- create an html element containing a text (that spreads on more than one line)
- apply a line-height (CSS) to this element - for instance line-height: 32px;
- apply a different line-height (CSS) to the first line using the pseudo element ::first-line (or :first-line) - for instance line-height: 12px;


Actual results:

Result: the line-height of the first line stays the same as the rest of the text. Any other style (color, background-color, font-weight ...) is effectively applied but not line-height.


Expected results:

The first line of the text should have a smaller line-height

It works fine in all the other browsers I could test (latest Chrome, latest Safari, latest Opera, IE 7 to 11, Edge).

I built an example https://codepen.io/OxyDesign/pen/8925363c55abdf8e288ec17d50817c95

To my understanding it should be applied as per:
- W3C: https://www.w3.org/TR/css3-selectors/#first-formatted-line
- MDN: https://developer.mozilla.org/en-US/docs/Web/CSS/::first-line#Allowable_properties
Status: UNCONFIRMED → NEW
Component: Untriaged → Layout: Text
Ever confirmed: true
Product: Firefox → Core
Either Layout: Block and Inlines or style system, I'm not sure...
Component: Layout: Text → Layout: Block and Inline
> Either Layout: Block and Inlines or style system, I'm not sure...

I don't think there's a bug here at all.  We apply line-height to first-line just fine.  Just change the "12px" to "120px" in the linked testcase from comment 0 to see that.

The spec at https://www.w3.org/TR/css3-selectors/#first-formatted-line clearly says that "The ::first-line pseudo-element is similar to an inline-level element, but with certain restrictions".  You can't use line-height on an _inline-level_ element to reduce line spacing in a block to below the block's line-height, because the blocks line-height puts a corresponding strut on every line.

I filed https://bugs.webkit.org/show_bug.cgi?id=181209 and https://bugs.chromium.org/p/chromium/issues/detail?id=798257 on Safari and Chrome respectively about the not following the spec here.  Edge's bug system won't let me file bugs, unfortunately....
Created attachment 8939352 [details]
Testcase that I believe at least Safari and Chrome fail

Note that https://drafts.csswg.org/selectors-3/#first-line and https://drafts.csswg.org/css-pseudo-4/#first-line-styling have the same language about ::first-line acting like an inline, so it's not like this has changed since selectors3 went to REC in 2011.
(Reporter)

Comment 4

15 days ago
On the W3c the fictional tag sequences always use <P> and <DIV> tags to wrap the first line. Even when breaking a <SPAN>.
So to me it seemed like it should behave like a block element rather than an inline one.
That's my interpretation but I might be wrong
(Reporter)

Comment 5

15 days ago
For me, an inline element inside text in a block shouldn't be able to reduce the line-height (only increase it if needed) because obviously the text around it needs the line height set. But in the first line pseudo element case, as it will fill the full line no matter what, it feels like it should behave like a block element. If you reduce the font-size for instance, then it makes sense to be able to reduce the line height as well, and it will never impact another line as it's the full line and only this line. If that makes sense
(In reply to Nicolas Escoffier from comment #4)
> On the W3c the fictional tag sequences always use <P> and <DIV> tags to wrap
> the first line. Even when breaking a <SPAN>.
> So to me it seemed like it should behave like a block element rather than an
> inline one.
> That's my interpretation but I might be wrong

<P::first-line> in the spec means ::first-line pseudo-element from the P element, and likely <DIV::first-line>. It says nothing about what the pseudo-element itself should be like.
> So to me it seemed like it should behave like a block element rather than an inline one.

Well, the spec pretty explicitly says it behaves like an inline.  If you think the spec should change, you should probably raise this with the CSS working group...

Note that it's not clear to me whether ::first-line behaves like a block in other ways in non-Firefox UAs or not.  It would need to be very carefully checked for all the properties that apply to first-line and behave somewhat differently for blocks and inlines (text-decoration and background come to mind immediately, but there may be others).  So just saying that the spec should change to having ::first-line be a block may still not end up with the spec and other implementations matching; needs checking.
If I understood correctly, block containers no longer impose a minimum height for their line boxes. What happens is that there is an anonymous root inline box that holds all of the inline-level contents of the block container, and this root inline box inherits the line-height from the block container.
The ambiguity is that the ::first-line behaves like an inline-level element, so it should be inside the root inline box. But the root inline box is an inline box, so its first line fragment should be inside ::first-line (and then inherit line-height from ::first-line instead of the block container).
See https://github.com/w3c/csswg-drafts/issues/1384
> block containers no longer impose a minimum height for their line boxes

As of when?  https://drafts.csswg.org/css-inline-3/#line-height clearly says "The CSS2 specification should be used as the guideline for implementation."  And all the links to line-height in css-inline-3 go to https://drafts.csswg.org/css2/visudet.html#propdef-line-height

In any case, if the working group totally redefines how inline layout works, and actually creates tests to test its new spec, then we can obviously align with that new spec....
Flags: needinfo?(dbaron)
(In reply to Boris Zbarsky [:bz] (no decent commit message means r-) from comment #9)
> As of when?

I don't know when, but this is what I understood from what dbaron said in https://github.com/w3c/csswg-drafts/issues/1551
But maybe I misunderstood what he meant, he didn't confirm...
Right, hence the needinfo for dbaron.
What I was saying in https://github.com/w3c/csswg-drafts/issues/1551 was that when we introduced the "strut" concept to CSS 2.1, it was done because it was seen as a smaller change than introducing the "root inline box" concept, even though I believe the root inline box concept is a clearer explanation for the same things (minimum line-height established by blocks, and how that relates to other inlines in terms of vertical alignment).  I still think it would be better for the relevant level 3 spec to use the "root inline box" concept instead and get rid of the "strut" defined in https://www.w3.org/TR/CSS21/visudet.html#line-height .

I don't see how that debate is particularly related to this issue.  Either way, applying 'line-height' to ::first-line would require an exception from that rule.
Flags: needinfo?(dbaron)
(In reply to David Baron :dbaron: ⌚️UTC-8 from comment #12)
> I don't see how that debate is particularly related to this issue.

If a block container does not directly impose a minimum line height and the fragment in the first line of the root inline box inherits from ::first-line, then the behavior of other browsers seems expected.
You need to log in before you can comment on or make changes to this bug.