libero / publisher

The starting point for raising issues for Libero Publisher
MIT License
16 stars 4 forks source link

Investigate using postcss-logical plugin for using css logical properties #41

Closed davidcmoulton closed 6 years ago

davidcmoulton commented 6 years ago

Problem / Motivation

As a user who reads in a right to left language, I want the site design to appear with the correct visual hierarchy, even though it was designed and built by people using a language with a left-to-right reading direction.

Proposed solution

Use CSS logical properties. As browser support is not fully there yet, there is a postcss plugin: postcss-logical that can rewrite CSS authored with directional properties to additionally use logical properties.

This should be implemented in such a way as to introduce logical properties as a progressive enhancement, so non-supporting browsers will fall back to using the directional properties.

Tasks

Assumptions

CSS authors are prepared to learn the new syntax. There's a good introduction at https://www.smashingmagazine.com/2018/03/understanding-logical-properties-values/

Changing writing mode orientation perpendicularly looks to be potentially more complicated generally when taking into account CJK-specific considerations. We shouldn't do things to make that harder, but first pass here should get it right for horizontal writing modes first.

davidcmoulton commented 6 years ago

One general thing to consider when perpendicularly changing writing mode orientation within a document: there may need to be an interstitial element of the same writing mode as its parent, which in turn contains the component with the altered writing mode, in order to handle things like float clearing etc. See https://lists.w3.org/Archives/Public/www-style/2016Nov/0044.html (linked to from the Editor's Draft).

davidcmoulton commented 6 years ago

Testing postcss-logical

Testing https://www.npmjs.com/package/postcss-logical locally has identified some problems using the following test code sample:

// test.scss

.test {
  padding-inline-start: 400px
}

The desire is to have the logical properties in the generated CSS, accompanied by equivalent directional fallbacks so that browsers that don't support logical properties use the appropriate padding rule depending on the current text direction. The desired output would be something close to:

/* theoretical desired output */

.test[dir="ltr"] {
  padding-left: 400px;
}
.test[dir="rtl"] {
  padding-right: 400px;
}
.test {
  padding-inline-start: 400px
}

Running the test.scss through gulp-sass and gulp-postcss using the postcss-logical plugin using the {preserve: true} option, it was actually converted to:

/* test.css */

.test {
  padding-inline-start: 400px;
}
.test:dir(ltr) {
  padding-left: 400px;
}
.test:dir(rtl) {
  padding-right: 400px;
}
  1. The main problem here is that the :dir() selector has worse browser support than the logical properties it's providing a fallback for.

  2. Additionally, the rules are inverted: the fallbacks occur after the rule they're backing, and so will overwrite the main rule anyway.

  3. When postcss is parsing scss, postcss-logical doesn't work, but when postcss is parsing css, postcssLogical outputs scss, meaning the style files have to be run through gulp-sass twice: both before and after running them through postcss-logical. I may be missing something here, but it feels like a bug.

The conclusion is that postcss-logical is not appropriate for our use case. The desired effect should be achievable using mixins to allow authoring in css logical properties.

stephenwf commented 6 years ago

Have you tried adding additional steps to your pipe to

davidcmoulton commented 6 years ago

@stephenwf Thanks for the pointer to postcss-dir-pseudo-class. I've tried piping through that, separately trying it with either or none of postcss-scss and postcss-sass. Depending on the ordering of the pipeline, either the generated css file contains sass, or the file contains only css, but with the fallbacks for dir occurring after the code it's supposed to be backing, which still makes it a non-starter really.

Even if this weren't a blocker, the postcss-dir-pseudo-class plugin falls back with, e.g.

// descendant selector
[dir="rtl"] .test {
  ...
}

whereas I think we need the option to have

// same element selector
[dir="rtl"].test {
  ...
}

This is consistent with previous discussions we've had around ensuring each pattern template has the ability to have its own dir attribute (and also its own lang attribute), in case of multiple languages on the same page. The descendant selector generated by postcss-dir-pseudo-class could mean having to insert spurious wrapping elements within patterns in order to cause the markup to match it, which I'd really like to avoid.

Useful as it would be to hand off the generation of fallbacks for logical properties to the build process, it doesn't seem to give us enough control over the final generated css. Reluctantly, I think that writing mixins to handle the fallbacks it is the most reliable way of supporting logical properties.