-
Notifications
You must be signed in to change notification settings - Fork 707
[css-inline-3] initial-letters; feedback from implementation #4171
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
Comments
#4116 might be able to solve 4. |
The CSS Working Group just discussed
The full IRC log of that discussion<RossenF2F> Topic: [css-inline-3] initial-letters; feedback from implementation<RossenF2F> github: https://github.com//issues/4171 <emilio> faceless: we implemented initial-letters, it works broadly <emilio> ... I think it should be simplified to work in non-latin baselines <emilio> ... the way it's currently defined is that you specify the number of lines that is supposed to cover and the amount that it's supposed to shift <emilio> ... the second parameter is redundant <chris> which was the non-Safari implementation mentioned in passing? I couldn't hear <emilio> ... we already got the ability to shifts baselines up / down using baseline-shift <emilio> fantasai: I think there are a bunch of issues in this issue and we should take one at a time <emilio> faceless: Sure. you can't add margins around the initial-letter... You can add some padding to the right <emilio> ... but it's not great with varying shapes <emilio> fantasai: so proposal would be to apply shape-margin only when wrapping around the glyph shape <dbaron> sounds reasonable <emilio> astearns: so for the rest we apply shape-outside <emilio> fantasai: interaction between shape-outside and initial-letter is tbd <emilio> ... but you can wrap around the glyph <emilio> astearns: makes sense to use shape-margin when shape-outside is none and `initial-letters-wrap: all` <florian> sounds good to me <emilio> RESOLVED: Use shape-margin on initial letter when shape-outside is none and `inlitial-letters-wrap: all` <fantasai> (we're skipping issue 2 in the issue, because it's covered in https://github.com//issues/719 ) <astearns> s/all/all and first/ <emilio> faceless: (describes issue 3 in #719) <emilio> faceless: I think the text about the alignment points is not relevant <emilio> ... once you drop the letter on the first-line it fits right <emilio> fantasai: you need that for shifting caps, that's what it's for <fantasai> s/shifting/raised or sunk/ <dbaron> I think this doesn't work both because it's hard to match the correct size, and because you need to control which lines wrap around the initial letter. <emilio> s/that/the second value of `initial-letters`/ <emilio> faceless: I can try to demonstrate you can achieve the same effects without that value <emilio> hober: I'd really love it if didn't file giant issues like this so that we can clear where the discussion is separately <tantek> +1 hober <emilio> ... this style of bug-filing is very hard to follow <emilio> RossenF2F: That being said all the detail is awesome <emilio> faceless: Let's move to issue 4... You can have atomic inlines as an initial letter, is that allowed? Otherwise it needs to be clarified how to align these <chris> q+ <emilio> ... we discussed about having baselines on svg which would solve this problem, probably <emilio> fantasai: we have an attempt to synthesize baselines for boxes <emilio> ... so cap-height corresponds to top-height of the box <RossenF2F> q? <RossenF2F> ack chris <emilio> chris: this has come up before for images <fantasai> https://drafts.csswg.org/css-inline-3/#initial-letter-box-size <emilio> myles: #4116 is the baselines in images <fantasai> For atomic initial letters, sizing follows the usual rules for that type of atomic inline. However, if the box has an automatic block size (auto), then its block size is determined as for an inline initial letter with border-box alignment, and is definite. <emilio> ... issue I filed a bug <emilio> s/a bug/ a while ago <chris> https://github.com//issues/4116 <emilio> iank_: this is not only for images right? Only atomic inlines <emilio> other atomic inlines too* <emilio> fantasai: I think the spec says how to size the box <emilio> ... so if you set an explicit size on an atomic inline you get that size <emilio> ... if the size doesn't match the amount of space you use the alignment properties to align it in that space <emilio> faceless: I suspect that'd probably do it for now but probably should be explicit about how baselines work <emilio> fantasai: agreed <emilio> faceless: issue 5 <emilio> ... the spec allows for inlines as initial-letter <emilio> ... the initial letter uses font-size not the computed size <emilio> ... so if you use superscripts or what not it produces really odd result <emilio> *results <fantasai> scribenick: fantasai <fantasai> on issue 6 <fantasai> faceless: If you have inlines as part of inial leter, e.g. a superscript in 1st, it doesn't scale up with the rest of the initial letter <fantasai> emilio: what you're proposing is some weird inheritance behavior in first-lin <fantasai> emilio: if you have span in first-line, it inherits from ::first-line <fantasai> fantasai: There's regular element initial letters, and ::first-letter first-letters <fantasai> fantasai: If can't have element in ::first-letter, then it's not a prolem there <fantasai> fantasai: but for regular elements, shouldn't be a problem to inherit like usual <fantasai> faceless: Should set the computed font size based on initial-letter, so that it will inherit as usual and affect the children <fantasai> emilio: Not great, because a lot of stuff depends on font-size right now <fantasai> emilio: would need t compute based on initial-letter <fantasai> dbaron: Might be able to specify the desired results wihtout changing computed value of font-size <fantasai> dbaron: might be more difficult to specify, but more realistic to implement <fantasai> emilio: Can you set the initial-letter size in em units <fantasai> faceless: no, it's derived from the algorithm <fantasai> florian: The algorithm gives you the siz eof the glyph, if we say therefore this must affect the font size, do browsers agree on which font size you get from that <emilio> fantasai: you have requirements for that calculation, to use specific metrics <emilio> ... like, my line-height is X or Y, and the alphabetic-baseline <emilio> ... that's all deterministic <emilio> ... assuming everyone pulls the same metrics <emilio> florian: is there a really a single font-size that gets you the right size? <fantasai> fantasai: yes <fantasai> fantasai: there's only one cap height metric <fantasai> emilio: But the computed line height depends on the computed font size? <dbaron> dbaron: modulo rounding issues <fantasai> emilio: think it's more reasonable to not affect the computed value and then do something, but... <fantasai> florian: Don't need the line-height/font-size of the initial letter, but of the paragraph <RossenF2F> q? <fantasai> emilio: but not easy to find that value at the time you're doing style computation <dbaron> https://wiki.csswg.org/spec/property-dependencies <fantasai> emilio: You cannot get to the containing block, you can get to the nearest display: contents thing... <emilio> non-display: contents thing <fantasai> dbaron: It's not super clear to me whether what you're proposing would make the computed value of font size on layout <fantasai> dbaron: but even if it's not, still refer you to this dependency chart <fantasai> dbaron: if you're proposing to add something, make sure it doesn't create a cycle <fantasai> dbaron: font-size is one of the most basic dependencies <fantasai> faceless: It definitely doesn't depend on layout <fantasai> florian: Computed font size of initial-letter would not affect the lineh height of the parent paragraph, so no circularity <fantasai> florian: The computed line-height of the initial letter affects nothing, so the loop stops here <fantasai> emilio: affects nothing if you don't add lh units or other things that are proposed <fantasai> florian: If you're trying to set the border of your initial-letter to 0.1lh, you can use it, but won't have ripple effects that mess up everything <fantasai> emilio: I still think getting to the right parent paragraph's line-height is not trivial <fantasai> florian: The alternative would be to say that within the initial-letter, a specific set of things do math against the used font-size instead? <fantasai> emilio: You would need some kind of multiplier, which seems OK <fantasai> emilio: You need to multiply by the ratio of the font-size of the initial letter to the computed font-size <fantasai> florian: I'm not concerned about having the ratio, I'm concerned about the whitelist of what it applies to <fantasai> florian: Not understanding the difficulty of inheriting through... <fantasai> fantasai: DIscuss at break? <fantasai> issue 7 <fantasai> faceless: inline boxes don't take width/height anywhere else, doesn't seem like a good idea here <emilio> fantasai: the reason we did this is that you can't make an atomic inline into an initial letter it doesn't resize the font <emilio> ... the content of the inline-block that is an initial letter are not affected by that <emilio> ... what this does is you do the resizing of the glyph as usual <emilio> ... but then you also define the size of the box <emilio> ... this was requested by tantek <emilio> faceless: alright, scratch that then <emilio> astearns: it'd be nice to have a note/example in the spec <fantasai> s/tantek/tantek, to handle the case of colored boxes with initial letters in them, wnat the boxes to all be the same size/ <emilio> faceless: number 8 <emilio> faceless: I'm ok dropping this <emilio> dbaron: can I suggest that the issues that are viable after this discussion should become separate issues? <emilio> ACTION: fantasai to go through the issues after doing the spec work and split the remaining issues <emilio> (or mentor faceless into doing so) |
About 5 years ago I made this use case: "On the 'initial-letter' property, I have previously made the case of I imagined few printers had type founts that exactly spanned the height This case would appear to be approximated to by, for example Section 2.5 shows the calculation for an aligned drop initial (i.e. with If 'initial letter' could additionally take some more direct sizing An example showing this was added by Dave Cramer. In the current draft this is shown as the final case in Example 5 'initial-letters: 2.51 3'. The problem is that I got the initial request wrong. Our putative printer would have packed the initial letters so that the tops of the type were aligned, not the baselines. Is it too late to fix this error? |
I want to sum up where we got to at the last F2F with this unwieldily hydra-issue, close it, and raise new, manageable bite-size issues for the aspects that are still relevant. 1. Allow shape-margin 2. Auto-sizing of element and effect on linebox 3. Alignment and font-sizing 4. Atomic inlines
5. More flexibility in initial-letters values 6. Non-replaced inlines as part of the initial-letter (the "computed font size" issue) 7. Width or height set explicitly on the initial-letters element. 8. font-size (allowing it to be specified) @zed-vector - I edited your comment to add a link to the example you reference. That example shows an initial-letter big enough for 2.51 lines, but dropped 3 lines. I think if you wanted it top-aligned, you'd make it 2.51 lines high and dropped 2.51 lines. This isn't possible with the current syntax, no, but I'll migrate this comment to my followup. |
Yo @faceless2 ! Don't close issues with resolutions until they've been edited in. :) Almost lost track of the 'shape-margin' one here. |
Ack ;-) Sorry. |
Edited in now, so closing. ;) |
We've just been working on initial-letters and have some feedback. As far as I'm aware it's only webkit (with a prefix) offering a partial implementation on this (is this true?). So I realise this specification is in its early days. Here's what we've come up with:
1. Allow shape-margin
For
initial-letters-wrap: all
, there's a definite need for theshape-margin
property, which should apply either to the shape manually specified withshape-outside
or to shapes derived from the glyph outlines. Relying on the end-inline margin is not not flexible enough, say for letters like "Γ" (greek capital Gamma) where you want to push text away from the protruding horizontal stroke, or "C", where without a margin the text could disappear into the mouth of the "C"2. Auto-sizing of element and effect on linebox
Inline initial-letters are auto-sized around the visible bounds of the content; around the size of the glyphs. What's not clear if whether this sizing algorithm should affect the linebox or not:

left-most: our rendering, where we auto-size the initial-letters elements as specified, but we don't push the linebox up to accomodate it.
middle: webkit's rendering, where the box extends down as far as required, but never goes above the cap-height of the letter.
right: a third option - the element is sized to fit the content, and the linebox is pushed up to include it.
You could make coherent arguments for the left or right renderings fairly easily; probably the left is more useful, as otherwise the height of the first line (and therefore its apparent position relative to the top of the block) will depend on its initial letter, which is likely to annoy someone at some point. I'm not sure Webkits approach will work for non-latin scripts; it's not testable as Webkit doesn't seem to support anything other than alphabetic alignment. Which brings me neatly to my next point.
3. Alignment and font-sizing
Alignment and sizing are two sides of the same issue for initial-letters. The specification goes to some length to describe how the letters have two alignment points - a two-line drop letter "A" would have its top top alignment at the cap-height of line one, and its bottom alignment at the baseline of line two, as shown with this example from the spec:

But this description only makes sense for fully dropped letters, i.e. where
sink==size
, and it necessarily fails if the lines aren't all the same size as the block element'sline-height
, as demonstrated in https://drafts.csswg.org/css-inline/#initial-letter-block-position.So while this description is helpful to understand the intention of the specification, I think it should be clear it's no more than that. When you come to implement it, you're positioning the text on the first line without any knowledge of what's to come. Layout necessarily goes like this:
initial-letters
.For alphabetic text this is effectively what the spec says already. But when aligning on a hanging baseline (for example), the outsize letter will effectively drop without any further shift.
The Hindi initial-letter was aligned on the hanging baseline of the first line. That's all. No further shift was required. In fact with
dominant-baseline: hanging
on the paragraph andalignment-baseline: baseline
on the first-letter, there's no need for theinitial-letters-align
property to exist at all.I would suggest dropping it completely and simply using
alignment-baseline
exactly as it is defined for regular inline elements, although perhaps disallowingtop
,center
andbottom
as values."But what about atomic inlines", you may ask?
4. Atomic inlines
Atomic inlines such as images can be used as an initial letter as the spec is now, and the intention appears to be that they're aligned based on the same alignment points derived from the
initial-letters
property. But the spec is silent on the mechanism for this. I presume the height is to be set then the width scaled to match? For example, if using an image:then the image will need to be scaled to cover three lines, and its top aligned with the top of the first linebox. Again there's no need for
initial-letters-align
: the "border-box" value of this property looks like it is intended to set the position and size of the image to be identical to the layout results you'd expect from this:or, for that matter (and discounting the differences in break opportunities):
The same process applies to elements with
display:inline-block
and other inline content generating its own formatting context (see also #4116)To be resolved then: does use of an atomic inline within an initial-letters element automatically set the atomic inline's height?
5. More flexibility in initial-letters values
The initial-letters element itself takes two numbers, the first ("size") determining the font-size via quite a complex algorithm, the second ("sink") the number of lines to shift up and down - not directly, as shown in the hindi example above; it's more a statement of intention as to where the bottom of the drop-cap should be.
As it is now, the "sink" value must be a positive integer and defaults to the "size" value. I don't see why this limitation is required. Make it a number or length describing the vertical shift of the initial-letter. If specified as a number, treat it as if it had an implied "lh" unit. If undefined, the value depends on the baseline: for alphabetic, it's the same as "size", for hanging or hebrew it's 0. And allow it to be less than zero if that's what the user wants.
Why? First, (like @tabatkins I believe) I dislike unitless numbers; make them a length so you can do interesting things with calc(). Second, by making this number explicitly "the distance to shift the text" it removes any confusion around the fact that
hanging
baseline text is dropped by default, whereasalphabetic
baseline text is not. It also opens up other alignment options, such ascenter
ormathematical
which might need finer adjusting (I can't think of a use for these, but I can't think of a reason to disallow it either). Finally, it's no harder to implement.Thought of as a length, its functionality is identical to
baseline-shift
. I'll leave that out there, perhaps greater minds than mine will have some ideas on reconciling the two. If there's an appetite to remove the "sink" parameter from initial-letters completely and replace it withbaseline-shift
, I don't see why that wouldn't work.6. Non-replaced inlines as part of the initial-letter
The idea is you can have an initial-letter made up of more than just a single text node. It is described in the specification and even an example given, with image:

This corresponds to
While I think this isn't a bad idea, the problem will come with the font size. The spec states that initial-letter sets the used font-size only, not the computed size. Well, this becomes a problem when you have more than one element. The nested
<b>
above would inherit the computed font size, not the used size: effectively it's getting the font-size of the parent block.You could insist that font-size is calculated with the magic algorithm for the entire subtree, but that seems unnecessarily restrictive. I can't think of many situations where this would be an actual problem; there may be better examples in other languages, but in English the best I can do is:
Frankly, for all the hoops you would need to jump through to fix this, you may as well just say that using the
initial-letters
property on an element sets the computed font size, not just the used one. I'm not sure what problem the current specification was trying to avoid by not doing this, but I'm not sure it's worth it.7. Width or height set explicitly on the initial-letters element.
The spec explicitly allows to have width or height specified, and section 5.7.1 describes how to align content within this box if required, using
text-align
oralign-content
.Personally I think this is a very bad idea. Inline, non-replaced elements do not take a width or height anywhere else in CSS, and I think there's no need to make them do so here. If you want to give the box a particular size, just use
display
to set toinline-block
orinline-flex
. If you're settinginitial-letters
on a<span>
this is trivially allowed; allowing limited values of display to be set on a ::first-letter pseudo-element is perhaps not an insurmountable issue either. I think this approach would be easier to understand and implement than describing some special, initial-letters only alignment rules for elements withdisplay: inline
.8. font-size
Once you've done all the above, you've reduced initial-letter from a special thing with complex layout rules, to not much more than a regular inline: positioned like an inline, excluded like a float. The only particularly special feature remaining is the font-size. For even more flexibility at the cost of virtually nothing from an implementers point of view, why not set the font-size to its magically calculated value when initial-letters is set, but allow the user to override this if they want? i.e. if they specify
font-size
it is respected, but if it's left unset, its value is computed using the initial-letters algorithm.I don't have a real use-case for this, but again I can't give a reason why it needs to be prevented. So why not?
Summary
Lots there, but to sum up my suggestions would be:
shape-margin
on initial-lettersalignment-baseline
andbaseline-shift
on initial-letters; use them as you would normally for inline content, and instead drop theinitial-letters-align
property.initial-letters
the vertical distance to shift the letter (a length), rather than the number of lines the initial letter should sink (a unitless value). Set its default based on the initial-letters "size" and the alignment.width
andheight
on initial-letters withdisplay:inline
. If these are required, the user can useinline-flex
orinline-block
.The text was updated successfully, but these errors were encountered: