Code Monkey home page Code Monkey logo

postcss-logical's Introduction

⚠️ PostCSS Logical Properties and Values was moved to @csstools/postcss-plugins. ⚠️
Read the announcement

PostCSS Logical Properties and Values PostCSS Logo

NPM Version CSS Standard Status Build Status Support Chat

PostCSS Logical Properties and Values lets you use logical, rather than physical, direction and dimension mappings in CSS, following the CSS Logical Properties and Values specification.

'Can I use' table

.banner {
  color: #222222;
  inset: logical 0 5px 10px;
  padding-inline: 20px 40px;
  resize: block;
  transition: color 200ms;
}

/* becomes */

.banner:dir(ltr) {
  padding-left: 20px; padding-right: 40px;
}

.banner:dir(rtl) {
  padding-right: 20px; padding-left: 40px;
}

.banner {
  resize: vertical;
  transition: color 200ms;
}

/* or, when used with { dir: 'ltr' } */

.banner {
  color: #222222;
  top: 0; left: 5px; bottom: 10px; right: 5px;
  padding-left: 20px; padding-right: 40px;
  resize: vertical;
  transition: color 200ms;
}

/* or, when used with { preserve: true } */

.banner:dir(ltr) {
  padding-left: 20px; padding-right: 40px;
}

.banner:dir(rtl) {
  padding-right: 20px; padding-left: 40px;
}

.banner {
  color: #222222;
  top: 0; left: 5px; bottom: 10px; right: 5px;
  inset: logical 0 5px 10px;
  padding-inline: 20px 40px;
  resize: block;
  resize: vertical;
  transition: color 200ms;
}

These shorthand properties set values for physical properties by default. Specifying the logical keyboard at the beginning of the property value will transform the flow-relative values afterward into both physical LTR and RTL properties:

Logical Borders

  • border, border-block, border-block-start, border-block-end, border-inline, border-inline-start, border-inline-end, border-start, border-end, border-color, border-block-color, border-block-start-color, border-block-end-color, border-inline-color, border-inline-start-color, border-inline-end-color, border-start-color, border-end-color, border-style, border-block-style, border-block-start-style, border-block-end-style, border-inline-style, border-inline-start-style, border-inline-end-style, border-start-style, border-end-style, border-width, border-block-width, border-block-start-width, border-block-end-width, border-inline-width, border-inline-start-width, border-inline-end-width, border-start-width, border-end-width, border-start-start-radius, border-start-end-radius, border-end-start-radius, border-end-end-radius

Logical Offsets

  • inset, inset-block, inset-block-start, inset-block-end, inset-inline, inset-inline-start, inset-inline-end, inset-start, inset-end

Logical Margins

  • margin, margin-block, margin-block-start, margin-block-end, margin-inline, margin-inline-start, margin-inline-end, margin-start, margin-end

Logical Paddings

  • padding, padding-block, padding-block-start, padding-block-end, padding-inline, padding-inline-start, padding-inline-end, padding-start, padding-end

Logical Sizes

  • block-size, max-block-size, min-block-size, inline-size, max-inline-size, min-inline-size

Flow-Relative Values

  • clear: inline-start, clear: inline-end, float: inline-start, float: inline-end, text-align: start, text-align: end

By default, PostCSS Logical Properties and Values creates fallback selectors which require at least one [dir] attribute in your HTML. If you don’t have any [dir] attributes, consider using the following JavaScript:

// force at least one dir attribute (this can run at any time)
document.documentElement.dir=document.documentElement.dir||'ltr';

Otherwise, consider using the dir option to transform all logical properties and values to a specific direction.

require('postcss-logical')({
  dir: 'ltr'
});

Usage

Add PostCSS Logical Properties and Values to your project:

npm install postcss-logical --save-dev

Use PostCSS Logical Properties and Values to process your CSS:

const postcssLogical = require('postcss-logical');

postcssLogical.process(YOUR_CSS /*, processOptions, pluginOptions */);

Or use it as a PostCSS plugin:

const postcss = require('postcss');
const postcssLogical = require('postcss-logical');

postcss([
  postcssLogical(/* pluginOptions */)
]).process(YOUR_CSS /*, processOptions */);

PostCSS Logical Properties and Values runs in all Node environments, with special instructions for:

Node PostCSS CLI Webpack Create React App Gulp Grunt

Options

dir

The dir option determines how directional fallbacks should be added to CSS. By default, fallbacks replace the logical declaration with nested :dir pseudo-classes. If dir is defined as ltr or rtl then only the left or right directional fallbacks will replace the logical declarations. If preserve is defined as true, then the dir option will be ignored.

preserve

The preserve option determines whether directional fallbacks should be added before logical declarations without replacing them. By default, directional fallbacks replace logical declaration. If preserve is defined as true, then the dir option will be ignored.

postcss-logical's People

Contributors

dargmuesli avatar in-in avatar jonathantneal avatar romainmenke avatar scrum avatar semigradsky avatar sheff146 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

postcss-logical's Issues

Border-radius properties

Is there any plan to continue support for incoming properties, like border-[start|end]-[start|end]-radius?

Produces invalid CSS when directional properties are used in @keyframes

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.

Cannot get it to work with webpack 2

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

Incorrect logical sizing in v4

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.

Is logical keyword generating correct output?

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?

Rendered CSS is wrong. It is '.class:dir(ltr)' instead of '[dir="ltr"] .class'

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.

Pipe fallback CSS rules to separate file

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!

Logical Background Images

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?

Transform origin is missing

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

Consider adding support for overflow and overscroll-behavior

There is specification for logical version of overflow and overscroll-behavior:

  • overflow-inline
  • overflow-block
  • overscroll-behavior-inline
  • overscroll-behavior-block

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.

Physical properties

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

`border-block-start-width` & `border-block-end-width` not transformed

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!)

Clarifying dependencies for the plugin in the readme

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.

Add using non shorthand CSS properties

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;
}

Viewport Units

vb and vi don't seem to be supported. Will this be added?

Integrating with Vue CLI 3 tool

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()
  ]
}

Why generating :dir selectors?

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.

Cannot nest [dir=]'s

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.