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

General discussion about UX #8

Closed JayPanoz closed 6 years ago

JayPanoz commented 6 years ago

Although I do think this repo might not be the best place to discuss User Experience—it’s more implementation-centric—, it is worth having a general issue imho. Indeed, we can’t have a clear separation of concerns there, the CSS design impacting UX and vice versa.

While discussing Readium CSS during the Readium 2 conference call yesterday, UX has been one of our major concerns. And I do believe @DanielWeck and @HadrienGardeur are right about that: defaults, themes, user settings are not just styles we add and remove, they are tools we offer to users. Now, one of our top priorities is building a good experience so that users can focus on, and enjoy reading electronic publications.

UX in general, and user research in particular, are by no means easy. They also require quite a budget—please note there has been some DIY tips and tricks lately though. Minimal (DIY) usability testing is I guess critical because very little user research on Reading Systems and ebooks has actually been published so far.

Anyways, Readium CSS design is pretty modular, with a lot of user settings. It doesn’t mean developers have to implement all those settings, obviously. What we want to offer is flexibility, so that implementers can do as they wish:

There are small details we must take into account. For instance, what we discussed yesterday:

Of course, there are a lot of other UX issues we’ll have to deal with as we go along. So please feel free to use this issue to report and discuss them. We will then be able to make recommandations related to UX in docs.

JayPanoz commented 6 years ago

While testing user settings yesterday, I was quite concerned with an UX issue related to font size.

Assumption

Font size will probably be a global setting i.e. when the users set a specific font size, they very likely want it to apply to all publications they’re reading. At least this is what happens with a lot of (existing) Reading Systems.

Issue

We have quite a significant amount of samples for which the base font size is really small: 12px (unsurprisingly, they tend to have the same origin).

12px happens to be our smallest font size setting. For reference, here is our current values for this setting:

  1. 12px = 75%
  2. 14px = 87.5%
  3. 16px = 100%
  4. 18px = 112.5%
  5. 22px = 137.5%
  6. 24px = 150%
  7. 26px = 162.5%
  8. 28px = 175%
  9. 32px = 200%
  10. 36px = 225%
  11. 40px = 250%
  12. Do we need more levels? (I’ve seen 400% used as a reference in a11y testing…)

(Of course, sizes are relative since 100% may not be 16px in all browsers.)

What’s worse is that, in that case, we’ve got useless settings (the smallest one), especially as there is a floor for font-size (which is like 8px in Safari for instance).

As an aside, this is incredibly painful as a user (and bad practice as an author). I don’t have vision problems but 12px makes my reading experience super uncomfortable.

Proposal

Map every publication relative to our settings, which means for instance:

  1. a book which base font size is 12px will be level 1;
  2. a book which base font size is 16px will be level 3;
  3. a book which base font-size is 18px will be level 4.

What happens for the user?

This process would be completely transparent to the user. If level 3 is set, then all books will have a base font size of 16px. It won’t be 12px for the first one, 16px for the second one, and 18px for the last one.

Counter-arguments

Alternative options

Technical details

Getting the base font-size

window.getComputedStyle(document.querySelector("p").getPropertyValue("font-size") might not be the most reliable way to get the base font-size for the publication. Think of complex publications in which the first paragraph may be a lede, or an unsemantic heading, etc.

window.getComputedStyle(document.body).getPropertyValue("font-size") may be a little bit better but doesn’t deal with CSS authoring like

p {
  font-size: 0.875em;
}

Defining the type scale used by the author

Turns out we can get a pretty good average by checking the base font-size and a heading, be it h1, h2 or h3.

In that case, getting the type scale is a one-two punch:

* h3 stops here.

Of course this is related to our specific CSS normalize.

I’ve been able to retrieve a good-enough author’s type-scale for 90% of our samples. For other publications, we could still change the type-scale on a per-heading basis.

danielweck commented 6 years ago

Useful analysis, thanks! Just to record my thoughts on this:

As a user, I would expect the "200%" option to result in the document's text (including interline spacing) to be proportionally scaled by a factor of 2, relative to the original publication's styles. I would also expect (or learn to tolerate) slight discrepancies in the visual output of different publications, because of text size variations in the original documents (as defined at authoring time by content creators via CSS). On the whole though, my user experience would be pretty consistent and satisfactory. There may be uncommon instances whereby scaled documents would look unreasonably smaller / larger (compared with the rest of my ebook library), in which case I would be forced to adjust the system-wide option (and restore my favourite setting when switching to other, more regular publications). I wouldn't expect reading systems to be particularly "smart" in this area (such as attempting to automatically detect unreasonable size discrepancies), because I would recognise that modern interactive multimedia publications ; just like gazillions of existing web pages ; can offer significant stylistic variations. However ; just like with web browsers ; as a user I might expect the reading system to provide a "enhance readability" mode that would present a minimalist and normalised view of rendered documents. Irrespective of how this special "reader mode" would operate under the hood, the "dumb" text sizing method based on a simple scale factor is in fact (based on previous implementation experience) not as easy to nail-down as it sounds. For instance, using CSS alone was not sufficient, and we had to programmatically walk the structure of loaded documents (HTML DOM) in order to apply the scale factor to individual nodes, based on their computed font-size (expressed in absolute points or pixels).

JayPanoz commented 6 years ago

Thanks for your thoughts, @danielweck, this indeed is a complex issue and I must admit I have mixed feelings about the proposal, especially because of edge cases.

So, as usual, I've taken a look at other RSs—“In case of doubt, check interop.”

iBooks

First and foremost, authors can opt-in using the ibooks:specified-fonts true meta in the OPF (or the older com.apple.ibooks.display-options.xml file in the META-INF folder).

When this metadata is set to true, iBooks will respect:

set in the authors’ CSS.

What’s interesting is their “FontsPresets.plist”.

Basically, the authors’ explicit font-family is the first <dict> they’re using, and 1em is the smallest setting available (unlike our current list of values for this setting). They don’t set a line-height.

When the user sets another font, then they customize per font (font-size + line-height, the later depending on the former).

It’s also noteworthy that the user preferences for text-align and hyphens (to be found in iOS global prefs) are then enforced.

In other words, the user picking another font is the signal for some kind of normalization.

Kindle

According to the guidelines, the following font fixes are applied during the upload process (KFX):

Source: Kindle Publishing Guidelines Version 2017.3, page 26.

In other words, they automatically normalize for Enhanced Typesetting. There is neither an opt-in nor opt-out mechanism. But they can obviously do that during conversion.

Play Books

EPUB files are processed, this is clearly visible when side loading a file in the app. Their pagination is quite different from iBooks/Kobo/Readium and at some point, you could find EPUB files were actually transformed into fragments (by using Android File Transfer for instance).

Looks Like they’re managing font-size via JS though. But what’s interesting is that, on processing, they “normalize” keywords, which are one part of our problem (they won’t resize).

If you take a look at this stylesheet, which is the one I can retrieve for one of my files, you can see font-size are set in pixels. In the original file, they are set using keywords, for Kindle Mobi.

Overdrive (online reader)

The author’s CSS is a theme, with an extra checkbox the user can check to normalize font-sizes.

disable

apply

Applying any other theme than the publisher’s automatically normalizes this text scale.

Custom if for more targeted settings (font-family, line-height, etc.).

Kobo

Looks like the setting is relative to the publication base font-size in the mobile and desktop apps. Couldn’t check eReaders.

In summary

We don’t have the luxury of a specific metadata or the processing/conversion of EPUB files so we basically find ourselves in the Overdrive/Kobo situation.

As far as I’m concerned, I still have mixed feelings about this issue: Overdrive’s approach seems the most sensible at first sight, iBooks mapping level 1 to 1em is probably a good idea as well (the 100% font-size in the R2-navigator is indeed quite small at the moment), but some other RSs deal with other preferences as well so it’s also a scoping issue (themes, opt-in checkbox, which styles are normalized, etc.).

JayPanoz commented 6 years ago

And we must of course anticipate User Agent Properties (const), which have just been proposed by Apple for the CSS-Variables spec. Cf. our issue #5.

It is my understanding that in iOS for instance, the UA prop is very likely to retrieve the value set in a11y settings:

a11y-fontsize

[Edit] As a clarification, I guess we’d better at least be in sync with the OS/UA setting e.g. if the user sets a bigger system font-size, it maps to our level automagically so that our settings are not relative to this global setting, especially as those properties will be exposed to authors.

JayPanoz commented 6 years ago

For the record, other styling related to font-size:

When the user font-size is a lot larger (relative to the screen size), one might wonder if we’d better disable this type of styling.

Kindle Enhanced Typesetting is doing this already, I could manage most cases using CSS so it’s up to implementers. Would those normalizes be useful to you?

JayPanoz commented 6 years ago

We’ve been discussing line-height lately, since some publications don’t have one set in their CSS. We’ll also probably need an explicit line-height for when the user changes the font-family.

Issue

If we don’t provide a base line-height, the normal value will be applied, and that’s quite an issue. On average, it is less than 1.2, which makes leading quite solid. The exception being Iowan Old Style for some reason, with a normal value you would mostly expect (1.375).

As a consequence I moved line-height to ReadiumCSS-base.css so that we can fix this issue in the prototype. The current value is 1.5, which is more or less the “good enough value for most typefaces and configs.”

Assumption

It would probably be a lot better to adjust line-height to each typeface, and the current user font-size (@ 300%, 1.5 is not a really good value anymore).

So I explored dynamic leading, using a calc() function which purpose is:

  1. automagically adjusting the line-height to the current typeface;
  2. adjusting this line-height to the current user font-size.

“Algorithm”

The calc() function is the following:

line-height: calc(1em + (2ex - 1ch) - ((1rem - 16px) * 0.1667));

To sum things up, the line-height is:

  1. 1em = the size of the font-size;
  2. 2ex - 1ch = 2 x-height - 1 character width, in order to take the typeface’s proportions into account e.g. if the font has a small x-height, leading will be less, and vice versa;
  3. 1rem - 16px = the current user font-size minus the 100% one (base font-size);
  4. 0.1667 = a scale which has been defined from an optimal range.

Results

I can get pretty solid results for our font-stacks.

The line-height algorithm for Iowan Old Style

Here is the calc() function with Iowan Old Style.

I’ve checked our other font-stacks and the computed value @ 100% would probably be the one I could deem “optimal” for each typeface (in terms of typographic color).

The major benefit is that it could help us avoid defining an optimal line-height for each typeface in every font-size.

Caveats

@danielweck I know you managed that in Readium, can you see other benefits or points of failure and caveats? My quick and dirty test webpage is available as a gist if needed.

JayPanoz commented 6 years ago

After further testing (±150 typefaces), I can report this works well except for a handful of typefaces e.g. American Typewriter, Libre Baskerville, Bitter, Lexia, Roboto Slab, FF Tisa Pro, etc.

In other words, mainly slabs with a large x-height, thick stroke and medium character width. We’ve got nothing in CSS to check the stroke for instance, so the only solution would be factoring in a thickness factor to make it perfect…

I’m pretty sure this “algorithm” could be improved though, and I’d really like someone to review it because confirmation bias is a thing.

danielweck commented 6 years ago

very useful analytical approach, thanks!

JayPanoz commented 6 years ago

We had a quick (private) discussion about tables yesterday, before the call, and we didn't have time to talk about it so I guess it’s worth listing it in this UX issue since it isn’t entirely in Readium CSS scope.

So, tables, the worst e-production nightmare nobody knows how to turn into a happy-end.

@camill-a has encountered a really long table (4 “pages”) during user settings implementation in the iOS testing app and it’s just vain to try managing that in pure CSS.

Tables are notoriously difficult to manage in a responsive context but well, publications can have a lot of them. For inspiration, here is a recap and listing of solutions by CSS-tricks.

@HadrienGardeur and I agreed that limiting the table size (if needed) and opening it into an external view (like non-linear contents) wouldn’t necessarily be a bad option to improve readability. But there’s probably other options which can be discussed.

table-open

As an author, I wouldn’t mind if the Reading System did that. To be honest, it would even suit me fine for various reasons*.

Footnote

* The major reason being that I’m often being forced to fit super complex tables for which there is no chance at all they will display correctly, even in a 27" screen.

danielweck commented 6 years ago

As always, how does a reading system know whether it is adequate to "take over" the presentation and interaction behaviours for table (or any other large / complex content fragment, likely to be problematic on smaller displays). For example, content creators may decide to include their own handling, like a clickable thumbnail preview which enlarges the full content in a "smart" / responsive way => how can the reading system interpret such cases as "leave me alone"?

llemeurfr commented 6 years ago

Jiminy, you created a fine prototype of "responsive tables" for the OECD this year, presented at the EPUB Summit. Would it be acceptable for authors to follow some design pattern promoted by the EPUB production community, based on this work?

JayPanoz commented 6 years ago

@danielweck Yeah I know, this is the main issue.

At least I can say people expect iBooks to open the table in a modal (double-click/double-tap) so if there are scripts out there, they would probably hijack this event.

@llemeurfr I doubt it if there is no “plug-n-play” script out there. And even if there were, you still have to deal with Reading Systems which don’t support javascript (per EPUB 3.1 spec, I saw that it would be expected only in scroll view by the way, not in paged view).

And it gets even worse with ePub 2 backwards compatibility as overflow won’t work in a lot of devices and apps so you can’t even use that as a fallback.

So, complex tables often end up being images, which was a Kindle recommendation at some point.

I also hit performance issues pretty quickly with javascript at the time (tables have a lot of nodes) and it doesn’t scale at all, you have to create an html file for each table at some point.

So I wouldn't hold my breath about someone finding a solution that can work everywhere, with stellar performance when JS kicks in—and nobody seems really interested in tackling this issue, at least that was the case when I did research for the OECD proto.

JayPanoz commented 6 years ago

Just recording a thought here, as I discussed this this morning: <abbr title="something"> will only have the tooltip on :hover, which means there won’t be any tooltip on mobile. And it looks like this is not necessarily common knowledge by the way.

Once again, the main issue is we don’t know what the author is doing. On the other hand, if we don’t find scripted in the OPF – for EPUB –, wouldn't it be sufficient to at least offer an option to the user so that he/she can improve table, abbr, etc.?

I know this might be naïve reasoning but on the other hand, the more I’m looking at feedback, the more it feels like a significant part of authors are expecting the RS to do such stuff because they can’t find an interoperable solution anyway.

JayPanoz commented 6 years ago

Is this issue still useful considering we now have apps and the UX discussion should probably happened at the app level? Or can we close this issue?

JayPanoz commented 6 years ago

So let’s close this one since those things belong to apps.

I re-read the discussion and only the handling of tables could be re-issued in the apps’ tracker i.e. we may not want to do a lot there but maybe at least open them in a dedicated web view on double-click/double-tap, as some apps have been doing for a while. This would also allow for overflow, should the table be very huge – the whole web view would overflow, something we can’t do in the paged and scrolled views.

So maybe let’s open a dedicated issue for each app if we did not reach consensus yet.

@HadrienGardeur Can you recall reaching a consensus on this one, when we discussed linear="no". I can’t.