replacement for importFrom
and exportTo
#192
-
📢 If you came here after seeing a warning in We want to do this right and create a way forward for as many people as possible. see : #151 Context for the original discussion :Context :
These options count as "side effects". They do something non-standard and make your code dependent on the plugin running.
The most clear example is using Proposal :The general idea is to create something that does not have any interaction or logic with other features or behaviours. Only has three features :
Caveats and issuesCSS would be syntactically correct, but would have invalid values in many contexts. This does not address the issue of execution order. Some might want to extract pieces of CSS as written others might want to extract the final result. For
|
Beta Was this translation helpful? Give feedback.
Replies: 21 comments 53 replies
-
New proposal see : #304 This proposal interprets The assumption is that very few authors write CSS that is truly dynamic with data fed to For the moment I consider Config : {
// Enforce using `design-token(foo)` for each `color` property
requiresDesignTokens: {
properties: [
'color'
]
},
designTokens: {
selectors: [
{
name: 'button',
value: ':is(.button, button[type="submit"])',
deprecated: false, // emit a warning when design token is used
}
],
atSupports: [
{
name: 'cover',
value: '(object-fit: cover)',
deprecated: false,
}
],
atMedia: [
{
name: 'medium',
value: '(min-width: 768px)',
deprecated: false
}
],
values: [
{
name: 'my-color',
value: '#f00',
deprecated: false,
allowedProperties: [], // only allowed on certain properties
blockedProperties: [], // not allowed on certain properties
}
]
}
} This focuses heavily on giving authors tools to manage the shared interface between CSS and X. It allows the creation of much more strict contracts for how design tokens must or must not be used. Example : .foo {
color: design-token(my-color);
}
@media (design-token: medium) {
.baz {
color: green;
}
}
@supports (design-token: cover) {
.baz {
color: green;
object-fit: cover;
}
}
:design-token(button) {
color: green;
} No new syntax is introduced and no existing syntax or keywords are overloaded. Each case has a specific context and prefix to support auto complete and snippet triggers in editors. |
Beta Was this translation helpful? Give feedback.
-
the exportTo function can be handy for devs building design systems from existing sites. Extracting css custom properties from :root to .json, so that they can be looped over/filtered as needed for display of various "token" level things. This is maybe redundant for new projects or when using things like tailwind, but for older projects where styles are not originally defined in .js this ability is super helpful. A helper script before building the design system (say, storybook) const postcss = require('postcss');
const postcssCustomProperties = require('postcss-custom-properties');
const fs = require('fs');
const path = require('path');
fs.readFile(path.resolve(__dirname,'../components/tokens/_variables.css'), (err, css) => {
postcss({
plugins: [
postcssCustomProperties({
exportTo: path.resolve(__dirname, './cssVariables.json')
})
]
}).process(css, {
from: path.resolve(__dirname, '../components/tokens/_variables.css'),
to: '' // don't need a css file here, just want the .json output from above
}).then(result => {
console.log('Finished processing CSS variables from ' + result.opts.from + ' for Storybook!');
})
}) then in Storybook (or whatever design system) you can easily do logic to pass different groups of variables to various templates import customProperties from 'path/defined/in/exportTo/cssVariables.json'
const vars = customProperties["custom-properties"];
const colorVars = Object.keys(vars)
.filter(key => key.includes('--color'))
.reduce((obj, key) => {
obj[key] = vars[key];
return obj;
}, {});
export const Colors = {
args: {
colorVars
},
...
} |
Beta Was this translation helpful? Give feedback.
-
Compiled with problems: WARNING in ./src/App.css (./node_modules/css-loader/dist/cjs.js!./node_modules/postcss-loader/dist/cjs.js!./src/App.css) Module Warning (from ./node_modules/postcss-loader/dist/cjs.js): (1:1) postcss-custom-properties: "importFrom" and "exportTo" will be removed in a future version of postcss-custom-properties. |
Beta Was this translation helpful? Give feedback.
-
Usage I am using My usage of I have values that need not change at runtime. I thought Questions
|
Beta Was this translation helpful? Give feedback.
-
May be a bit of an unconventional use but we are using the importFrom to be able to be able to theme our CSS output. We started using this feature with the package "postcss-css-variables" which allows you to pass in additional variables, but have had to move packages due to some output issues with that package.
|
Beta Was this translation helpful? Give feedback.
-
Update on design tokens :see the wip plugin : https://github.com/csstools/postcss-plugins/tree/design-tokens--affectionate-sponge-94364bcfba/plugins/postcss-design-tokens#readme On design tokens formats :I have now tried multiple formats with most time spend on Style Dictionary and the Design Tokens specification. In general the implementations are flawed because they make the simple things a little bit easier but the hard things much harder. This is a common mistake for tools that integrate multiple existing systems. To keep things simple, choices have been made that limit design tokens to a subset of features of all other systems involved. (With this I mean values and typings support) Instead it should be embraced that styling is complicated and that CSS is a very advanced and feature rich language. Other contexts (iOS, android, ...) will have their own complexity that also can not be expressed by current design token formats. Personally I think the current formats and proposals are a bad direction and will be harmful. Design tokens as an idea are incredibly powerful and can speedup design and development when implemented correctly. It should be magical because it just works. How I think it should (or should not) work :
I do hope that all this evolves in a healthy way for everyone. Current implementationExposing design tokens to CSSFile formatBecause no single format has a good design I propose that we implement multiple. Choosing a single format would be an endorsement of that format and they are all not good in their own way. To support this a new @design-tokens url('./tokens-light.json') format('style-dictionary3'); This allows the plugin to pick a different token parser per imported file. Include pathsWhyThe plugin doesn't have any options to import design tokens. This unlocks more features and convenience :
When tokens are added to the plugin config, they are only exposed to the plugin itself and no other system or tool has access to your tokens. Declaring everything in CSS will benefit developers most. Resolving paths
You will have to do things like this : @design-tokens url('../../../node_modules/style-dictionary-design-tokens-example/style-dictionary.tokens.json') format('style-dictionary3'); ThemingTo support theming or similar use cases, a With the existing plugins you would run the // define what the current build "is"
postcssDesignTokens({ is: ['dark'] }) @design-tokens url('./tokens-light.json') format('style-dictionary3');
@design-tokens url('./tokens-dark.json') when('dark') format('style-dictionary3');
.foo {
color: design-token('color.background.primary');
} Will use This option is an array to allow more complex configurations. postcssDesignTokens({ is: ['light', 'mobile', 'branded-blue'] })
postcssDesignTokens({ is: ['dark', 'mobile', 'branded-blue'] })
postcssDesignTokens({ is: ['light', 'tablet', 'branded-blue'] })
postcssDesignTokens({ is: ['dark', 'tablet', 'branded-blue'] })
postcssDesignTokens({ is: ['light', 'desktop', 'branded-blue'] })
postcssDesignTokens({ is: ['dark', 'desktop', 'branded-blue'] })
postcssDesignTokens({ is: ['light', 'mobile', 'branded-green'] })
postcssDesignTokens({ is: ['dark', 'mobile', 'branded-green'] })
postcssDesignTokens({ is: ['light', 'tablet', 'branded-green'] })
postcssDesignTokens({ is: ['dark', 'tablet', 'branded-green'] })
postcssDesignTokens({ is: ['light', 'desktop', 'branded-green'] })
postcssDesignTokens({ is: ['dark', 'desktop', 'branded-green'] }) The above example is likely complete overkill but it's designed for the most complex case I could think of. (please tell me if there is something this does not support) @design-tokens url('./tokens/color_dark_branded-blue.tokens.json') when('dark', 'branded-blue') format('style-dictionary3');
@design-tokens url('./tokens/color_light_branded-blue.tokens.json') when('light', 'branded-blue') format('style-dictionary3');
@design-tokens url('./tokens/color_dark_branded-green.tokens.json') when('dark', 'branded-green') format('style-dictionary3');
@design-tokens url('./tokens/color_light_branded-green.tokens.json') when('light', 'branded-green') format('style-dictionary3');
@design-tokens url('./tokens/size_mobile.tokens.json') when('mobile') format('style-dictionary3');
@design-tokens url('./tokens/size_tablet.tokens.json') when('tablet') format('style-dictionary3');
@design-tokens url('./tokens/size_desktop.tokens.json') when('desktop') format('style-dictionary3'); This becomes a lot when you have a complex matrix, but you can create a single CSS file with all you Using design tokens in CSS.foo {
font-family: design-token('font.family.serif');
font-size: design-token('size.font.small');
color: design-token('color.font.base');
} This uses a new function Why a stringIt has to be a string because al design token formats have ID's which are incompatible with CSS. You should not be typing these manually. It also opens the door for namespaces. .foo {
font-family: design-token('font.family.serif', 'design-team-a');
font-size: design-token('size.font.small', 'design-team-b');
color: design-token('color.font.base');
} Why not
|
Beta Was this translation helpful? Give feedback.
-
We use queries.css@custom-media --media-phablet (30em <= width < 48em);
@custom-media --media-tablet (48em <= width < 62.5em); mediaQueryLoader.jsconst postcss = require('postcss');
const postcssPresetEnv = require('postcss-preset-env');
module.exports = function customMediaLoader(content, map, meta) {
const callback = this.async();
postcss([postcssPresetEnv({
stage: 1,
preserve: true,
})])
.process(content, { from: this.resourcePath })
.then((result) => {
postcss([postcssPresetEnv({
stage: 1,
exportTo: (variables) => {
if ('customMedia' in variables) {
const moduleContent = `export default ${JSON.stringify(variables.customMedia)}`;
callback(null, moduleContent, map, meta);
}
},
})])
.process(result, { from: this.resourcePath })
.catch(callback);
})
.catch(callback);
}; Usageimport queries from '@/styles/queries.css';
const mediaTablet = queries['--media-tablet'] // '(min-width: 48em) and (max-width: 62.499em)' |
Beta Was this translation helpful? Give feedback.
-
We currently use importFrom to include a global file of custom properties. e.g. :root {
/* Primary colors */
--color-primary-1: #153247;
--color-primary-2: #1d4f73;
--color-primary-3: #57a9e3;
--color-primary-4: #abdcff;
/* etc. */
}
|
Beta Was this translation helpful? Give feedback.
-
currently we have some separate css files with vars, import/export used to generate js\ts defs |
Beta Was this translation helpful? Give feedback.
-
We're using importFrom to feed values from JS into the CSS world, where the same file is used as a module in other parts of the JS world (Material UI theming), hence it is one source of truth for basic colors. /* eslint-disable sort-keys */
// eslint-disable-next-line unicorn/prefer-module
module.exports = {
customProperties: {
'--black': '#000',
'--dark-grey': '#323232',
'--grey': '#666',
'--light-grey': '#f0f0f0',
'--white': '#fff',
get '--primary'() {
return this['--dark-navy-blue'];
},
get '--secondary'() {
return this['--navy-blue'];
},
get '--tertiary'() {
return this['--cyan'];
},
get '--success'() {
return this['--grass'];
},
get '--warning'() {
return this['--orange-red'];
},
/* Brand Colors */
'--cyan': '#89D4D9',
'--dark-navy-blue': '#112130',
'--navy-blue': '#143B55',
/* Supplementary Colors (mostly for chart curves) */
'--aqua': '#39a9d3',
'--earth': '#8b572a',
'--grass': '#88ba4e',
'--lavender': '#9177d5',
'--orange-red': '#FF4500',
'--rose': '#d44250',
'--light-rose': '#FFB6C1',
'--sun': '#eeb541',
'--magenta': '#ca54ab',
/* Shadow Colors */
'--box-shadow-default': '0 2px 1px -1px rgba(0,0,0,0.2)',
'--box-shadow-focus': '0 0 0 0.2rem rgba(0,123,255,.25)',
'--border-radius-default': '2px',
},
};
/* eslint-enable sort-keys */ |
Beta Was this translation helpful? Give feedback.
-
How can I silence this warning BTW? It is all over the place during compilations |
Beta Was this translation helpful? Give feedback.
-
Hey @romainmenke we use the custom properties plugin to expose our css color variables to JS so that they can be used in the codebase for inline styles where inline styles are required for color or for libraries which requires colors to be passed through props as valid color value. We don't want anyone to use the hardcoded colors in our codebase because they are hard to manage and any one can change hex easily and sometime can use colors which are outside of our design system |
Beta Was this translation helpful? Give feedback.
-
Hi there! We have just released PostCSS Design Tokens Our hope is that this will be a more reliable and controlled way to inject values into your CSS. This is not a (drop-in) replacement for any of the plugins with |
Beta Was this translation helpful? Give feedback.
-
My use of I use hugo to build my static site and dev builds simply include all css and all js defined in the themes. In production it includes no CSS or JS and relies on a build process to add/inject the required assets. The build process looks for files following a naming convention of <html element name, classname>[-inline|-sync|-async].css (and JS). Once the build process has the set of files, it parses each HTML file and adds With this set up I end up with lots of small CSS files tied to HTML elements and classnames. Using
|
Beta Was this translation helpful? Give feedback.
-
I'm using https://github.com/codetot-web/ct-bones/blob/production/webpack.config.js#L71 I also use https://github.com/codetot-web/ct-bones/blob/production/codetot/assets.php#L136 |
Beta Was this translation helpful? Give feedback.
-
Hi there 👋 Where Design Tokens are great for inserting values into CSS and form a natural successor for We ended up creating postcss-extract. It allows you to extract bits of CSS and it is powered by queries written in CSS. The feature set will grow over time and we think it is the better solution:
|
Beta Was this translation helpful? Give feedback.
-
Hi, Thanks for doing what you're doing. We're using postcss-custom-media plugin and our setup is:
We're getting, when upgrading postcss-custom-media from 8.0.2 to 9.0.1,
Please advice. Thanks. |
Beta Was this translation helpful? Give feedback.
-
Hi everyone 👋 We have written the code for the drop-in replacements but we decided against publishing and maintaining these ourselves. You can read more about it here : #734 TL;DR; if anyone is willing to take over maintenance of the functionality behind The source code is available and anyone is free to take this and publish their own plugins based on that. To summarize :
|
Beta Was this translation helpful? Give feedback.
-
https://github.com/GoogleChromeLabs/postcss-jit-props This plugin is also a good replacement for |
Beta Was this translation helpful? Give feedback.
-
https://github.com/allmyfutures/postcss-custom-media-generator This plugin seems to be a good replacement for |
Beta Was this translation helpful? Give feedback.
-
https://github.com/csstools/postcss-plugins/tree/main/plugins/postcss-global-data#readme This plugin is a good replacement for |
Beta Was this translation helpful? Give feedback.
Hi everyone 👋
We have written the code for the drop-in replacements but we decided against publishing and maintaining these ourselves.
You can read more about it here : #734
TL;DR; if anyone is willing to take over maintenance of the functionality behind
importFrom
/exportTo
please let us (and each other) know.The source code is available and anyone is free to take this and publish their own plugins based on that.
To summarize :
exportTo
For
exportTo
we advice everyone to switch over to@csstools/postcss-extract
. We think it is a more powerful tool and it isn't limited to a small set of features, anything can be exported.If you do depend on
exportTo
and migrating is absolutely impossibl…