Skip to content
This repository has been archived by the owner on Feb 18, 2022. It is now read-only.

Cannot nest [dir=]'s #26

Closed
snowystinger opened this issue Jun 2, 2020 · 1 comment
Closed

Cannot nest [dir=]'s #26

snowystinger opened this issue Jun 2, 2020 · 1 comment

Comments

@snowystinger
Copy link

I don't know if this can be solved in this library. However, I a) wanted to know if anyone has solved this. or b) throw some ideas out and see if anyone can take them any further

The entire tree that the css is applied to must be one dir, otherwise there is equality in specificity.

css logical properties postcss takes lines like this:

.someClass {
  padding-inline-start: calc(var(--checkbox-cursor-hit-x) * -1);
}

and transforms them into:

[dir="ltr"] .someClass {
  padding-left: calc(var(--checkbox-cursor-hit-x) * -1);
}
[dir="rtl"] .someClass {
  padding-right: calc(var(--checkbox-cursor-hit-x) * -1);
}

this is problematic because these are equal in specificity, so if you have nested locale changing nodes you could end up with both applied

<div dir="rtl">
  <div dir="ltr">
    <div class="someClass">hello</div>
  </div>
</div>

I've been trying to use css variables to accomplish it. Idea originally from reading https://css-tricks.com/logical-operations-with-css-variables/. Essentially I've come up with a couple variables that need to be set on any node that has the 'dir' attribute.
Something along the lines of

[dir="ltr"] {
  --ltr: calc(1 / 0);
  --rtl: 1;
}
[dir="rtl"] {
  --ltr: 1;
  --rtl: calc(1 / 0);
}

the purpose of this is to make one of the variables invalid
with that, my hope would then be to use css variable fallbacks to unset properties

[dir="rtl"] .someClass {
  --left: calc(15px * var(--rtl));
  --right: calc(15px * var(--ltr));
  padding-left: var(--left, unset);
  padding-right: var(--right, unset);
}
[dir="ltr"] .someClass {
  --left: calc(15px * var(--rtl));
  --right: calc(15px * var(--ltr));
  padding-left: var(--left, unset);
  padding-right: var(--right, unset);
}

it's not quite there though, I can't get an invalid variable, haha.
there's also still the issue of what happens if both padding-inline-start and padding-inline-end were declared

@romainmenke
Copy link
Member

The mention of variables as a solution is interesting and reminded me that variable values are inherited.

https://codepen.io/romainmenke/pen/OJxxMqo

:dir(rtl) {
   color: purple;
}

[dir="rtl"] {
   color: purple;
}

:dir(ltr) {
  color: green;
}

[dir="ltr"] {
  color: green;
}

:dir(ltr) + :dir(rtl) * {
  border-bottom: solid 2px red;
}

[dir="rtl"] {
  --unique-id-1: solid 2px red;
}

[dir="ltr"] + :not([dir="ltr"]) * {
  border-bottom: var(--unique-id-1);
}

I would need to test this further but the basic idea is this :

  • create a unique variable name
  • assign value for rtl with [dir="rtl"] { --the-id: the-rtl-value; }
  • assign value for lrt with [dir="ltr"] { --the-id: the-ltr-value; }

The id's need be unique per property and selector (excluding :dir or [dir] parts).
An md5 hash of the selector and property would work well.

The tricky part is that the selector also needs to transformed in a way that it matches the elements. This is easier id :dir() is always part of a compound selector. (.foo:dir(ltr) vs :dir(ltr))

Maybe it works well enough with :not([dir="<inverse>"]).

Support of this would be limited to browsers that have variable support.


I would need to prototype this and check if there are any unexpected issues.
Work on this will continue here : csstools/postcss-plugins#88


Closing this issue here as the repo has been moved and will be archived soon, preventing further discussion.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants