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-sizing][css-align][css-text] Aligning an aligned block of text within its container #1975

Closed
palemieux opened this issue Nov 10, 2017 · 24 comments

Comments

@palemieux
Copy link

Per the 20171109 joint TTWG/CSS meeting

As illustrated at multiRowAlign.pdf and specified at https://tech.ebu.ch/docs/tech/tech3380.pdf, a common captioning style requires the author to control the alignment of lines relative to the longest line within a block. This styling capability is not currently supported by CSS.

See https://codepen.io/palemieux/pen/yVxZWm . Region 2 illustrate the intended result of centering the longest line and right-aligning other lines relative to the right edge of the longest line.

This capability mirrors the ebutts:multiRowAlign styling attribute at https://www.w3.org/TR/ttml-imsc1.0.1/#multiRowAlign, which is demonstrated in the following sample document, which can be rendered at http://sandflow.com/imsc1proc/index.html .

<?xml version="1.0" encoding="UTF-8"?>
<tt xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns="http://www.w3.org/ns/ttml" xmlns:ttp="http://www.w3.org/ns/ttml#parameter"
 xmlns:tts="http://www.w3.org/ns/ttml#styling" xmlns:ttm="http://www.w3.org/ns/ttml#metadata"
 xmlns:ebutts="urn:ebu:tt:style" xml:lang="en" ttp:timeBase="media" xmlns:ebuttm="urn:ebu:tt:metadata" >
	<head>
		<metadata>
			<ebuttm:documentMetadata>
				<ebuttm:conformsToStandard>urn:ebu:tt:distribution:2014-01</ebuttm:conformsToStandard>
				<ebuttm:conformsToStandard>http://www.w3.org/ns/ttml/profile/imsc1/text</ebuttm:conformsToStandard>
			</ebuttm:documentMetadata>
		</metadata>		
		<styling>
            <style xml:id="baseStyle" tts:color="#FFFFFF" tts:lineHeight="100%"/>
            <style xml:id="blackBackground" tts:backgroundColor="#000000"/>
            <style xml:id="greenBackground" tts:backgroundColor="#00FF00"/>
			<style xml:id="startEnd" tts:textAlign="start" ebutts:multiRowAlign="end"/>
			<style xml:id="centerStart" tts:textAlign="center" ebutts:multiRowAlign="start"/>
		</styling>
		<layout>
			<region xml:id="area1" tts:origin="15% 10%" tts:extent="70% 20%" style="greenBackground" tts:displayAlign="center"/>
			<region xml:id="area2" tts:origin="15% 70%" tts:extent="70% 20%" style="blackBackground" tts:displayAlign="center"/>
		</layout>
	</head>
	<body>
		<div style="baseStyle">			
			<p xml:id="s1" region="area1" style="startEnd" begin="00:00:01" end="00:00:09">
multiRowAlign="end"<br/>textAlign="start"
			</p>
			<p xml:id="s2" region="area2" style="centerStart" begin="00:00:01" end="00:00:09">
multiRowAlign="start"<br/>textAlign="center"
			</p>
		</div>
	</body>
</tt>
@astearns astearns changed the title Support multiRowAlign [css-text-4] Support multiRowAlign Nov 22, 2017
@astearns
Copy link
Member

On first readthrough of the subtitling format spec, I'm thinking this should likely be another longhand of the text-align property, like text-align-last. It would take the same values as text-align-last, and need to be called something that communicated its 'text-align-all-but-longest' functionality. The only thing that comes immediately to mind is 'text-align-inner'

@fantasai
Copy link
Collaborator

fantasai commented Jan 3, 2018

From what I recall from the discussions, this was actually a Sizing issue: it's desired to shrinkwrap around the text after wrapping, which was IIRC possible in some ancient browsers but is not how fit-content works today. Once a block is sized to fit the (wrapped) text content, the regular text-align property will work as expected (and various other layout desires become possible). This is an especially important capability for text-wrap: balance.

text-align-all-but-longest wouldn't work because if there is more space than would fit the longest line (which there typically is), then all the lines would be aligned further to the side than the untouched longest line. We need to size a box around that longest line, so that we can align the rest of the lines to those edges.

@fantasai fantasai changed the title [css-text-4] Support multiRowAlign [css-sizing-4] True Shrinkwrap [solving self-referencing wrapped text alignment] Jan 3, 2018
@fantasai
Copy link
Collaborator

fantasai commented Jan 3, 2018

Thinking about it some more, we could take Alan's solution: the engine would virtually track the edges of that line and apply text alignment to those edges instead of the containing block edges.

But then you have extra space within the box (assuming the longest line doesn't perfectly fit the container, which it usually doesn't). You'd want to align that space as well. The justify-content property effectively does this for flexbox layout, so we could re-use it here as well--values other than normal|stretch would mean that within the containing block we tightwrap a virtual box around the text, and then align that virtual box according to justify-content; meanwhile, text-wrap would operate within that virtual box.

@fantasai fantasai added the css-align-3 Current Work label Jan 3, 2018
@fantasai fantasai changed the title [css-sizing-4] True Shrinkwrap [solving self-referencing wrapped text alignment] [css-sizing][css-align][css-text] True Shrinkwrap [solving self-referencing wrapped text alignment] Jan 3, 2018
@astearns
Copy link
Member

astearns commented Jan 3, 2018

My assumption is that text-align would control how the longest line is aligned within the box (as it does now), and text-align-inner would control how the rest of the lines align to the longest line's endpoints

@fantasai
Copy link
Collaborator

fantasai commented Jan 3, 2018

(Well, technically for Flexbox it's the align-content property; but we're operating in the justify-* axis here.)

@fantasai fantasai changed the title [css-sizing][css-align][css-text] True Shrinkwrap [solving self-referencing wrapped text alignment] [css-sizing][css-align][css-text] Aligning an aligned block of text within its container Apr 4, 2018
@fantasai
Copy link
Collaborator

fantasai commented Apr 4, 2018

@astearns So, we can use a text-align property (which inherits) if we want the set of line boxes that are being considered to be restricted to the direct contents of a block. If we need alignment across blocks, then it becomes more complicated... I'm not sure what TTML needs (@palemieux?), but I imagine more broadly we'll want to group lines of text across block boundaries for this kind of alignment.

@tabatkins
Copy link
Member

tabatkins commented Apr 4, 2018

So how about this: text-group-align: <'text-align'>. Non-inheriting, put it on a block at some point in your hierarchy where you want to apply the group-alignment. This causes the text descendants of the box (down to the next BFC, I imagine) to align as specified in text-group-align, then the length of the largest such line is used to clamp the width of all the lineboxes (down to the next BFC), and they then align as normal per 'text-align'. (And they align with that largest linebox; this is like putting a margin on each linebox.)

So in the first example PDF, you'd specify text-group-align: center; text-align: left; to get the effect.

This is non-inheriting so you can declare it on a particular block that you want all the text inside of to align.

This might also solve some CJK justification issues. It's common to want the longest line to fill the container exactly, and everything smaller to justify inside of that. Right now you can only achieve that if the box width is exactly a multiple of 1ic; if it's not, the text will justify looser than you want. With this, you can do text-group-align: center; text-align: justify and get the effect you want - if the box isn't exactly the right size, the extra space will just be used on either side, rather than being distributed between the characters.

@palemieux
Copy link
Author

palemieux commented Apr 7, 2018

I'm not sure what TTML needs

The longest line within a block is aligned according to text-align, and all the other lines within the same block are aligned within the lateral dimensions of the longest line according to text-group-align.

If text-group-align is not supported, then all lines are aligned according to text-align, which is fine.

@palemieux
Copy link
Author

palemieux commented Apr 7, 2018

it's desired to shrinkwrap around the text after wrapping

@fantasai Precisely. Post-wrapping processing is probably also necessary to support fillLineGap and linePadding. There is a sample implementation using JS at https://github.com/sandflow/imscJS.

edited

@tabatkins
Copy link
Member

Note that in my proposal it was the other way around - text-group-align was the "align the longest line" thing, then text-align applied to all the rest of the lines, constrained within the bounds of the aligned longest line.

@palemieux
Copy link
Author

@nigelmegitt is it preferable that the alignement of the longest line or the alignement of the other lines prevail if the multiRowAlign feature is supported?

@css-meeting-bot
Copy link
Member

The Working Group just discussed Outstanding requests from TTML, and agreed to the following resolutions:

  • RESOLVED: Add a text-group-align property to text 4 with an outline and open issues on that text once it's drafted.
The full IRC log of that discussion <dael> Topic: Outstanding requests from TTML
<dael> github: https://github.com//issues/1975
<dael> fantasai: If you load the first link the first issue you'll get the PDF.
<dael> fantasai: Basic issue is you have a paragraph or a sentence. You put it in a box with a width constraint so it wraps. All the lines of text aren't 100% filled. One is 80% one with 50% full.
<dael> fantasai: You want text left aligned byt the paragraph to be centered in its container.
<dael> fantasai: We can't do this in CSS. TTML would like for us to be able to do this. Different ways to approach it.
<dael> TabAtkins: Line beak is between is and enormous in the example. They want text left aligned but once you have the line breaks center the group and then left align within the established center.
<dael> astearns: Text can do this in a 2 line, they want this in a 3 line scenario
<dael> TabAtkins: And any line might be the longest.
<dael> Rossen: If we have padding auto, that's what they want.
<dael> astearns: Not only centering
<dael> dbaron: Underlying feature is you want to re-shrinkwrap the width of the block and then figure out what to do with it.
<dael> florian: This is a sizing thing or a text effect thing.
<dael> fantasai: If this was laid out with css the left gap would not be here.
<dael> Rossen: You're sure we can't with flexbox?
<dbaron> s/block/block after wrapping lines/
<dael> TabAtkins: Yes. YOu need to re-shrinkwrap after linebreaking and flexbox determines size after linbreaking.
<dael> myles: So you want to layout the first line, figure out the width?
<dael> dbaron: Layout all the lines, figure out which is the longest, and then shrink
<dael> dbaron: You have a size, layout all the line in the size, then change the width of the block smaller so that it's lined up with the widest.
<dael> myles: Does flaots make that real harD?
<dael> dbaron: Probably
<dael> TabAtkins: Solution was a second level of text alignment where it's within the bounds of the longest line. Should be fine with floats, or at least well defined.
<dael> dbaron: You'd have to do work to define what to do with extra bits.
<dael> florian: Driving use case isn't floats driven.
<dael> TabAtkins: And you don't need a second wrapper to get that.
<dael> astearns: You and I TabAtkins have some solution just properties are reverced.
<dael> dbaron: I think what I desc is what browsers did pre-CSS. Like netscape 4 would narrow the backgrounds to make the longest line.
<dael> astearns: To my mind what's happening is here you have a center-left paragraph. We lay it out as if it's left aligned, taking the longest line and centering the whole paragraph. I'm looking similar to text-align-last, I suggested text-align-inner where you say this is acentered paragraph by inner is left.
<dael> floI saw it the other way around.
<dael> astearns: I forgot how TTML asked.
<dael> florian: I htink TabAtkins is better for forward compat. left left is better then fully centered.
<dael> TabAtkins: fantasai pointed out a futher use case when handling some CJK topography where most content-ful should be centered but shorter are justified by the width. Right now you have to size the box with ic unit.
<dael> fantasai: That would solve a complain from CJK that jsutification causes their lines to have space.
<dael> florian: I think there is still advanced CJK alignment, but this gets up most of what they want.
<fantasai> s/space/too much space/
<dael> myles: This is center-left and you're talking center-justified?
<dael> astearns: this is a text-align: left with a tex-group-align: center
<dael> fantasai: And when there's floats you try to shorten as much as the shortened line.
<fantasai> s/shorten as/shift as/
<dael> florian: For TTML float interuption is unimportant, but in CJK we care.
<fantasai> s/line/line would allow/
<dael> koji: So it's a group?
<dael> fantasai: The question we have to think about is from TTML if we only deal with one block it's probably good enough.
<dael> florian: Per BFC instead?
<dael> TabAtkins: I was assuming 2 paragraphs there were use cases to have them the same. Don't cross BFC bounderies.
<dael> myles: What happens if you put it on one paragraph of BFC>
<dael> TabAtkins: It FCs the block or it's ignored because block is not a BFC.
<dael> dbaron: Inherited or non?
<dael> TabAtkins: Non
<dael> myles: Put it on your BFC and hopefully authors knows what a BFC is
<dael> fantasai: I don't think it needs to BFC anything. If we're going to have a block, a section with 2 paragraphs is we want them to be a unit they property has to be non-inherit and when you apply on a section it modifies line box on both sections.
<dael> astearns: More complicated.
<dael> florian: blocka nd to descendencts
<dael> fantasai: You break at BFC bounderies. The block itself doesn't need to be a BFC
<dael> dbaron: It applies to all the lines that are in this block and it's descendent blocks? Only traversing child blocks and not into the lines?
<dael> fantasai: Right.
<dael> dbaron: I feel like scope is similar to first-letter or text-indent for finding things? But those just look at first and this is looking at all?
<dbaron> dbaron: ... never mind text-indent, that's inherited
<dael> astearns: Before we go further into complicating we should ask the TTML people if they want to align paragraphs.
<dael> florian: CJK does
<dael> koji: CJK the whole block is one BFC and then we need to layout everything.
<dael> florian: For CJK case i'm worried about floats.
<dael> TabAtkins: [whiteboards floats]
<dael> TabAtkins: Have big element and a floating picture and some text.
<dael> TabAtkins: This block of lines having a shorter allowed line width is handled separately for the second block?
<dael> Rossen: That would be horrible.
<dael> fantasai: I don't think separate blocks.
<dael> dbaron: Look at the exits, not the lengths.
<dael> florian: floats are aligned to the box
<dael> fantasai: no
<dael> dbaron: So you have some excess on each line, figure out the smallest, and use that for the alignment.
<dael> Rossen: But then add a float o nthe right side.
<dael> dbaron: THere's still excess on each line.
<dael> TabAtkins: Excess you know whichever has the smallest because all the others can be adjustested jsut as much.
<dael> dbaron: Suppose you're crossing multiple blocks and they have different text alignment. You block align it center, and you have a child with right align.
<dael> dbaron: You accumulate excess on both sides and use the smallest from both. I think that's similar. If the left aligns have 0 and the right is whatever is the smallest. If you're then told to center you move the over by that much.
<dael> fantasai: I was thinking alignment after the group alignment. You find out the shortener and then you shrink your line box. Then we center in the remaining space after we apply group alignment.
<dael> dbaron: I think you're right.
<dael> florian: Use cases to make it more complex then TTML wants are CJK. If we're not solving moving the alignement we're not solving CJK.
<dael> astearns: I suuget we design this only at the paragraph level.
<dael> TabAtkins: Won't work if there's floats for CJK. We want the extra shrinkwrapping.
<dael> [everyone talks]
<dael> iank_: We want smartness and things will be complex.
<dael> fantasai: Offset on list is in respect to he edge of the lin with alignment so it'll move with this.
<dael> astearns: Let's get the conversation to one person at a time.
<dael> TabAtkins: I think this needs more design. I don't think we should agree right now, but it's good to get this in fron tof people.
<dbaron> I think the CJK usecase requires the block-level thing that Netscape 4 did.
<dael> fantasai: Before we consider restrict to single paragraph we should hear from TTML to see if it works for them. I think we have agood idea what we want to try and let's see if it works. I would suggest we draft the proposal into Text 4 and work it through as a part of writing.
<dael> astearns: And having sep issues.
<dael> florian: Most solve TTML, nice for CJK
<dael> astearns: Add a text-group-align property to text 4 with an outline and open issues on that text once it's drafted.
<dael> astearns: Obj?
<dael> koji: Early someone mentioned creating an anon block?
<dael> fantasai: I think that's more difficult for the mechanism.
<dael> fantasai: Can you explain the use cases in the issue?
<dael> koji: Yes.
<dael> RESOLVED: Add a text-group-align property to text 4 with an outline and open issues on that text once it's drafted.
<dael> astearns: And we'll talk witht he TTML.
<dael> fantasai: They're looking to edit.

@nigelmegitt
Copy link

Thanks for this, just seen it after a short vacation. @palemieux I don't quite get your question - if you mean "if the multiRowAlign feature is not supported" then the fallback should be that all the lines are aligned as per text-align.

For example text-align: left; multi-row-align: center; would left align every line if it did not support multi-row-align. (I'm not proposing a CSS solution with a property called multi-row-align, just using this "syntax" as a short-hand to try to answer the question)

Does that answer your question in #1975 (comment) ?

@palemieux
Copy link
Author

@nigelmegitt @tabatkins suggests that CSS text-align worked like TTML text-group-align, and CSS text-group-align worked like TTML text-align, if I understand #1975 (comment) correctly. In addition to making the mapping more complex, it also means that the fallback would be the opposite of that of TTML.

@tabatkins
Copy link
Member

it also means that the fallback would be the opposite of that of TTML.

My ordering seems like the more desirable fallback. In the first example in the PDF linked in the OP, where the text is left-aligned but the block as a whole is center-aligned, if you had to only honor one of those I think left-aligning is better than center-aligning. And I think this applies generally; aligning the block of text will usually not have a huge visual effect on things, while individual line alignments can have a dramatic visual effect.

This is largely academic, tho; it just applies to people naively using the block-aligning property without testing for support. We have the @supports rule to let people make more informed styling choices based on actual property support, tho.

@nigelmegitt
Copy link

In the first example in the PDF linked in the OP, where the text is left-aligned but the block as a whole is center-aligned, if you had to only honor one of those I think left-aligning is better than center-aligning.

In the context of subtitles and captions, this would not work well. The "coarse" positioning should have priority over the "fine" positioning, otherwise text that's overall supposed to be somewhere near the centre could be shifted all the way to the left, which is less like the specified intention than centering it. The block alignment is more important than the text alignment within that block.

@nigelmegitt
Copy link

This was just discussed in the TTWG, who thanks CSSWG for taking this up. One point that came out is that regarding #1975 (comment) and #1975 (comment) if what we are considering is a fallback for the case that text-group-align is not supported, then the behaviour should be the same as if if were not set at all. In other words, the fallback for non-support of text-group-align can not depend on support for text-group-align!

@fantasai
Copy link
Collaborator

fantasai commented Apr 27, 2018

@palemieux @nigelmegitt One major question we have is whether this needs to work across blocks or only within a single “paragraph”. In other words, do you choose the longest line only within that paragraph or do you choose the longest line considering some set of paragraphs > 1?

If you choose the longest line only within a paragraph, e.g. the text in two consecutive blocks that have text-align: left; text-group-align: center will not align on the left edge, since they will be centered individually.

@nigelmegitt
Copy link

@fantasai as specified in EBU-TT-D and IMSC 1.0.1, ebutts:multiRowAlign applies to <p> only and is inheritable. The application to <p> implies that it works per paragraph, rather than per set of paragraphs.

@fantasai
Copy link
Collaborator

OK, @frivoal and I drafted up some text for this! Please have a look and let us know if there's any problem.

@fantasai
Copy link
Collaborator

@nigelmegitt
Copy link

@palemieux did you spot the commenter response pending label on this? Might be good to give it a look over.

To me, it looks like it does what is needed.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed Aligning an aligned block of text within its container.

The full IRC log of that discussion <birtles> Topic: Aligning an aligned block of text within its container
<birtles> https://github.com//issues/1975
<fantasai> github: https://github.com//issues/1975
<birtles> nigel: action was with us to check that the draft spec text was ok
<AmeliaBR> draft spec: https://drafts.csswg.org/css-text-4/#text-group-align-property
<birtles> pal: I haven't had a chance to look. What's the right way to test it?
<birtles> nigel: there's draft spec, but no tests
<birtles> ... what is the best thing is to do to create those tests
<birtles> ... we don't have any perspective on implementation
<birtles> florian: it's not implemented
<birtles> fantasai: to get it implemented, write tests, convince browsers to implement it, hire Igalia, implement it yourself
<birtles> florian: as far as the WG is concerned, if the spec is done, there's not much more we can do
<birtles> AmeliaBR: it would be great to have pictures in the spec
<birtles> ... if you are keen on the feature, adding pictures and use cases would help
<birtles> pal: so create a new PR with examples?
<birtles> all: yes

@MatsPalmgren
Copy link

Hmm, why mint a new property instead of using justify-content for this?

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

7 participants