3

In this question I'm looking for the cleanest possible solution for the problem below, along with urging the browsers' coders to catch up with the spec, especially :dir() one!!

The problem and it's current best known to me solution:

I'd like to style the image below based on directionality, flipping it, for example, when in RTL mode. The image resides in a shadow DOM. As of now, I'm achieving that with the styling below.

::shadowRoot
    <style>
        .directed-image:dir(rtl) { transform: rotateY(180deg); }    -- Firefox only as of now
        :host-context([dir=rtl]) { transform: rotateY(180deg); }    -- Chromium only as of now
    </style>

    <img class="directed-image" src="..." />

Issues yet to be solved:

  • None of the styles above helping Safari: it has not yet implemented :dir() pseudo class and it's people seems to have a strong objection to :host-context()
  • I'm really not fan of those double-done solutions for a platform's diversity; would like to get rid of those, but this is only a secondary concern

Solutions ?:

The best I'd wish to have is that :dir() will get wide cross browser support - it'll solve the Safari's issue as well as would provide a truly directionality context aware styling (downsides of [dir=ltr] are touched a bit in the WebKit's bug link above).

But given that

-- having all this: is there any other solution for the problem (looking to solve the Safari issue at first priority).

JS based solutions are interesting but much less preferred.

GullerYA
  • 1,320
  • 14
  • 27
  • `[dir=rtl]` would cover all HTML tags with `dir='rtl'` attributes and using a class such as `.rtl {direction: rtl}` should cover the rest...or am I missing something? Better yet a selector like `[dir=rtl], .rtl` would work. – zer00ne Jan 23 '20 at 11:02
  • Assume that user switches the language within the site (I have my own library to do that on the fly, no new site reload needed). The relevant `dir='ltr'` is set on the `body` of course. Now, non `:host-context` able browsers can't match that from within the `shadowRoot`. Class appliance dynamically as per lang. switch (a) requires JS; (b) still won't be matched unless going over each and every shadow host and applying the class directly + using `:host(.rtl)` within the shadow... – GullerYA Jan 23 '20 at 12:37
  • Is the img a custom `[is]`? Why is it in the `shadowRoot`? – zer00ne Jan 23 '20 at 14:03
  • It is just an example, but in this specific case: (a) no, it is not __customized__ (that's the right term) element, (b) it is in `shadow` since my use case is to style it while being __inside__ my custom component. – GullerYA Jan 23 '20 at 16:20
  • `[is]` as in the attribute assigned to a standard tag (ex ``) so it can be treated as a *customized **built-in** element* (that's the correct term). If you need a more encompassing style scope that applies to all Shadow DOM, then gather all `` and ` – zer00ne Jan 23 '20 at 17:13
  • The correction about the term accepted, you are right, thanks. Regarding the rest: practicality of the shadow DOM APIs is out of this scope; saying `styleSheets` is like to say - go JS path, I try to escape that (and even if I do go that way, `styleSheets` is not enough, it won't reflect `dir=rtl` on the `html`, for example). – GullerYA Jan 23 '20 at 19:15
  • Why not `html { direction: rtl }`? I don't see the difference vs. `` – zer00ne Jan 23 '20 at 19:30
  • See [this](https://stackoverflow.com/questions/5375799/direction-ltr-rtl-whats-the-difference-between-the-css-direction-and-html-di) and W3C recommendation there. But we are derailing from the topic here. – GullerYA Jan 23 '20 at 19:58
  • 1
    As you said: the ``dir`` attribute on the ``body`` tag will (in most cases) be the **only** indication of a language change. Since CSS doesn't cascade (as you said) The only option **for now** is for Elements to observe that attribute change. So I *__fear__* your only option is a MutationObserver (in the elements you own) – Danny '365CSI' Engelman Jan 23 '20 at 20:37
  • @Danny'365CSI'Engelman: would you like to publish your comment as an answer and I'll mark it as the accepted one? I'm doing as you said - starting MutationObserver in each custom element that needs to react on `dir` change and set the relevant class on the element self; while CSS is handling the rest via something like `:host(.rtl) {...}`. – GullerYA Jan 25 '20 at 13:02

2 Answers2

1

january 2020 answer:

As you said: the dir attribute on the body tag will (in most cases) be the only indication of a language change. Since CSS doesn't cascade (yet; as you said) the only option for now is for Elements to observe that attribute change. So I fear your only option is a MutationObserver (in the elements you own)

https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver

// Options for the observer (which mutations to observe)
const config = { attributes: true, childList: false, subtree: false };
Danny '365CSI' Engelman
  • 16,526
  • 2
  • 32
  • 49
0

Not sure if this is what you are looking for, but you could use RTLCSS. It's a CSS framework that allows you to easily switch between and create RTL and LTR stylesheets, without having to do too much double work.

It also supports a couple of big CSS frameworks if you use those, like Bootstrap and Semantic-UI

user12711697
  • 129
  • 6
  • Thanks for an answer. I've went over the library and must say that my personal opinion about the architectural design decision taken by that lib is a wrong path: IMHO it imposes ever needed technical debt of maintenance and support for an initially wrong approach. Generally, RTL/LTR should be handled via `flex`, `flex-start`, `flex-end` etc. Those do not need any special rendition (manual or automated of 'inverted' CSS), change the `dir` on the `body` and voila! Rare special cases (not supported by RTLCSS, BTW) like image flip, are app's own concern and must not be delegated to the 3rd party. – GullerYA Jan 23 '20 at 16:11