csstools / postcss-logical Goto Github PK
View Code? Open in Web Editor NEWUse logical properties and flow-relative values in CSS
Home Page: https://jonathantneal.github.io/postcss-logical/
License: Creative Commons Zero v1.0 Universal
Use logical properties and flow-relative values in CSS
Home Page: https://jonathantneal.github.io/postcss-logical/
License: Creative Commons Zero v1.0 Universal
Is there any plan to continue support for incoming properties, like border-[start|end]-[start|end]-radius
?
Please refer to https://github.com/ackl/postcss-logical-bug
when using jsx syntax, postcss decl.parent is defined, but decl.parent.parent is undefined, so calling parent.before throws error, need to check if parent.parent exists, else just do before on decl
pls see this fix
https://github.com/csstools/postcss-logical
-start
or -end
without block
or inline
)Looks like 4.0.0 was tagged today, but is not published to npm.
As the title says, I guess this:
.element {
transition: 1s inset-inline-start ease;
}
should be translated to:
.element:dir(ltr) {
transition: 1s left ease;
}
.element:dir(rtl) {
transition: 1s right ease;
}
I am not sure what's wrong but other plugins like css-nano
and css-next
are working fine.
My postcss.config.js is like the following
module.exports = {
plugins: {
'postcss-import': {},
'postcss-logical': {},
'postcss-cssnext': {},
cssnano: {},
},
};
and my webpack.config relevant part is like:
module: {
rules: [
...
{
test: /\.css$/,
use: [
{
loader: 'style-loader',
options: { sourceMap: true },
},
{
loader: 'css-loader',
options: {
importLoaders: 1,
sourceMap: true,
},
},
{
loader: 'postcss-loader',
options: { sourceMap: true },
},
],
},
],
},
When compiling it refuses to transpile inline-start
or start
to the corresponding value. I tried passing the dir: "ltr"
to the plugin, add dir
attribute to the html tag but still have no effect.
I am trying to debug it and see what's wrong
Hi,
I have a doubt about how the library generate code when using the "logical" keyword. For instance the following code:
ul {
margin: logical 28px 0 28px 1.25em;
}
Generate this:
[dir="ltr"] ul {
margin: 28px 1.25em 28px 0;
}
[dir="rtl"] ul {
margin: 28px 0 28px 1.25em;
}
Is this the expected output as per specification? Should not the logical follow by default the "LTR" (most common) variation? Intuitively I would have expected the opposite output, as this means that I should actually transform first the various direction before using the logical keyword?
Hi. Thank you for a great work. I have a question about plugin. Does it converts physical properties for both directions? For example float: right into float: left. Or it's only for logical properties?
Thank you, Pasha
Hi there,
It looks like border-block-start-width
and border-block-end-width
are not transformed.
In a top to bottom block flow:
border-block-start-width
should become border-top-width
border-block-end-width
should become border-bottom-width
See: https://developer.mozilla.org/en-US/docs/Web/CSS/border-block-start-width
Probably something to add here ?
https://github.com/csstools/postcss-logical/blob/master/src/lib/transform-border.js
btw, this plugin is a really nice initiative, thanks ;) (I wish I could find time to help more!)
Hi,
I am trying to integrate logical properties into a project of mine and would like to take advantage of a post processor. However there is something I do not get but I may be missing something obvious.
Why would:
.banner {
padding-inline: 20px 40px;
}
generate this:
.banner:dir(ltr) {
padding-left: 20px; padding-right: 40px;
}
.banner:dir(rtl) {
padding-right: 20px; padding-left: 40px;
}
Instead of simply:
.banner {
padding-left: 20px;
padding-right: 40px;
padding-inline: 20px 40px;
}
This would have the advantage of keeping the code much smaller and much easier to read. Modern browsers would simply use the logical properties while older browser would default to physical properties.
I was expecting transform-origin
to work as expected.
.selector {
transform-origin: inline-end;
}
[dir="ltr"] .selector {
transform-origin: right;
}
[dir="rtl"] .selector {
transform-origin: left;
}
I will be happy to submit a PR
vb
and vi
don't seem to be supported. Will this be added?
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
According to this bug the issue should have been resolved.
.postcssrc
:
{
"plugins": {
"autoprefixer": true,
"postcss-logical": {
"preserve": "true",
}
}
}
HTML, with dir
attribute specified.
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>...</head>
<body>
<div class="widget">
<div class="widget-sidebar">...</div>
<div class="widget-content">...</div>
</div>
...
SCSS:
.widget {
&-sidebar {
margin-inline-end: 2rem;
}
}
Rendered CSS:
.widget-sidebar:dir(ltr){margin-right:2rem}.widget-sidebar:dir(rtl){margin-left:2rem}.widget-sidebar{margin-inline-end:2rem}
Btw, I'm using Parcel to bundle my UI assets, not Webpack or Gulp.
Using transform: rotate(72.3deg);
results in the following error:
postcss-transform-logical: could not parse rotate(72.3deg)
preserve: true
with block-size
and inline-size
doesn't seem to work.
Just to inform you about the above issue. I do not know yet which module has a problem.
There is specification for logical version of overflow
and overscroll-behavior
:
Chrome should relatively soon get support for both (See 1 and 2). Just to be clear these are not yet shipped in Chrome so I don't suggest adding the support yet.
But just wanted to given you a heads up since I think it will be nice if your plugin could support them as well once these are available in Chrome.
When running postcss-logical on @keyframes
at-rule blocks, the resulting CSS isn't valid.
For example, I have this CSS that produces a basic loading bar-like effect (a div starts at 0% fixed on the "left", grows to 100% width, then reduces back to 0% whilst fixed on the "right"). This is achieved using the left-right directional properties inset-inline-start
and inset-inline-end
.
@keyframes busy {
0%,
100% {
inset-inline-start: 0;
inset-inline-end: auto;
inline-size: 0;
}
33% {
inset-inline-start: 0;
inset-inline-end: auto;
inline-size: 100%;
}
33.01% {
inset-inline-start: auto;
inset-inline-end: 0;
inline-size: 100%;
}
66% {
inset-inline-start: auto;
inset-inline-end: 0;
inline-size: 0;
}
}
Running it though postcss-logical on the default configuration produces this invalid CSS, where each timing step has been prefixed with a [dir]
attribute selector:
@keyframes busy {
[dir="ltr"] 0%,[dir="ltr"] 100% {
left: 0;
}
[dir="rtl"] 0%,[dir="rtl"] 100% {
right: 0;
}
[dir="ltr"] 0%,[dir="ltr"] 100% {
right: auto;
}
[dir="rtl"] 0%,[dir="rtl"] 100% {
left: auto;
}
0%, 100% {
width: 0;
}
[dir="ltr"] 33% {
left: 0;
}
[dir="rtl"] 33% {
right: 0;
}
[dir="ltr"] 33% {
right: auto;
}
[dir="rtl"] 33% {
left: auto;
}
33% {
width: 100%;
}
[dir="ltr"] 33.01% {
left: auto;
}
[dir="rtl"] 33.01% {
right: auto;
}
[dir="ltr"] 33.01% {
right: 0;
}
[dir="rtl"] 33.01% {
left: 0;
}
33.01% {
width: 100%;
}
[dir="ltr"] 66% {
left: auto;
}
[dir="rtl"] 66% {
right: auto;
}
[dir="ltr"] 66% {
right: 0;
}
[dir="rtl"] 66% {
left: 0;
}
66% {
width: 0;
}
}
This issue does not occur if the dir
configuration option is set, as it doesn't prepend [dir]
attribute selectors in that situation.
I'm not sure how the desired result can actually be achieved in an automated fashion due to the inability to nest selectors within @keyframes
. It would seemingly be required to have multiple @keyframes
definitions and to swap which one is used based on the directionality of the calling selector.
Regardless of how to achieve that, postcss-logical adding these selectors within a @keyframes
at-rule block currently creates invalid CSS, and the tool should probably ignore any CSS properties that would create such selectors.
According to this draft I can only find references for logical values for background-size
. I am not sure if logical properties will be added to background-position
or not but it's really needed for rtl implementations. Do you know if such specs exist or not? If not, where do you recommend we suggest it? W3C or WHATWG?
Is there any example of how to integrate with Vue CLI 3?
I have a postcss.config.js
and a vue.config.js
but I tried some changes but I could not make it work.
My last change was on postcss.config.js
module.exports = {
plugins: [
autoprefixer(), //already existing on my project.
postcssLogical()
]
}
According to this demo when I try:
.test {
float: inline-start;
}
The output should be:
[dir="ltr"] .test {
float: left
}
[dir="rtl"] .test {
float: right
}
I get different output in my workflow:
.test:dir(ltr) {
float: left;
}
.test:dir(rtl) {
float: right;
}
I thought the problem might be due to my browserlist and the configuration for css-next
. I did a little research and found the postcss-dir-pseudo-class plugin. Adding it to my flow transformed the output to:
.test {
[dir="ltr"] & {
float: left;
}
[dir="rtl"] & {
float: right;
}
}
I figured that I will need another plugin to transform this into something the browsers can understand; postcss-nested.
The question is, shouldn't we clarify the requirements for the plugin? I think it will save time and hassle. I spent at least 30 minutes trying to figure all this out.
Is there any way with your plugin to not add the RTL fallback selectors to the original CSS but instead pipe them into a separate file? So only to transform the LTR selectors, but have the RTL fallback selectors (the ones with :dir()
) in another file.
Use case: we would like to load that file only when the interface is in a RTL language.
Thanks for the plugin!
According to the caniuse not all browsers support shorthand CSS properties such as padding-inline
padding-block
and etc.
There is suggestion to add a new option to the plugin for deploying shorthand CSS properties.
.banner {
padding-inline: 20px 40px;
}
/* becomes */
.banner {
padding-inline-start: 20px;
padding-inline-end: 40px;
padding-inline: 20px 40px;
}
Hi Jonathan,
Having upgraded to v4 of this plugin, I noticed that parts of my layout broke. Looking into why, it seems that the logical sizing properties have been reversed. From my limited testing, I have observed the following:
Value | v3.0.0 | v4.0.0 |
---|---|---|
block-size |
height |
width |
inline-size |
width |
height |
In addition, min/max values are no longer translated into their physical equivalents (assuming left-to-right, top-to-bottom):
Value | v3.0.0 | v4.0.0 |
---|---|---|
min-block-size |
min-height |
min-block-size |
max-block-size |
max-height |
max-block-size |
min-inline-size |
min-width |
min-inline-size |
max-inline-size |
max-width |
max-inline-size |
Other properties don’t appear to be affected.
Hi, Thank you for this great tool!
Gulp plugin is generating :dir() CSS pseudo-class but that doesn't work in chrome, so how can I have it generating [dir=""] selector like your demo on Codepen?
Please refer to https://github.com/ackl/postcss-logical-bug
when using jsx syntax, postcss decl.parent is defined, but decl.parent.parent is undefined, so calling parent.before throws error, need to check if parent.parent exists, else just do before on decl
pls see this fix
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.