readium / readium-css

🌈 A set of reference stylesheets for EPUB Reading Systems, starting with Readium Mobile
https://readium.org/readium-css/
BSD 3-Clause "New" or "Revised" License
90 stars 20 forks source link

Vertical writing #19

Closed JayPanoz closed 6 years ago

JayPanoz commented 6 years ago

This will be a tougher one.

Unlike horizontal RTL, for which there is an attribute you can target in CSS (dir), vertical-writing is a CSS property: you need to know its value (and there are deprecated values to take into account if you want to support IE 11). Please feel free to confirm/infirm, maybe I’m missing something obvious there.

We definitely need to constrain the height of the document in scroll mode, when vertical-writing is used, so I’ll probably bet on appending a flag inside html so that we can do that in CSS.

Unfortunately, there is another painful issue we must take into account: -epub-writing-mode (in which the prefix is the culprit).

Blink and Webkit have aliased the -epub- prefix, Gecko didn’t (FYI didn’t check Trident/EdgeHTML yet). Consequently, if the author is using -epub-writing-mode: vertical-rl, it will fail in Firefox, Gecko wants the unprefixed property there.

I’m pretty sure those issues were tackled in Readium 1 at some point, so any hint would be greatly appreciated.

ghost commented 6 years ago

I just checked on Readium based cloud reader and it seems not be handled for firefox. (Here: http://idpf.org/sites/default/files/cloud-reader/index.html?epub=epub_content%2Fkusamakura-japanese-vertical-writing). Thinking about there might(should) be already a bunch of content created in this way, I feel it worth to polyfill it.

danielweck commented 6 years ago

@rakutenjeff this IDPF link points to a very old deployment of the Readium "cloud / web reader". This is the most up to date: https://readium.firebaseapp.com/?epub=https%3A%2F%2Fcdn.rawgit.com%2FIDPF%2Fepub3-samples%2Fmaster%2F30%2Fkusamakura-japanese-vertical-writing&epubs=epub_content%2Fepub_samples.opds (same "kusamakura-japanese-vertical-writing" EPUB from the official IDPF samples, directly loaded from GitHub)

ghost commented 6 years ago

Thanks @danielweck. I just checked the above one on firebaseapp and it displayed horizontally as well.

JayPanoz commented 6 years ago

Just checked with the most up to date and Firefox ignores the vertical writing.

capture d ecran 2017-10-03 a 19 40 34

While it should be

capture d ecran 2017-10-03 a 19 40 53

So, if it only relies on CSS’ vertical writing, I can confirm -epub-writing-mode will be an issue if the unprefixed property is not used as well (this is actually the file I originally used to check support).

JayPanoz commented 6 years ago

And despite native EPUB support, Edge 16 seems to not support it either (so it’s safe to assume IE11/Trident doesn’t).

capture d ecran 2017-10-03 a 20 02 47

JayPanoz commented 6 years ago

EPUB 3.1 spec mapping for future reference, since it impacts a significant list of properties: http://www.idpf.org/epub/31/spec/epub-contentdocs.html#sec-css-prefixed

jccr commented 6 years ago

I have always wondered how the -epub prefixed CSS prop for writing-mode worked out of the box in Blink/Webkit without some sort of JS logic. It's an alias coded in webkit/blink! -epub-writing-mode alias_for=-webkit-writing-mode -epub-writing-mode is an alias for -webkit-writing-mode

danielweck commented 6 years ago

Yes, and CSS property alias deprecation is also an interesting topic amongst browser implementors in the CSS Working Groups ;) (for their own respective vendor prefixes) But yeah, the -epub- prefix is an odd one :)

JayPanoz commented 6 years ago

Yeah they probably added that at the time they implemented stuff they needed for iBooks directly in Webkit. There’s a couple of other extra properties for which they added support (e.g. -webkit-line-box-contain to deal with raised caps) at some point.

But as far as I can tell, they’ve stopped doing that so should they deprecate and remove that, here goes support.

To clarify, the issue really lies in CSS authoring, it’s been bad practice to use prefixed properties without the (at least expected) standard one and this is what we’re having to manage there.

From the EPUB 3.1 spec (emphasizes mine):

CAUTION

Authors are strongly encouraged to use unprefixed properties, and Reading Systems to support current CSS specifications. The widely-used prefixed properties from [Content Docs 3.0.1] have been retained, but support for the other properties has been removed. Authors are advised to use CSS-native solutions for the removed properties where and when they are available.

Authors currently using these prefixed properties are advised to move to unprefixed versions as soon as support allows, as these properties are not anticipated to be supported in the next major version of EPUB.

Unfortunately, we don’t have data so we don’t know how many files use the prefixed property only. But if people actually checked the sample we’re testing there, it means the bad CSS practice might have spread pretty widely.

JayPanoz commented 6 years ago

The dated references may also become a complication, cf. http://www.idpf.org/epub/301/spec/epub-contentdocs.html#sec-css-writing-modes, and it seems that people may want to translate that to:

The rule might have changed, or will change in the future, yet -epub- prefix guarantees behavior consistent to when EPUB 3 standard was defined. (Source: how to article).

I really don’t know how tricky this could become at some point.

ghost commented 6 years ago

I agree with this is rather a bad css practice problem. On the other hand, I am afraid there are (could be) a lot of existing JP contents are created with prefix -webkit- and -epub-. The reason is there is a widely used JP epub template (http://ebpaj.jp/cmspage/wp/wp-content/uploads/2015/04/ebpaj_epub3guide_ver1.1.3-en-1.zip) in the book-template.epub you can see stylesheet (stylestandard.css) is created in this way unfortunately... It would be awesome if can provide some solution to cover those prefix problem.

JayPanoz commented 6 years ago

Oh definitely, this is one of my fears as well, since this is what happened with prefixed properties on the web already: the -webkit- one was used and that’s it, which is why Microsoft had to add support for the -webkit- prefix recently.

So, let’s sum up the current situation:

There might be other browsers we must take into account on the markets impacted.

If we choose to polyfill there, we’ll need to:

@danielweck and @JCCR You’ll be the ones mostly impacted there, as it requires doing things at runtime. Do you have any thought or remark you’d like to add to this list?

I know we’ve discussed that in the Readium 2 engineering call and we agreed that:

But it is starting to feel like this is a problem we’ll have to deal with sooner or later.

[edit] On a related note, we’ll probably have to choose in which repo the polyfill issue should be moved since even if it is related to CSS, it out-scopes Readium CSS quite significantly.

JayPanoz commented 6 years ago

An important detail being that you can’t obviously get the computed style since the property is not supported. Here’s what Firefox returns for instance:

capture_d___e__cran_2017-10-04_a___21 53 40

So we’re entering the dark side of polyfilling CSS there: fetching the stylesheet(s) to find the properties/values.

If we can do that any other way (for instance in the streamer), we’d better try it first.

llemeurfr commented 6 years ago

A radical solution would be to avoid treating such issues "on the fly", but as a "repair" action activated by the user himself. Because after all, the culprit is the missing standard CSS property, and this should be solved once for all in the EPUB file. To do this, we would have to a/ developer a "repair" (or "cleaning") lib b/ offer it as a command line tool and/or c/ plug it into the Readium test apps in some way.

danielweck commented 6 years ago

Yeah, the possible combinations of writing-mode (vertical vs. horizontal) and page-progression-direction (LTR vs. RTL) via CSS direction property, HTML dir attribute, and of course other relevant CSS properties ... leads to some tricky code (in order to work cross-browser):

https://github.com/readium/readium-shared-js/blob/62490d18031c6dd675639b442a7b791274bfe7b1/js/views/reflowable_view.js#L331-L371

JayPanoz commented 6 years ago

c/ plug it into the Readium test apps in some way

On a related note, that would possibly open the door to altering CSS files on EPUB (side) load; some app developers might deem it the best way to fix rendering issues for instance, and use it extensively.

[edit] So to clarify, this is probably something we must factor in and decide to espouse/limit.

JayPanoz commented 6 years ago

It appears PostCSS could be an option for such a lib/tool, at least in some cases: it can indeed be browserified: https://www.npmjs.com/package/browserify-postcss (and is being used to parse CSS for existing polyfills).

Whether this should be a global solution, I really don’t know, but it would help us quite a lot since we would just have to create plugins in that case.

JayPanoz commented 6 years ago

So I’ll try to create a PostCSS plugin for next week, so that we can at least have that in the meantime – and it will be useful for our own testing anyway, because I really don’t want to edit a lot of CSS by hand.

Hopefully, this plugin will be usable with PostCSS-cli (command line interface), which is available as a node package.

JayPanoz commented 6 years ago

So I just init’d a very very alpha version of a PostCSS plugin to deal with -epub-props unprefixing. This monstrosity is available @ https://github.com/JayPanoz/postcss-epub-interceptor

Don’t judge me for the code please, I had to do one practical implementation to get all the details in the EPUB 3.1 mapping – this is kind of a labyrinth, especially as it deals with those props back to EPUB 3.0.0 – and it ended up messy; i’ll redo it asap now that it is clear to me.

Since it works OK on all the files I could test, I decided to publish the repo early should anyone want to help. So please feel free to improve it if you can/want. 🙏

JayPanoz commented 6 years ago

On a related note, writing-mode is screwing columns big time when set on the same element (html) so we’ll probably have no other choice than to check and sanitize it (i.e. moving it to body).

fs-smaller

I’ve just check how iBooks is doing it and they indeed have to do this – idea for the next revision of EPUB: forbid styling for html/:root since it’s been a constant issue when dealing with pagination.*

[edit] As a clarification, yeah I know -webkit-column-axis is a thing but it’s obviously non-standard and undocumented, and iBooks itself is not using it. Consequently, I do think it would be a lot safer to find another solution to this issue, especially as prefixed properties are going the way of the dodo.

Footnote

* I can neither confirm nor deny this is a joke.

danielweck commented 6 years ago

In Readium "1" (readium-shared-js) CSS columns are laid on the y-axis in HTML documents with vertical writing mode (typically in Japanese, also right-to-left page progression direction)

JayPanoz commented 6 years ago

Further info: this issue may be a lot bigger than I personally expected.

Indeed, I’ve spent this Thursday and Friday doing InDesign training, which reminded me that InDesign doesn’t output all the necessary properties in the generated CSS.

For instance, it outputs -epub-hyphens and -webkit-hyphens but not others, in at least some previous versions (couldn't check CC 2018 yet).

Here’s some example output:

body {
    -epub-hyphens:auto;
}
h1.titre-1 {
    -epub-hyphens:none;
    -webkit-hyphens:none;
}

They’re not even using the standard prop… which is really, really, bad since prefixed properties are an endangered species.

Assuming they’re doing this for such highly used properties, they might be doing this as well for writing-mode, which would imply quite a significant impact at the production level. I must still check but I don’t necessarily have high hopes they’re doing it well for this one.

At some point, we might create guidelines for authoring tools, as their impact is hundredfold.

JayPanoz commented 6 years ago

So I can confirm EPUB files created with InDesign only get the -epub- properties by default (some authors might be adding the unprefixed property afterwards but I guess such authors would be in the minority).

Example output from the latest version of InDesign (CC 2018):

body {
  -epub-writing-mode: vertical-rl;
}
span.j-tatechuyoko {
  -epub-text-combine: horizontal;
}

Quick question to @JCCR and @danielweck: what would be the possibility and impact of parsing CSS before opening those files, adding the unprefixed properties (and necessary prefixed ones), and overwriting the stylesheet so that the issue is fixed once and for all, as @llemeurfr envisioned?

In theory, we could:

  1. use PostCSS
  2. create a config using the following plugins:
  3. browserify PostCSS + its config

But it also means the stylesheets must be read and written, and that would bring some complexity. It is my understanding that if we want to make it work reliably for all files in IE 11, Edge and Firefox though, we won’t necessarily have a lot of options. So the other question is whether you want to do it in the first place.

JayPanoz commented 6 years ago

I’ve been documenting -webkit-column-axis and -webkit-column-progression a little bit. For further reference, I’m recording this research there.

It was primarily meant for the setPagination API available in the UIWebView, which goal was to provide app developers with an easiest way to paginate contents using CSS3 multi-columns.

To the best of my knowledge, this API simply doesn’t exist in the WKWebView and, from testing, it doesn’t make any difference in Safari. Also, Google removed it from Blink more than 3 years ago. In other words, it shouldn’t have any impact in a logical world. But… it looks like it actually does.

Here are interesting commits:

Those two properties still live in Webkit (probably as legacy for iOS < 8) but I’ve checked iBooks in details and found no evidence they are using them for pagination.

To put it simply, I’m unable to tell how long they will be supported (they may well be on their way towards deprecation and removal) and, more importantly, don’t know if that could be a bug in the WKWebView.

JayPanoz commented 6 years ago

OK so I’ve done extra research to see how iBooks get horizontal pagination right without the -webkit-column-axis.

When checking your link to the cloud reader, @danielweck, I changed the column-width to see what would happen. And we get what we currently have in the R2 iOS test app. That would be expected when checking the spec.

capture d ecran 2017-11-21 a 19 03 36

I checked Safari and… -webkit-column-axis doesn’t seem to deal with that in there.

capture d ecran 2017-11-21 a 20 02 53

I switched to iBooks for the same book. And their columns don’t work like that. Here’s what you get:

capture d ecran 2017-11-21 a 19 09 36

This is what I’ve been trying to do for the last weeks. So I opened the dev tools, and there’s a huge small detail in computed styles.

capture d ecran 2017-11-21 a 19 09 32

There are two writing modes, the -webkit- one, and the standard one. And if you check the value for the standard one, you can see the deprecated lr-tb. Oh joy! Needless to say the sideways-* values which are meant to replace those deprecated ones are not yet supported.

Anyways, I switched back to Chrome, added writing-mode: lr-tb and a dir="rtl" attribute on html but, as you can see, this is not the result we want.

capture d ecran 2017-11-21 a 19 13 23

I got even worst results with Safari BTW, it’s not even worth adding a capture because it fails dramatically.

What’s kinda fishy is that both -webkit-writing-mode and writing-mode seem to be applied in computed styles. I don’t know whether this is a bug or not, but it’s kind of worrying.

If iBooks has some kind of magic behind the scenes, this is even more worrying, because this is already an insane interoperability mess and I’m starting to wonder whether we should not just disable the 2-column view for vertical writing.

JayPanoz commented 6 years ago

So I went the extra mile and checked styles at runtime on iOS 11.

Here’s what I could get:

photo 22-11-2017 00 20 51

photo 22-11-2017 00 21 04

photo 22-11-2017 00 21 26

No columns, no use of -webkit-column-axis nor -webkit-column-progression, nothing. They’re not even appending a __ibooks-writing-mode on html.

I’m actually starting to wonder whether their :root is not something else than html like say, a phantom container for EPUB contents, or if they have access to some private pagination API.

JayPanoz commented 6 years ago

TL;DR: see first log in the following screenshot.

photo 22-11-2017 01 47 46

If this sniffing is reliable, they’re still using the UIWebView – and its pagination API. Consequently, they would use the MacOS’ WebView as well, which would explain why text scaling, content alignment, typefaces, etc. are managed at a higher level than CSS (checked the methods available and it makes sense).

I guess it’s not worth trying to achieve those results with CSS, we have nothing reliable to deal with the axis on which columns should be laid out, and we should obviously avoid nasty CSS hacks to make it happen.

JayPanoz commented 6 years ago

My research probably ends here – sorry for the flood.

This is the closest result I could get in pure CSS. As you can see, this is kind of nasty since it implies managing different writing-modes and directions, the column-axis and the column-progression (also, vertical writing doesn’t play very nice in this horizontal column layout since it just overflows the columns, it doesn’t flow from one column box to the other).

capture d ecran 2017-11-22 a 10 46 31

capture d ecran 2017-11-22 a 10 46 22

JayPanoz commented 6 years ago

So I’ve tried to convert our page model to vertical writing, here is the result on Codepen.

capture d ecran 2017-11-25 a 16 36 37

capture d ecran 2017-11-25 a 16 36 42

I hope this would be acceptable as there is an insane lot of issues to deal with at the CSS and JS level. We’ll probably have to constrain the size of the web view/iframe though, I can’t tell for sure but I guess readers probably don’t want text to run full-width.

JayPanoz commented 6 years ago

So it turns out that if you set -webkit-column-axis: horizontal on this demo, it will work as you would expect in Safari (columns laid ou on the inline i.e. x-axis).

That’s obviously not cross-platform but it’s super weird (this is the first time it works as expected, and sizing is a complete mess as widths have to be sized depending on the height of the viewport, etc.).

JayPanoz commented 6 years ago

Recap and demoes for this retro-engineerathon are available here, so that you know it has been reported to the CSS Multicol editors.

JayPanoz commented 6 years ago

OK so, a proposal for vertical-writing pagination:

At least there are example of columns laid out on the y-axis in the Requirements for Japanese Text Layout doc so I guess it would not feel unnatural to do so in portrait.

From my point of view, the impact on Readium CSS shouldn’t be significant, and it won’t make our page model more complex.

The biggest impact is outside of Readium CSS, though, as we’ll need to flag documents for vertical-writing, which means we’ll have to check it during runtime.

JayPanoz commented 6 years ago

there’s a possibility we could offer a “modern” option which would lay out docs with writing-mode: horizontal-tb. But I must do some extra research there.

That was pretty naïve in hindsight. I’ll indeed have to list all the adjustments needed for each writing-mode (and there’s quite a lot, from typefaces which should be used to <ruby> alignment…)

danielweck commented 6 years ago

Thank you for the thorough analysis. The Readium1 (ReadiumSDK / ReadiumJS) implementation is naive in the sense that it displays only a single "page" (CSS column) even when the visible viewport gets tall / wide. So it is nice to see some "proper" thinking being put into this, and ultimately we will get some help / advice from "proper" CJK experts too :)

danielweck commented 6 years ago

PS: another caveat with Readium1's use of Y axis to layout columns (i.e. "pages") in vertical writing mode is that animated page transitions (e.g. manual drag or automatic swipe) must be on the Y axis too, when instead they should really follow the horizontal block-level flow. The reason why columns are stacked on the y-axis is because the default x-axis didn't work at the time in Webkit and Chromium -based webviews, due to viewport width/height and other constraints such as column content balancing (not sure exactly why anymore, it was a long time ago). Anyway, I'm really exited that we (you) are now testing all this state-of-the-art stuff with the most recent browser incarnations!

JayPanoz commented 6 years ago

Thanks Dan.

I’ll probably sum up text layout requirements for CJK in our docs, so that implementers know what’s important, what can be done, etc. I must admit that some requirements can be pretty cryptic from my westerner point of view (the Japanese doc is quite poetic in some places for instance, and I must get used to this conception of typography) but it gives formulas and clear guidelines to do well.

Here’s the list:

I quickly checked the docs and the good news is that we can assume that:

  1. if page-progression is RTL;
  2. and if language is Chinese, Japanese or Korean;
  3. then it’s vertical writing;
  4. columns on the y-axis are OK.

and that:

  1. if page-progression is LTR;
  2. and if language is Chinese, Japanese or Korean;
  3. then it’s horizontal writing;
  4. columns on the x-axis are OK.

If confirmed (I’ll really need a confirmation there, from content providers), that would solve quite an important issue we currently have.

The not so great news is that to switch from vertical to horizontal, we’ll obviously have to change the page-progression on the fly… but there’s a lot more. Indeed, parentheses, punctuation, quotes, characters themselves, and even typefaces, etc. must be changed as well. This is probably why you often find an horizontal.css as an alternate stylesheet.

So to sum this up, I’m not sure content providers will be happy if we have a horizontal/vertical writing user setting.

The very bad news is ruby, which is a super complex system based on multiple factors (type of font for which it is applied for instance), with different alignements based on hotizontal/vertical writing, sizes based on the reference character, the font-size and the number of characters in the ruby (2, or 3), etc. And some shouldn’t wrap.

@llemeurfr I can already tell that we’ll need reviews from experts for the CJK-related docs. They did their very best for the Text Layout requirements docs and share a lot of insights and useful information, but some details clearly require another way of thinking.

In Japanese for instance, harmony and gravitational forces are prevalent. So if I get some details wrong, it’s as if we typeset the ebook super badly.

JayPanoz commented 6 years ago

I’m recording this so that we can keep it in mind.

On a related note, it looks like Readium-shared-js is currently not managing horizontal-tb documents as it should in vertical writing publications, according to the Japanese Text Layout Requirements—and this is a popular use case we’ll have to deal with.

This is how such documents are rendered:

capture d ecran 2017-12-02 a 13 59 04

It looks like documents are starting on the left “page” but with a direction (dir="rtl") of right to left (cf. text-indent and text-align), with a page-progression-direction of left to right.

Now It should be:

photo 02-12-2017 14 02 26

Documents starting on the left “page” with a direction of left to right, and a page-progression of right to left.

Next pages on the left are:

photo 02-12-2017 14 02 31

photo 02-12-2017 14 02 36

After verification, this would be the expected result for such a use case.

Here’s a test file and the captures if needed.

vert-horz-mix.zip

JayPanoz commented 6 years ago

Safari/webkit issue when switching from columns → scroll with vertical-specific CSS: fragmentation isn’t updated properly (related to padding in our case), and you’ll get a gap inside paragraphs, as if scroll was paginated.

capture d ecran 2018-01-22 a 16 41 57

Chrome is OK.

JayPanoz commented 6 years ago

So I can indeed confirm that for some reason, Safari has a fragmentation update issue when switching from columns to no columns (don’t know if it is scoped to iframe at the moment).

Safari Paged view reference

safari-paged

As you can see, when switching to scroll, there is a gap exactly where the flow has been fragmented in columns.

safari-scrolled

Here’s Chrome for comparison.

Paged reference

chrome-paged

Scrolled, no gap:

chrome-scrolled

Issue doesn’t seem related to -webkit-column-axis (which i tried to reset for scroll, to no effect), root sizing (min|max-height) nor column-gap. It even isn’t consistent with the padding-left|right set for root. The gap is just here, as if Webkit re-used existing columns and laid them out next to one another instead of just resetting fragmentation…

It also only occurs in writing-mode: vertical-*, we didn’t have this issue so far.

JayPanoz commented 6 years ago

Issue fixed in this commit, turns out to reliably force a relayout in Webkit, we must force it on body.

In our case, we can force it with body’s max-width (horizontal) or max-height (vertical) through the --RS__maxLineLength variable, which was already the case for “number of columns” user setting anyway.

So now we know.

JayPanoz commented 6 years ago

One thing we may want to pay attention to during the beta: vertical-* writing modes on mobile devices in portrait orientation.

I’m kinda clueless there, as it means 5–6 lines of vertical text in some configurations and the reading experience is subpar, to say the least. Don’t know if users are switching to the landscape orientation in this case but it’s quite uncomfortable otherwise.

JayPanoz commented 6 years ago

It’s safe to assume we can close this issue and “fork” it into another one discussing the handling of missing prefixed CSS properties, as it doesn’t apply to vertical writing only, in the web app context. I just opened an issue on the Readium-NG repo (see above) as Evident Point will probably be the first encountering and solving it.

I’ll consequently create a new issue and close this one if no one disagrees.

JayPanoz commented 6 years ago

Please use issue #44 to discuss the remains of this issue from now on. Thanks!