Skip to content
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

[css-pseudo] Problems with styling ::first-letter with punctuation #2040

Closed
fantasai opened this issue Dec 4, 2017 · 18 comments
Closed

[css-pseudo] Problems with styling ::first-letter with punctuation #2040

fantasai opened this issue Dec 4, 2017 · 18 comments

Comments

@fantasai
Copy link
Collaborator

fantasai commented Dec 4, 2017

Johannes Odland wrote in https://lists.w3.org/Archives/Public/www-style/2017Nov/0024.html :

Hi

According to Selectors Level 3 the ::first-letter includes punctuation that precedes the first character. The example specifically shows a dropped cap with an opening quotation mark.

Although there are no hard and fast rules for initial caps, it is a common typographical practice to style the punctuation different than the letter itself. The punctuation can hang in the margin, and be styled in the same font and font-size as the body text so that the initial letter is flush with other initial letters that does not have punctuation.

In Norwegian typography it is considered bad practice not to leave the letter itself flush with the other letters.

http://theworldsgreatestbook.com/book-design-part-6/
http://www.typografi.org/dropcaps/initialer.html
http://www.typografi.org/dropcaps/assets/lite-sitattegn_714.jpg

As the spec is now it is hard to achieve good drop caps.

Should there be a way to select the initial-punctuation also?

@fantasai fantasai added the css-pseudo-4 Current Work label Dec 4, 2017
@fantasai fantasai changed the title [css-pseudo] Selecting first letter skiping punctuation [css-pseudo] Selecting first letter skipping punctuation Dec 4, 2017
@dauwhe
Copy link
Contributor

dauwhe commented Dec 4, 2017

If we have initial punctuation with an initial letter, we usually omit the punctuation.

@johannesodland
Copy link

It is possible to omit the punctuation in some cases.
A coherent solution would be to hide the punctuation using css.

Say that you create a stylesheet for feature articles. You want to control both how the drop-cap looks and how to handle the punctuation. Leaving it up to writers/authors/journalist to remove the punctuation if there happens to be a drop cap is a fragile solution. If you decide to change the stylesheet later on you would have to go back and edit the content as well.

If you choose to hide or hang your punctuation, it should be possible to do so using css.

@fantasai fantasai changed the title [css-pseudo] Selecting first letter skipping punctuation [css-pseudo] Problems with styling ::first-letter with punctuation May 24, 2018
@fantasai
Copy link
Collaborator Author

OK, so new proposal is to have a ::first-punctuation pseudo-class, which is a child of ::first-letter, and which selects the punctuation which is part of ::first-letter. Then such punctuation can be styled or hidden accordingly.

Hanging the punctuation can be done with hanging-punctuation: first.

@johannesodland
Copy link

What's the status of the ::first-punctuation pseudo class?

@plinss
Copy link
Member

plinss commented Jul 16, 2020

I like the proposal for a child pseudo-element. I'm not sure of the status of nested pseudo-elements being legal, but it's a bridge we need to cross at some point anyway (if we haven't already), so let's not let that stop it.

  1. I suggest that it be called simply ::punctuation, the first- is redundant if it's a child of ::first-letter. Also if we ever extend the notion to other pseudos like ::marker we can simply re-use it rather than have ::marker-punctuation.
  2. There are examples of punctuation following the first letter being included in a drop cap, e.g. L' in French. I presume in that case punctuation following the first letter would also be a ::punctuation pseudo-element. Which then allows two of them within a single ::first-letter, e.g. «L'. In principle we could allow selecting them independently with pseudo-classes (once we allow pseudo-classes on pseudo-elements). I'm also guessing the rules about which following punctuation are to be included are likely language specific.
  3. If there are multiple leading punctuation characters, would they all be considered one pseudo-element, individual pseudo-elements, or do we possibly need grouping rules, e.g. does –«L' have two or three ::punctuations? What if there's a space between the dash and quote? e.g. – «L' This isn't relevant unless we can select the individual pseudo-elements with pseudo-classes, but I'm wondering if there's a use case to style them independently (I can see use cases for styling the leading and trailing punctuation differently, e.g. make the leading quote small, but the following apostrophe match the font size of the first-letter.)

@tabatkins
Copy link
Member

We already have nested pseudos, they're fine.

@fantasai
Copy link
Collaborator Author

fantasai commented Aug 5, 2020

More examples: #5154 (comment)

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-pseudo] Problems with styling ::first-letter with punctuation.

The full IRC log of that discussion <dael> Topic: [css-pseudo] Problems with styling ::first-letter with punctuation
<dael> github: https://github.com//issues/2040
<dael> Rossen_: Linked to a lengthier topic from the F2F
<dael> fantasai: As I'm sure many of you saw during F2F when debating drop-caps typical way to present punct like opening quote is style with different font and styling that's closer to paragraph rather than initial-letter
<dael> fantasai: Not always the same as paragraph. Positioned in relation to initial-letter
<dael> fantasai: Super common and a problem for people trying to use drop-caps.
<dael> fantasai: A number of issues surrounding this aspect. Some are about hanging punct, but also being able to select it.
<dael> fantasai: Prop is we add a pseudo-element.
<dael> fantasai: Two prop one is first-punctuation and the other is ::puntuation pseudo class attached to first-letter
<myles> q+ to ask if ::punctuation would apply outside of ::first-letter
<dael> fantasai: You can have multi-characters but you can't have them in the middle b/c only one letter
<Rossen_> ack myles
<Zakim> myles, you wanted to ask if ::punctuation would apply outside of ::first-letter
<dael> myles: Would ::punctuation apply outside of ::first-letter?
<fantasai> ::first-letter::punctuation
<dael> fantasai: I think that would be bad. I think it would be required to be attached to first-letter. You could write ^ but anything else invalid.
<dael> AmeliaBR: I don't want to get into compleixyt of general punct pseudo element. THis is parts of first-letter other than letter.
<dael> myles: Sounds like name is bad
<dael> fantasai: It's selecting punctuation
<myles> s/like name/like the name "punctuation"/
<dael> fantasai: Once concern I have with that approach is in many cases the special style you want is only punct before but not after. There's the one in plinss comment. The em-dash in opening quote would be styled vertically middle to the L but the quote would not read properly there.
<dael> fantasai: If doing special alignment you only want leading but not trailing.
<dael> florian: Is it not included in first-letter pseudo?
<fantasai> –«L'
<dael> fantasai: It is. All the punct in plinss comment is in first-letter pseudo
<AmeliaBR> In “I'm here.”, the “I' are all part of ::first-letter
<dael> fantasai: You have ^ sequence. If we have ::punctuation it doens't make sense for the first 2 to be selected but not the last, but you do need to be able to select them separately
<dael> AmeliaBR: Visual examples I've seen it's only the bits before styled differently
<dael> AmeliaBR: Probably okay at this point to focus on that part. If we see examples to style the after different we can handle it
<dael> florian: I think we've seen some
<dael> AmeliaBR: We need to distinguish them b/c styles not the same
<dael> AmeliaBR: first-letter before-the-letter
<dael> plinss: My prop was apply pseudo classes to those pseudo elements
<dael> florian: So it selects a run and you can do first-of-type and last-of-tyme
<dael> plinss: "L' you have two punctuation pseudo elements
<dael> florian: em-dash " letter punct do you get 2?
<dael> plinss: That was a question in my comment. Several ways of doing it. If there's spce def multiple pseudo elements. If no space don't know
<dael> fantasai: An entire sequence of punct incl the space might be single unit. Flexible with U20 but not other space
<dael> plinss: Looking for use cases with em-dash and quote do you want to style different
<fantasai> https://github.com//issues/5154#issuecomment-659129316
<dael> fantasai: Yes, there was an example ^
<dael> plinss: THen different punct pseudo elements
<dael> fantasai: em-dash and opening quote look same and following different
<dael> plinss: Is there a use case to style differently?
<dael> fantasai: I think that low level we say you should put markup. We should do common case and opening punct being adjusted is common. multi opening punct styled independently might not be common enough for support
<dael> plinss: If you wrap punct in a span they're all in ::first-letter
<dael> fantasai: Insied of them
<dael> fantasai: The people who want to style multi leading punct differently is a very small case. I think when you have the case you markup special without first-letter.
<dael> florian: Concern with impl complexity. If we go character by character the pseudo will be tree abiding but if we grab a bunch it's not always. first-letter is already a mess so manybe not worse, but might be adding
<dael> myles: Why can't ask authors to surround punct with spans? This is getting complex, can't we get authors to do it explicitly?
<Rossen_> q
<dael> fantasai: Once you do that you can't use first-letter. Also, this is a common case. If it was unusal I'd say put a bunch of spans. General case of opening punct being different is part of basic drop cap styling. If we want drop cap to be usable we'll need to support it.
<dael> florian: A run of punct in punct pseudo and you can get 2 of them is good enough for general use case and if you want more complex you pile in spans. I do wonder about impl complexity
<heycam> +1 to the complexity concerns around having the run of punctuation, since it will be non-tree-abiding
<fantasai> s/of spans/of spans, hope that implementers support initial-letter styling on arbitrary spans soon/
<dael> fantasai: I don't have strong opinion of individual or a run. If they are wrap independently will they be kerned together? If it breaks kerning it's a problem. If no doesn't matter much
<dael> florian: If independent we need to get spaces in pseudo
<dael> fantasai: Yeah
<dael> myles: webkit breaks kerning between elements and we view that as a bug. We shouldn't assume different pseudo elements break kerning
<heycam> I am wondering whether the kinds of styles authors want to apply to the punctuation is limited enough that we should handle this with a property rather than more pseudos
<dael> fantasai: What if you have 2 elements side by side. Normally no styling, but give both vertical-align:super will they continue to be a single line? part of problem here is aligning differently here.
<heycam> (for the common cases we want to support)
<fantasai> heycam, I don't think it is... because they want to tweak the font (family, size, and color)
<fantasai> as well as vertical aligment
<dael> florian: Could we do a simplification here? In case of what to style run of punct together you're not having span boundries in the middle. Maybe could make that a tree abiding run?
<dael> fantasai: Yes, could work. Hvae allownces in first-letter if it breaks browser not required to do first-letter. We could do that
<dael> florian: Yeah, browser could do a weird thing that crosses boundary.
<dael> fantasai: Making it tree abiding should be completely possible
<dael> fantasai: So how do we select? punct selector punct selector attached to first-letter?
<dael> florian: Can you use first child or first of type?
<Rossen_> q?
<heycam> random wondering: will this pseudo match quotes inserted with the quotes property?
<dael> AmeliaBR: I don't think anything else with first-child on pseudo elements
<dael> myles: I think we're designing a new feature. Surely that's outside a call.
<myles> s/that's/that should be done/
<dael> AmeliaBR: Yeah. Probably back to issue. Whatever we do it must be tree abiding is one resolution
<dael> plinss: Was a prop for pseudo classes applying to pseudo elements
<dael> Rossen_: I think we went 360 around plinss suggestion. Most was restating how we arrive here.
<dael> Rossen_: Do we have any reasons why ::first-letter punctuation should have effect outside of first-letter? If not reduces choices quite a bit and it comes down to how do we allow pseudo class only on first-letter
<dael> plinss: One of the reasons why switching to ::punctuation we may want to allow in other cases like inside of marker, though not everything
<dael> fantasai: 1.3.4 it selects to period?
<dael> plinss: Maybe. We can look in the future. Why I'm suggesting a more generic name.
<dael> AmeliaBR: IN that case need to distinguish between before or after main thing. Still needs a modifier on punctuation pseudo element. If that's different name or combining pseudo classes we have to design that.
<dael> plinss: Ulterior motive to push pseudo classes
<dael> Rossen_: It's top of hour and we're not ready to resolve. We can continue next week if we're closer.

