Open jantimon opened 2 years ago
No. I haven't thought it through. But there's a workaround. dynamic styles
import React from 'react'
import { css } from '@pieces-js/tag'
export function Box({ size }) {
return (
<div
className={css`
height: var(--box-size);
width: var(--box-size);
`}
style={{ '--box-size': size }}
/>
)
}
The main goal, for now, is to solve the CSS rules order
problem in atomic CSS-in-JS. You could find more details in this wonderful article Atomic CSS-in-JS.
After solving the order problem, the project will be production-ready and I will be focusing on adding tests.
Dynamic styles are reducing the complexity of js-in-css a lot so it would be great to be build in without hard to maintain workarounds..
Also css-variables won't work in different cases e.g the following does not work:
@media (min-width var(--x)) { ... }
Afaik the order problem is really hard.
Which atomic styles should the following code generate and in which order?
.foo:nth-child(2n) {
color: red;
}
.foo:active {
color: blue;
}
.foo:not(:focus-within) {
color: orange;
}
@media (min-width 300px) {
.foo {
color purple;
}
}
and a second file:
@media (min-width 300px) {
.bar {
color purple;
}
}
.bar:not(:focus-within) {
color: orange;
}
.bar:active {
color: blue;
}
.bar:nth-child(2n) {
color: red;
}
Yeah. I'm going to remove At-rule
and pseudo-classes
supports. It creates a lot of edge cases.
It will only support something like
const foo = css`
margin: 0 20px;
margin-top: 10px;
`
const bar = css`
margin-top: 10px;
`
It first will be transformed to
const foo = css`
margin-top: 0px;
margin-bottom: 0px;
maring-left: 20px;
maring-right: 20px;
margin-top: 10px;
`
const bar = css`
margin-top: 10px;
`
and finally
const foo = css`
margin-bottom: 0px;
maring-left: 20px;
maring-right: 20px;
margin-top: 10px;
`
const bar = css`
margin-top: 10px;
`
and compile to
const foo = 'c1 c2 c3 c4'
const bar = 'c4'
This way, no matter what the style order be,
.c1 { margin-bottom: 0px; }
.c2 { margin-left: 20px; }
.c3 { margin-top: 20px; }
.c4 { margin-top: 10px; }
and
.c4 { margin-top: 10px; }
.c3 { margin-top: 20px; }
.c2 { margin-left: 20px; }
.c1 { margin-bottom: 0px; }
will have a consistent result.
I haven't figured out how pseudo-classes
fit into the process. but I guess At-rule
supports will be removed forever.
@jantimon You are right that dynamic styles could reduce the complexity. But the approach of pieces-js requires static analysis, code like transform: translateX(${x}px);
is very hard to do static analysis.
what do you mean by removed?
no os based dark mode?
@media (prefers-color-scheme: dark) {
no responsiveness?
@media (max-width 1200px) {
no print?
@media print {
no accessibility?
@media (prefers-reduced-motion) {
no element queries?
@container (min-width: 700px){
no touch detection?
@media (hover: none) and (pointer: coarse) {
Yes. That's the pain in this approach. Nicolas Gallagher has a talk about this. https://youtu.be/tFFn39lLO-U?t=1184
oh there is also
@supports (display: grid) {
so to summarize its css just with
to me this approach feels like it introduces a lot more problems than it is able to solve
yeah. But what do you mean about limited code splitting?
let's say you have a special part of your application which is used rarely e.g. only on black friday which ships with special colors, fonts, font sizes and so on...
your code might look like this:
if (isBlackFriday) {
import("./blackfriday");
}
if (isVipCustomer) {
import("./vip");
}
this would create 3 chunks but if a specific order must be guaranteed I guess that's not possible anymore as you wouldn't know which css file is load first
this means that all users need to download the black friday and vip css the entire year
Yeah. I'm going to remove
At-rule
andpseudo-classes
supports. It creates a lot of edge cases. It will only support something likeconst foo = css` margin: 0 20px; margin-top: 10px; ` const bar = css` margin-top: 10px; `
It first will be transformed to
const foo = css` margin-top: 0px; margin-bottom: 0px; maring-left: 20px; maring-right: 20px; margin-top: 10px; ` const bar = css` margin-top: 10px; `
and finally
const foo = css` margin-bottom: 0px; maring-left: 20px; maring-right: 20px; margin-top: 10px; ` const bar = css` margin-top: 10px; `
and compile to
const foo = 'c1 c2 c3 c4' const bar = 'c4'
This way, no matter what the style order be,
.c1 { margin-bottom: 0px; } .c2 { margin-left: 20px; } .c3 { margin-top: 20px; } .c4 { margin-top: 10px; }
and
.c4 { margin-top: 10px; } .c3 { margin-top: 20px; } .c2 { margin-left: 20px; } .c1 { margin-bottom: 0px; }
will have a consistent result.
It doesn't require specific order. The above example shows it.
but pseudo elements need an order
.b {
color: orange;
}
.c:hover {
color:blue
}
.d:focus {
color:purple
}
is not the same as
.d:focus {
color:purple
}
.c:hover {
color:blue
}
.b {
color: orange;
}
yeah. Another downside :(.
btw did you see https://compiledcssinjs.com/
First time saw this. Looks like it also has the order problem. https://codesandbox.io/s/musing-kilby-rwvcf?file=/pages/Foo.tsx
--- edit
Sorry. It seems doesn't have the order problem. It solves the problem using the way I described above.
It also supports At-rule, wondering how they do it.
does it support dynamic css?
e.g.: