postcss-rtl icon indicating copy to clipboard operation
postcss-rtl copied to clipboard

Remove [dir] selectors

Open LFFATE opened this issue 4 years ago • 30 comments

Hello everyone! Thank for your library, but i can't it use for now 😟 For what purpose some styles transformed to selectors with leading [dir] or [dir=ltr]? Is it possible to leave original style with appended rtl rules?

Because there is some issues, for example, i'm using MUI with build-in jss styles and rtl. So, also I use some styles from Bootstrap and at my css there is structure like this: bootstrap.css

fieldset {
  border: 0
}

mui styles

.Mui-some-class-for-fieldset {
  border: 1
}

so by css rules - last with more weight. Class has more weight than tag selector. All is ok aaand after postcss-rtl I have:

[dir] fieldset {...} and .Mui-some-class-for-fieldset {}

So it breakes everything because now [dir] fieldset has more weight than mui selector. How a developer can predict all of this during develop?

I think it's not good to reassign selector`s weights for default direction.

LFFATE avatar Apr 01 '20 12:04 LFFATE

In the GlobaLeaks project actually we have the same requirement. Is there an option for making this?

This is actually very useful to simplify customizations over the generated library.

In fact suppose that a project is using a certain library (e.g. boostrap.css) and have already a customization well writtend to support rtl (e.g. customization-over-bootstra-with-rtl-support.css). After using the current version postcss-rtl probably the customization wont work anymore because you will have added [dir] in front of every css directive. With the suggestion by @LFFATE instead the customization would likely continue to work. What do you think?

evilaliv3 avatar Apr 01 '20 14:04 evilaliv3

@evilaliv3 There is the option:

addPrefixToSelector: Custom function for adding prefix to selector. Optional. Example:

function addPrefixToSelector ( selector, prefix ) { return ${prefix} > ${selector} // Make selectors like [dir=rtl] > .selector }

with the notice:

note: the returned string must include prefix to avoid an infinite recursion

So I ignored it and my quick workaround:

...
       use: [
          {
            loader: 'postcss-loader',
            options: {
              plugins: function () {
                return [
                  require('postcss-rtl')(
                    {
                      addPrefixToSelector: function addPrefixToSelector ( selector, prefix ) {
                        if (prefix === '[dir]' || prefix === '[dir=ltr]') {
                          return `${selector}`
                        }

                        return `${prefix} ${selector}`
                      }
                    }
                  )
                ]
              }
            }
          }

And as a side effect I got some styles duplicated. Something like

.selector {
  padding-left: 2rem;
  padding-left: 2rem;
}

But looks like it works in general

LFFATE avatar Apr 02 '20 06:04 LFFATE

Thats nice @LFFATE thank you.

@vkalinichev do you have any suggestion on how we can improve this result removing this duplication effect? Do you consider this the only solution or do you have any other good solution that could work in our case? Thank you!

evilaliv3 avatar Apr 02 '20 12:04 evilaliv3

@LFFATE: By any chance, have you found any alternative?

evilaliv3 avatar Apr 03 '20 20:04 evilaliv3

@evilaliv3 no, I'll try to wait for answer from @vkalinichev

LFFATE avatar Apr 07 '20 06:04 LFFATE

I see, thank you anyway

evilaliv3 avatar Apr 09 '20 11:04 evilaliv3

We're facing this same issue and the @LFFATE alternative is a way to go but duplicate rules is a little problem for us. Hope to see any update regarding a more performant solution.

PaquitoSoft avatar Apr 28 '20 14:04 PaquitoSoft

@vkalinichev : what do you think?

evilaliv3 avatar Apr 29 '20 22:04 evilaliv3

@LFFATE,

As a workaround, you can use the rtl:ignore directive to ignore a single rule or to ignore multiple of them.

Your workaround of creating an override of the main rule can create issues like this one (In rtl, there will be left and right properties at the same time). Or this one (in ltr the border-leftproperty is overridden).

fabercancio avatar May 06 '20 21:05 fabercancio

Thank you @fabercancio , but actually this wasnt the main goal of the ticket.

The main need is to make it possible to add only rules related to RTL without changing any existing CSS. This in fact complicate the whole CSS in many situations like the one exposed in https://github.com/vkalinichev/postcss-rtl/issues/64#issuecomment-607293296

Do you have any advice on this?

evilaliv3 avatar May 06 '20 22:05 evilaliv3

@evilaliv3 I know that this is not the purpose of the ticket, I brought just a workaround to avoid adding [rtl] for certain rules. I think that it is possible to do what you are proposing, the only thing is that it has some pitfalls like the ones that I described or some examples that can be found on the section Override CSS on the rtlcss library.

fabercancio avatar May 06 '20 22:05 fabercancio

I see, thank you for the clarification. I guess we are stuck waiting for the suggestions by Vladimir Kalinichev and the evaluation for the possibility to make a patch to the library.

In my opinion the library could assume that the default is RTL and dont ass [rtl] to any of the rtl roules. @vkalinichev do you thins this could be done? even just a config flag for setting the default and apply this change if the user has specified it would be great!

evilaliv3 avatar May 12 '20 09:05 evilaliv3

FWIW just to add to this issue; we've been evaluating this plugin and we're blocked on using this as well. For us it creates large bundle regressions. Most css has very few asymmetrical scenarios, but has plenty of symmetrical cases:

.r { margin: 0; }
.r { border: 1px solid color; }
.r { left: 0; right: 0; }

None of these should be affected as they're all symmetrical, but the plugin adds a bunch of bloat to the output unnecessarily. I took a look at the tests and see that it's validating that the [dir] prefix is added to directionally sensitive things.

Is there any reasoning for adding the dir prefix and modifying symmetrical rules at all? I'm assuming it's a specificity related thing like make all directional rules at least 2 levels of specificity so that they can be predictably overridden, maybe?

The workaround mentioned above would work, but the duplication fights against bundle size as well.

Could the [dir] prefixes be removed? Accepting PRs?

dzearing avatar May 13 '20 20:05 dzearing

I thinks so @dzearing and i may support with retesting;

I'm experienced with testing and packaging, in the meantime we could eventually fork the project while the patch gets officially loaded in.

evilaliv3 avatar May 13 '20 20:05 evilaliv3

FWIW just to add to this issue; we've been evaluating this plugin and we're blocked on using this as well. For us it creates large bundle regressions. Most css has very few asymmetrical scenarios, but has plenty of symmetrical cases:

.r { margin: 0; }
.r { border: 1px solid color; }
.r { left: 0; right: 0; }

None of these should be affected as they're all symmetrical, but the plugin adds a bunch of bloat to the output unnecessarily. I took a look at the tests and see that it's validating that the [dir] prefix is added to directionally sensitive things.

Is there any reasoning for adding the dir prefix and modifying symmetrical rules at all? I'm assuming it's a specificity related thing like make all directional rules at least 2 levels of specificity so that they can be predictably overridden, maybe?

The workaround mentioned above would work, but the duplication fights against bundle size as well.

Could the [dir] prefixes be removed? Accepting PRs?

without [dir] (and such) prefixes you can use some postcss plugins like this one: https://www.npmjs.com/package/postcss-discard-duplicates

LFFATE avatar May 14 '20 05:05 LFFATE

@LFFATE: Would please you explain it more in details? Thank you!

evilaliv3 avatar May 14 '20 14:05 evilaliv3

I believe @LFFATE means if we use the previously suggested custom prefix to strip the dirs, then that will create the dupe rule situation, but that could be worked around with that extra plugin. That makes sense.

I certainly would just rather fix the plugin here though. And understand more deeply why symmetrical rules were prefixed with [dir] in the first place. It seems like there was some reason there because it's covered in the tests.

dzearing avatar May 15 '20 03:05 dzearing

Yes, i would prefer we could arrive to bugfix postcss-rtl that would offer more guarantees.

evilaliv3 avatar May 15 '20 08:05 evilaliv3

Hey, I found this RTL plugin, I have been testing it and it seems to cover this specific issue (but it is very new so I don't know if it is reliable). Check the override mode (even if I'm normally against of overriding RTL it seems to work pretty well in this mode)

fabercancio avatar May 16 '20 16:05 fabercancio

Thanks you!

With your help for testing actually I would like to contribute to this library and just try to implement this ticket and then if it won't be officially integrate I may run a fork below the globaleaks project.

Would you support me with testing eventually? You will be able to use it in production and as soon that the pull request will be integrated officially we may switch back to it

evilaliv3 avatar May 16 '20 18:05 evilaliv3

@evilaliv3 I can test any change, we are already using this library and we don't have any issues so far, so any change that you make I can check if it works with our code and doesn't break anything (but we are not overriding rules and we don't have any plans to do it).

fabercancio avatar May 16 '20 22:05 fabercancio

I got it sorted out!

Here you can find the patch: https://github.com/evilaliv3/postcss-rtl/commit/d0fe859bd5c6e905fa39e0f0b885d9bd6c054505

You could see the improvement as well in the commit evaluating which will be the change result in the modified CSS. In my experimentations on a library like bootstrap the save is around 3%. Many are the advantages already documented in this ticket.

i've opened a pull request so that as soon we are confident we could eventually proceed with the integration.

In the meatime if any of you would like to support the retesting and provide feedback you find it on npm as @evilaliv3/postcss-rtl

evilaliv3 avatar May 17 '20 17:05 evilaliv3

The override works, some things that are still there or that are created by the overriding:

  • dir prefixes are maintained:
    • https://runkit.com/embed/8cqhc3qmoa03
    • https://runkit.com/embed/taajyvacu3xb
  • Left and right properties at the same time in rtl:
    • https://runkit.com/embed/21pgnqhfduhx
  • border-left is overridden:
    • https://runkit.com/embed/fs77yyfrgwmp

The second and third points didn't occur before:

  • https://runkit.com/embed/zs6tzz8c1txz
  • https://runkit.com/embed/ihja3jtn3v31

fabercancio avatar May 17 '20 18:05 fabercancio

Thank you @fabercancio for this fast reply.

will try to fix them all and gt back to you. woull you please annotate me here for each of your reported bugs:

  1. the example of the initial rule

  2. the rule as currently badly rewritten

  3. the expected good rewrite

thank you!

evilaliv3 avatar May 17 '20 18:05 evilaliv3

All fixed @fabercancio:

https://runkit.com/evilaliv3/5ec1913925d80b001b42f740 https://runkit.com/evilaliv3/5ec19191efbfa6001391bdd3 https://runkit.com/evilaliv3/5ec191bbcb578c001ea91e75

evilaliv3 avatar May 17 '20 19:05 evilaliv3

@evilaliv3, the issues are fixed. I'll try tomorrow with one of my projects and I let you know if everything is OK. Regards ;)

fabercancio avatar May 17 '20 22:05 fabercancio

Hi @evilaliv3,

I have tested this with some big CSS files and it works OK in most of the cases. But I noticed that are multiple cases in which some declarations are overridden. This happens when multiple rules are applied in one element at the same time:

  • Current library: https://runkit.com/embed/h93bpl5863dy
  • The modified version: https://runkit.com/embed/n6868zzgavwx

Imagine that both rules are added to the same element with the purpose of resetting the borders. This works with the current version of the library, but with the modified version the reset doesn't work because the prefixed rules are more specific (I think that this is the reason for the [dir] prefixes that @vkalinichev implemented):

  • Result with [dir] prefix: https://jsfiddle.net/cr5728sh/
  • Result without [dir] prefix: https://jsfiddle.net/fehw28sx/

fabercancio avatar May 18 '20 19:05 fabercancio

I see. Nice catch.

In this case I think we have no choices. Let's think about it.

Anyone here has an idea?

evilaliv3 avatar May 18 '20 21:05 evilaliv3

Adding this here in case it helps someone: My requirement was to create separate css files for rtl and ltr (using onlyDirection option), but like others, I ran into issues with the new [dir] tags overriding my other styles. To remove them I employed a trick similar to @LFFATE, with the prefix commented out. Seems to work fine from what I can tell. addPrefixToSelector (selector, prefix) { return '/*${prefix}*/${selector}';}

hoorncj avatar Jun 12 '20 01:06 hoorncj

Hi there! Encountered specificity issues between a 3rd party app and my application styles due to the [dir] attribute selector being added. I was able to overcome it using the !important attribute but looking forward to @evilaliv3's PR getting merged 🙏

adrianmorales80 avatar Oct 27 '20 21:10 adrianmorales80