lightningcss icon indicating copy to clipboard operation
lightningcss copied to clipboard

Convert css properties to shorthands when css vars are used.

Open nicksrandall opened this issue 3 years ago • 3 comments

Currently, parcel-css will covert css properties to shorthand notation when it is safe to do so:

.should-collapse {
  border-left-style: none;
  border-left-width: 0;
  border-left-color: #333;
  border-top-style: none;
  border-top-width: 0;
  border-top-color: #333;
  border-right-style: none;
  border-right-width: 0;
  border-right-color: #333;
  border-bottom-style: none;
  border-bottom-width: 0;
  border-bottom-color: #333;
}

becomes

.should-collapse {
  border: none;
}

See: https://parcel-css.vercel.app/#%7B%22minify%22%3Afalse%2C%22nesting%22%3Atrue%2C%22customMedia%22%3Atrue%2C%22cssModules%22%3Afalse%2C%22analyzeDependencies%22%3Afalse%2C%22targets%22%3A%7B%22chrome%22%3A6225920%7D%2C%22source%22%3A%22.should-collapse%20%7B%5Cn%20%20border-left-style%3A%20none%3B%5Cn%20%20border-left-width%3A%200%3B%5Cn%20%20border-left-color%3A%20%23333%3B%5Cn%20%20border-top-style%3A%20none%3B%5Cn%20%20border-top-width%3A%200%3B%5Cn%20%20border-top-color%3A%20%23333%3B%5Cn%20%20border-right-style%3A%20none%3B%5Cn%20%20border-right-width%3A%200%3B%5Cn%20%20border-right-color%3A%20%23333%3B%5Cn%20%20border-bottom-style%3A%20none%3B%5Cn%20%20border-bottom-width%3A%200%3B%5Cn%20%20border-bottom-color%3A%20%23333%3B%5Cn%7D%22%2C%22unusedSymbols%22%3A%5B%5D%2C%22version%22%3A%22local%22%7D

But when the above is changed to use css variables:

.should-collapse {
  border-left-style: none;
  border-left-width: 0;
  border-left-color: var(--theme-colors-gray-200);
  border-top-style: none;
  border-top-width: 0;
  border-top-color: var(--theme-colors-gray-200);
  border-right-style: none;
  border-right-width: 0;
  border-right-color: var(--theme-colors-gray-200);
  border-bottom-style: none;
  border-bottom-width: 0;
  border-bottom-color: var(--theme-colors-gray-200);
}

The conversion to shorthand does not happen (but I think it should).

See: https://parcel-css.vercel.app/#%7B%22minify%22%3Afalse%2C%22nesting%22%3Atrue%2C%22customMedia%22%3Atrue%2C%22cssModules%22%3Afalse%2C%22analyzeDependencies%22%3Afalse%2C%22targets%22%3A%7B%22chrome%22%3A6225920%7D%2C%22source%22%3A%22.should-collapse%20%7B%5Cn%20%20border-left-style%3A%20none%3B%5Cn%20%20border-left-width%3A%200%3B%5Cn%20%20border-left-color%3A%20var(--theme-colors-gray-200)%3B%5Cn%20%20border-top-style%3A%20none%3B%5Cn%20%20border-top-width%3A%200%3B%5Cn%20%20border-top-color%3A%20var(--theme-colors-gray-200)%3B%5Cn%20%20border-right-style%3A%20none%3B%5Cn%20%20border-right-width%3A%200%3B%5Cn%20%20border-right-color%3A%20var(--theme-colors-gray-200)%3B%5Cn%20%20border-bottom-style%3A%20none%3B%5Cn%20%20border-bottom-width%3A%200%3B%5Cn%20%20border-bottom-color%3A%20var(--theme-colors-gray-200)%3B%5Cn%7D%22%2C%22unusedSymbols%22%3A%5B%5D%2C%22version%22%3A%22local%22%7D

nicksrandall avatar Apr 12 '22 17:04 nicksrandall

This is not possible to do correctly in all cases. CSS variables are essentially raw tokens. A single variable may represent multiple values. For example, in properties that allow a list of values, this would be broken:

.foo {
  --bg-images: url(a.png), url(b.png);
  --bg-repeat: repeat, no-repeat;
  background-image: var(--bg-images);
  background-repeat: var(--bg-repeat);
}

naively combining those variables might produce this, which is not valid:

.foo {
  background: var(--bg-images) var(--bg-repeat);
}

This can also happen for border properties. For example if you do this:

.foo {
  border-width: 2px;
  border-left-width: 5px;
}

we produce:

.foo {
  border-width: 2px 2px 2px 5px;
}

but with variables, it's not possible. You could have something like this:

.foo
  --borders: 1px 2px 3px 4px;
  border-width: var(--borders);
  border-left-width: 5px;

and we can't combine those safely.

devongovett avatar Apr 12 '22 18:04 devongovett

I think even the current behaviour is wrong. Consider this:

.a {
    border: none green;    /* will be transformed to `border: none;` */
}
.b {
    border-style: dashed;
}
<span class="a b">I should have a green dashed border, but it's black.</span>

Maybe this also affects other shorthand properties like background, haven't checked.

https://parcel-css.vercel.app/#%7B%22minify%22%3Afalse%2C%22nesting%22%3Atrue%2C%22customMedia%22%3Atrue%2C%22cssModules%22%3Afalse%2C%22analyzeDependencies%22%3Afalse%2C%22targets%22%3A%7B%22chrome%22%3A6225920%7D%2C%22source%22%3A%22.a%20%7B%5Cn%20%20%20%20border%3A%20none%20green%3B%5Cn%7D%5Cn.b%20%7B%5Cn%20%20%20%20border-style%3A%20dashed%3B%5Cn%7D%22%2C%22unusedSymbols%22%3A%5B%5D%2C%22version%22%3A%22local%22%7D

schuetzm avatar Apr 13 '22 09:04 schuetzm

@schuetzm your issue should be fixed by the above commit.

devongovett avatar Apr 30 '22 17:04 devongovett