@AmeliaBR
Copy link
Contributor

AmeliaBR commented Aug 6, 2020

My preference is to keep this as a nested pseudo-element, but with a parenthetical modifier that distinguishes between the before / after.

It would probably also be useful to have a ::first-letter::the-letter-itself pseudoelement (name TBD) so that if you want the font or color to change on the enlarged letter but to inherit from the paragraph for the punctuation, you can do that directly instead of changing it on ::first-letter and then re-setting it on the nested punctuation pseudos.

Example:

<p>“I’m on my way,” she said.</p>

p::first-letter selects “I’
p::first-letter::punctuation(before) selects
p::first-letter::letter-only selects I
p::first-letter::punctuation(after) selects
p::first-letter::punctuation selects both the quote and the apostrophe, separately.

In the case of <p>— « Madame… »</p> example, the string of punctuation before the M would ideally be a single ::punctuation(before) pseudoelement, but if it was <p>— <q>Madame…</q></p> or some other markup structure that breaks up that string in the DOM tree, then there would be multiple consecutive pseudoelements that all match that selector, so the tree with pseudos inserted would look like:

p
  p::first-letter
    p::first-letter::punctuation(before)
      [text]— [/text]
    q [partial, split by the ::first-letter]
      q::before
        p::first-letter::punctuation(before)
          [text]« [/text]
      p::first-letter::letter-only
        [text]M[/text]
  q [rest of the element, outside the ::first-letter]
    [text]adame…[/text]

(Either way, we do need to carefully consider the case where the quotation mark at the start of the paragraph is generated content from a <q> element — that should still be stylable the same as a literal quotation mark in the text!)

I liked the suggestion that the ::punctuation nested pseudoelement would also be useful on ::marker. In that case we'd probably need an additional ::punctuation(separator) modifier for multi-part counters like (6.a.iii). The name of the “everything except the punctuation” nested pseudo-element should also be decided after considering this case.

P.S. I chose “before” and “after” for the modifiers because they are plain English terms already used in CSS, but if people think that it is confusing to re-use the terms another option would be “leading” vs “trailing”.

@fantasai
Copy link
Collaborator Author

Agree that before vs. after needs to be built into the pseudo, not a pseudo-class, because if we go with the idea that it is a tree-abiding pseudo-element, then there are potentially multiple pseudos representing the leading punctuation if there are element boundaries in there.

Wrt ::letter-only, would be nice to pick a word that worked with ::marker, if that's in fact the direction we want to go in eventually. Either way, I'd drop -only.

Wrt color, if we implement fill on CSS generally, you could do it like

::first-letter { fill: fun-color-here; }
::first-letter::punctuation { fill: currentColor; }

:) But that wouldn't solve for font family changes, so you're probably right that we need to have ::letter be separate somehow. This is all getting very complicated. :/

@AmeliaBR
Copy link
Contributor

Wrt ::letter-only, would be nice to pick a word that worked with ::marker, if that's in fact the direction we want to go in eventually. Either way, I'd drop -only.

Yes, definitely, and one of the reasons I emphasized that the name needed work.

Maybe ::value? So ::first-letter::value would match the letter itself, while ::marker::value would match the value of the counter(s). That works for separating out any prefix/suffix defined by an @counter rule, separators inserted by counters() function. But… it's a little strange if you want to handle markers set directly via the content property. For ::marker { content: "(" counter(n) ")"; }, the non-counter strings are equivalent to prefix/suffix punctuation. But for ::marker { content: "→"; }, the string is the marker value.

So… maybe it would be best to focus on a name for the current use case & deal with the counter use case, if need be, with a more explicit name.

@johannesodland
Copy link

Adding examples in case they're needed:

ex3

@acli
Copy link

acli commented Aug 19, 2020

The Norwegian example also applies to English. Bringhurst specifically recommends keeping the initial quotation mark bu style it differently (smaller size, exact size by eye; see 4.1.5).

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-pseudo] Problems with styling ::first-letter with punctuation, and agreed to the following:

  • RESOLVED: Add sub-pseudo elements. Bikeshed name
The full IRC log of that discussion <dael> Topic: [css-pseudo] Problems with styling ::first-letter with punctuation
<dael> github: https://github.com//issues/2040
<dael> fantasai: Basically a requirement that punct associated with first-letter is styled independant of the letter. Sometiems punct is in font of paragraph, sometimes inbetween. Sometimes not colored when letter is
<fantasai> https://github.com//issues/2040#issuecomment-669614648
<dael> fantasai: Need pseudo elements to select first letter different from punch
<dael> fantasai: ameliabr posted ^ which is adding pseudo element which attaches to first-letter pseudo and attaches to only letter and only punct so you can style sep
<dael> fantasai: Other comment is ::marker has similar structure with counter, prefix, postfix. Might want to use same system and maybe same names
<dael> fantasai: Not going to get through bikesheding, but want to ask WG if this is how they want to go about it
<dael> astearns: Not sure about paralel between this and marker. Seem different kinds. But I do like idea of tacking on another pseudo element to first-letter
<dael> fantasai: Do we like idea of one name for punct on both sides with before/after params or separate pseudo?
<dael> florian: Common to style before and after same?
<dael> fantasai: Don't know
<dael> florian: I think that's the answer. If it's common it's useful to style both
<dael> astearns: Less common to have following punct. I would guess when you have both style same
<dael> florian: In French it's not rare. "I' is plausable. I don't know style, though. If want to style ' same as letter you may want before punct different
<dael> fantasai: I can see cases where you want different. Things like em dash you want aligned to center of letter but smaller size. But might not want the veritical align on the apostophy
<fantasai> s/I'/J'/
<dael> astearns: Agree with examples. I'm wrong about not having cases
<florian> example: “J'aime…
<dael> astearns: Other thoughts?
<dael> astearns: Could resolve to have a pseduo element with way to pick apart pieces
<dael> fantasai: pseudo-sub-eleemnt. And we can bikeshed later
<dael> florian: If a shortname falls out we can have it, but we shouldn't explictly try to have one
<fantasai> ::prefix / ::postfix
<dael> astearns: Shouldn't make the same syntax for marker
<dael> fantasai: prefix and postfix perhaps
<dael> astearns: YOu'd like resolution?
<dael> astearns: Objections?
<dael> fantasai: As sub-pseudo elements. Bikeshed name
<fantasai> s/As/Add/
<dael> RESOLVED: Add sub-pseudo elements. Bikeshed name

@frivoal
Copy link
Collaborator

frivoal commented Mar 25, 2021

As suggested by @fantasai during the call ::first-letter::prefix and ::first-letter::postfix seem like a good idea: short and clear.

@fantasai
Copy link
Collaborator Author

fantasai commented Dec 27, 2021

OK, posted edits for this following @frivoal's recommendation to go with ::prefix and ::postfix. Let me know if anything about the edits is unclear, or if anything else needs to be addressed here.

Agenda+ to review the change and confirm the naming.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed ::first-letter punctuation styling, and agreed to the following:

  • RESOLVED: Accept what's in the draft
The full IRC log of that discussion <fantasai> Topic: ::first-letter punctuation styling
<fantasai> github: https://github.com//issues/2040#issuecomment-1001364249
<astearns> changes: https://github.com/w3c/csswg-drafts/commit/aee785be2c270b6f52de066825cb24b3e02c0c3e
<emeyer> fantasai: Want to confirm with the WG that these edits are acceptable
<fantasai> fantasai: Resolved to add sub-pseudo-elements, didn't decide on names.
<fantasai> fantasai: Florian suggested ::prefix and ::postfix, which has advantage of being usable on ::marker as well
<fantasai> fantasai: So wanted to confirm with WG
<fantasai> dbaron: How understandable would these terms to non-English speakers / other English speakers
<fantasai> astearns: ...
<fantasai> dbaron: prefix is much more common than postfix
<fantasai> plinss: Alternative would be suffix, but postfix has better symmetry
<fantasai> astearns: Anyone lining up to implement this?
<fantasai> astearns: Lacking that, I say we go with what's in the draft
<fantasai> RESOLVED: Accept what's in the draft
<tantek> +1 to suffix. better known term than postfix. usability trumps symmetry

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

10 participants