Skip to content

postcss-light-dark-function generates bloat css in :root #1454

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
2 of 3 tasks
vovsemenv opened this issue Aug 8, 2024 · 6 comments · Fixed by #1458
Closed
2 of 3 tasks

postcss-light-dark-function generates bloat css in :root #1454

vovsemenv opened this issue Aug 8, 2024 · 6 comments · Fixed by #1458
Labels
feature request New feature or request

Comments

@vovsemenv
Copy link

What would you want to propose?

I try to use do this

:root {
    --ad-other-focus: light-dark(var(--system-blue-200), var(--system-blue-300));
    --constant-bg-base-primary: light-dark(var(--gray-neutral-900), var(--constant-bg-base-primary-night));
}

but since i have 150+ colors
every light-dark produce new selector like this i end up in the selector hell. ( even chrome devTools stops working

:root {
    --csstools-light-dark-toggle--0: var(--csstools-color-scheme--dark) var(--system-blue-200);
    --ad-other-focus: var(--csstools-light-dark-toggle--0, var(--system-blue-300));
    --csstools-light-dark-toggle--1: var(--csstools-color-scheme--dark) var(--gray-neutral-900);
    --constant-bg-base-primary: var(--csstools-light-dark-toggle--1, var(--constant-bg-base-primary-night));
}

:root {
    & * {
        --csstools-light-dark-toggle--1: var(--csstools-color-scheme--dark) var(--gray-neutral-900);
        --constant-bg-base-primary: var(--csstools-light-dark-toggle--1, var(--constant-bg-base-primary-night));
    }
}

:root {
    & * {
        --csstools-light-dark-toggle--0: var(--csstools-color-scheme--dark) var(--system-blue-200);
        --ad-other-focus: var(--csstools-light-dark-toggle--0, var(--system-blue-300));
    }
}

Suggested solution

// @postcss-light-dark-no-subselector
:root {
    --ad-other-focus: light-dark(var(--system-blue-200), var(--system-blue-300));
    --constant-bg-base-primary: light-dark(var(--gray-neutral-900), var(--constant-bg-base-primary-night));
}

that lead to this result without additional selectors

:root {
    --csstools-light-dark-toggle--0: var(--csstools-color-scheme--dark) var(--system-blue-200);
    --ad-other-focus: var(--csstools-light-dark-toggle--0, var(--system-blue-300));
    --csstools-light-dark-toggle--1: var(--csstools-color-scheme--dark) var(--gray-neutral-900);
    --constant-bg-base-primary: var(--csstools-light-dark-toggle--1, var(--constant-bg-base-primary-night));
}

Additional context

No response

Validations

  • Follow our Code of Conduct
  • Check that there isn't already an issue that request the same feature to avoid creating a duplicate.

Would you like to open a PR for this feature?

  • I'm willing to open a PR
@vovsemenv vovsemenv added the feature request New feature or request label Aug 8, 2024
@romainmenke
Copy link
Member

romainmenke commented Aug 9, 2024

Hi @vovsemenv,

Thank you for reaching out about this.

Unfortunately there isn't much we can do about this.
The generated CSS is correct and the smallest/simplest it can be.

We test this extremely thoroughly and pass all the same tests that browsers do.

The :root * {} blocks are needed because of how inheritance works with light-dark() and custom properties.

You can see this in action in this codepen: https://codepen.io/romainmenke/pen/wvLGwyb

Notice how the output for light-dark() is computed for each child element and not only once at the root.


Maybe it is too soon to use light-dark() with so many colors and also in a setup where everything is a custom property?

Fallbacks/polyfills can never be as performant and efficient as native implementations.
Using a feature this intensive with a fallback/polyfill might not be ideal?


i end up in the selector hell

How do you mean?

These are all very low specificity selectors and shouldn't conflict with anything you wrote yourself.

Do you simply mean that there is a lot of generated CSS?

even chrome devTools stops working

That seems like an issue with dev tools, not with postcss-preset-env?


Is there an actual problem when rendering pages?
Or only a large CSS file and buggy chrome dev tools?

@romainmenke
Copy link
Member

🤔 We can simplify one thing.

We can output a single & * {} rule per parent rule instead one per light-dark().

:root {
    & * {
        --csstools-light-dark-toggle--1: var(--csstools-color-scheme--dark) var(--gray-neutral-900);
        --constant-bg-base-primary: var(--csstools-light-dark-toggle--1, var(--constant-bg-base-primary-night));
    }
}

:root {
    & * {
        --csstools-light-dark-toggle--0: var(--csstools-color-scheme--dark) var(--system-blue-200);
        --ad-other-focus: var(--csstools-light-dark-toggle--0, var(--system-blue-300));
    }
}

->

:root {
    & * {
        --csstools-light-dark-toggle--1: var(--csstools-color-scheme--dark) var(--gray-neutral-900);
        --constant-bg-base-primary: var(--csstools-light-dark-toggle--1, var(--constant-bg-base-primary-night));
        --csstools-light-dark-toggle--0: var(--csstools-color-scheme--dark) var(--system-blue-200);
        --ad-other-focus: var(--csstools-light-dark-toggle--0, var(--system-blue-300));
    }
}

@vovsemenv
Copy link
Author

🤔 We can simplify one thing.

We can output a single & * {} rule per parent rule instead one per light-dark().

This is actually can help a lot too!!
Let me know if i can contribute that myself

@romainmenke
Copy link
Member

romainmenke commented Aug 9, 2024

You can! 😄

The contributing guides are here : https://github.com/csstools/postcss-plugins/blob/main/CONTRIBUTING.md#quick-start

The relevant code here is :

const variableInheritanceRule = rule({
selector: '& *',
source: decl.source,
});
for (const [toggleName, toggle] of modified.toggles) {
variableInheritanceRule.append(decl.clone({ prop: toggleName, value: toggle }));
}
variableInheritanceRule.append(decl.clone({ value: modified.value }));
decl.parent.append(variableInheritanceRule);

Keeping track of state and data can be done in the prepare block:

let counter = 0;
const currentToggleNameGenerator = (): string => {
return toggleNameGenerator(counter++);
};

I would likely use something like a Map() and only create one variableInheritanceRule for each unique decl.parent.


Test config is here : https://github.com/csstools/postcss-plugins/blob/main/plugins/postcss-light-dark-function/test/_tape.mjs

Maybe best to create a new test CSS file : tests/common-patterns-1.css.
A separate test file is likely more representative of your use case.

And add an entry for it in _tape.mjs :

	'common-patterns-1': {
		message: 'support common patterns',
	},

@vovsemenv
Copy link
Author

@romainmenke thank you very much for amazing work!!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants