JetBrains / svg-mixer

Node.js toolset for generating & transforming SVG images and sprites in modern way
MIT License
176 stars 40 forks source link

Is there any way to use CSS variables together with svg-transform-loader? #71

Open wujekbogdan opened 4 years ago

wujekbogdan commented 4 years ago

When I do the following:

.element {
  background-image: url('icon.svg');
  -svg-mixer-stroke: var(--my-custom-color-1);
}

then var(--my-custom-color-1) is not evaluated to an actual color.

I thought that maybe I could use the transform callback together with postcss-css-variables, but it's not possible because the CSS file is not available within the context of this callback.


I tried to modify the plugin to be able to access the Declaration object and transform CSS variables into strings with postcss-css-variables, but I got stuck at processing CSS variables https://github.com/MadLittleMods/postcss-css-variables/issues/106

kisenka commented 4 years ago

Yes, it's possible. You'll need to use postcss-move-props-to-bg-image-query plugin and configure computeCustomProps option in a following way:

.postcssrc.js

module.exports = {
  plugins: [
    require('postcss-css-variables')(),
    require('postcss-move-props-to-bg-image-query')({
      computeCustomProps: require('postcss-css-variables')()
    })
  ]
};

It's not documented feature so in a few days I'll add it to the docs :)

wujekbogdan commented 4 years ago

@kisenka

Thanks for your help, but this solution has one big downside: it requires the whole CSS to be passed through postcss-css-variables plugin so all my CSS variables are converted to their string representations.

If I omit the postcss-css-variables plugin:

module.exports = {
  plugins: [
    require('postcss-move-props-to-bg-image-query')({
      computeCustomProps: require('postcss-css-variables')()
    })
  ]
};

Then I get the following error:

Module build failed (from ./node_modules/postcss-loader/src/index.js):
TypeError: Cannot read property 'apply' of undefined
    at /Users/wujekbogdan/htdocs/postcss-test/node_modules/postcss-css-variables/index.js:147:17
    at Array.forEach (<anonymous>)
    at logResolveValueResult (/Users/wujekbogdan/htdocs/postcss-test/node_modules/postcss-css-variables/index.js:145:16)
    at _logResolveValueResult (/Users/wujekbogdan/htdocs/postcss-test/node_modules/postcss-css-variables/lib/resolve-decl.js:81:4)
    at resolveDecl (/Users/wujekbogdan/htdocs/postcss-test/node_modules/postcss-css-variables/lib/resolve-decl.js:91:21)
    at /Users/wujekbogdan/htdocs/postcss-test/node_modules/postcss-css-variables/index.js:255:7
    at Array.forEach (<anonymous>)
    at /Users/wujekbogdan/htdocs/postcss-test/node_modules/postcss-css-variables/index.js:252:33
    at Array.forEach (<anonymous>)
    at /Users/wujekbogdan/htdocs/postcss-test/node_modules/postcss-css-variables/index.js:251:18
    at Array.forEach (<anonymous>)
    at /Users/wujekbogdan/htdocs/postcss-test/node_modules/postcss-css-variables/index.js:234:46
    at computeCustomProps (/Users/wujekbogdan/htdocs/postcss-test/node_modules/postcss-move-props-to-bg-image-query/utils.js:45:9)
    at /Users/wujekbogdan/htdocs/postcss-test/node_modules/postcss-move-props-to-bg-image-query/index.js:53:17
    at async Promise.all (index 5)

Is there any way to make postcss-css-variables process CSS variables only when used together with -svg-mixer-*?

kisenka commented 4 years ago

I didn't test postcss-move-props-to-bg-image-query with postcss-css-variables, but it surely works with postcss-custom-properties. @wujekbogdan you can create demo repo with minimal setup and I'll try to help you.

wujekbogdan commented 4 years ago

I was referring to the code snippet you posted before:

module.exports = {
  plugins: [
    require('postcss-css-variables')(),
    require('postcss-move-props-to-bg-image-query')({
      computeCustomProps: require('postcss-css-variables')()
    })
  ]
};

At the 3rd line you import the 'postcss-css-variables' plugin. If I do so then everything works fine - the CSS variables are transformed when used together with -svg-mixer-*.

The problem is that I don't want to pass my entire CSS through 'postcss-css-variables' because it replaces all my CSS variables with their strings representations - which I'd like to avoid.

The following code doesn't work:

module.exports = {
  plugins: [
    require('postcss-move-props-to-bg-image-query')({
      computeCustomProps: require('postcss-css-variables')()
    })
  ]
};

It causes an error I posted before.


@wujekbogdan you can create demo repo with minimal setup and I'll try to help you.

Sure, I'll do it soon. Thanks for your help!

kisenka commented 4 years ago

@wujekbogdan ping

wujekbogdan commented 4 years ago

@kisenka I'll create a repo soon, please don't close the ticket.

kisenka commented 4 years ago

@wujekbogdan ping

Orhideous commented 3 years ago

Ok, I figured how to make this work.

import postCSSCustomProperties from 'postcss-custom-properties';
import moveProps from 'postcss-move-props-to-bg-image-query';
moveProps({
    computeCustomProps: postCSSCustomProperties({ preserve: false }).Once,
})

:root {
    --bookmark-color: green;
}

.bookmark {
    background-image: url(../images/assets/bookmark.svg);
    -svg-mixer-fill: var(--bookmark-color);
    background-repeat: no-repeat;
    background-position: center;
}
andreymal commented 1 year ago

It doesn't work with postcss-custom-properties 12+ because of changes in the PostCSS 8 API.

Also importFrom was removed in postcss-custom-properties 13, which breaks our use case.

I had to write this to make it work again:

import postcss from 'postcss';
import postCSSGlobalData from '@csstools/postcss-global-data';
import postCSSCustomProperties from 'postcss-custom-properties';
import moveProps from 'postcss-move-props-to-bg-image-query';
moveProps({
  computeCustomProps: root => postcss([
    postCSSGlobalData({
      files: ['path/to/global-variables.css'],
    }),
    postCSSCustomProperties({ preserve: false }),
  ]).process(root),
})