DEV Community

Cover image for postcss-custom-property-prefixer
ice breaker
ice breaker

Posted on

postcss-custom-property-prefixer

Add prefix to your css custom-property

Usage

<npm/yarn/pnpm> i -D postcss-custom-property-prefixer
Enter fullscreen mode Exit fullscreen mode

Then register this plugin into your postcss.config.js:

module.exports = {
  plugins: {
    // ...
    'postcss-custom-property-prefixer': {
      // prefix option must be passed! 
      prefix: 'ice-'
    }
    // ...
  }
}
Enter fullscreen mode Exit fullscreen mode

Demo

.a {
  --tab-color: hsl(var(--bc) / var(--tw-text-opacity, 1));
  --tab-bg: hsl(var(--b1) / var(--tw-bg-opacity, 1));
  --tab-border-color: hsl(var(--b3) / var(--tw-bg-opacity, 1));
}
Enter fullscreen mode Exit fullscreen mode

Will be transformed to:

.a {
  --ice-tab-color: hsl(var(--ice-bc) / var(--ice-tw-text-opacity, 1));
  --ice-tab-bg: hsl(var(--ice-b1) / var(--ice-tw-bg-opacity, 1));
  --ice-tab-border-color: hsl(var(--ice-b3) / var(--ice-tw-bg-opacity, 1));
}
Enter fullscreen mode Exit fullscreen mode

Not right? Yes! Default this plugin will transform all css custom property!

If you want to ignore some custom properties like --tw-*, you should pass some ignore* options, See Below!

Use with Tailwindcss

Css nodes are generated by tailwindcss, because it's custom property all start with '--tw-', so you can pass options like below.

    'postcss-custom-property-prefixer': {
      // your custom prefix
      prefix: 'ice-',
      ignoreValueCustomProperty(cp, decl) {
        // ignore value
        return cp.startsWith('--tw-')
      },
      ignoreProp(decl) {
        // ignore prop
        return decl.prop.startsWith('--tw-')
      }
    }
Enter fullscreen mode Exit fullscreen mode

Options

ignoreValueCustomProperty

plugin options:

    'postcss-custom-property-prefixer': {
      prefix: 'ice-',
      ignoreValueCustomProperty(cp) {
        return cp.startsWith('--tw-')
      }
    }
Enter fullscreen mode Exit fullscreen mode

Before:

.a {
  /*                              ⬇ --tw-* */
  --tab-color: hsl(var(--bc) / var(--tw-text-opacity, 1));
  /*                            ⬇ --tw-* */
  --tab-bg: hsl(var(--b1) / var(--tw-bg-opacity, 1));
  /*                                      ⬇ --tw-* */
  --tab-border-color: hsl(var(--b3) / var(--tw-bg-opacity, 1));
}
Enter fullscreen mode Exit fullscreen mode

After:

.a {
  --ice-tab-color: hsl(var(--ice-bc) / var(--tw-text-opacity, 1));
  --ice-tab-bg: hsl(var(--ice-b1) / var(--tw-bg-opacity, 1));
  --ice-tab-border-color: hsl(var(--ice-b3) / var(--tw-bg-opacity, 1));
}
Enter fullscreen mode Exit fullscreen mode

See! All css decl's value's custom properties which start with --tw- are ignored!

ignoreDecl

This option will ignore the whole decl!

    'postcss-custom-property-prefixer': {
      prefix: 'ice-',
      ignoreDecl(decl) {
        return decl.prop === '--tab-color' || decl.value.includes('hsl(var(--b1)')
      },
      ignoreValueCustomProperty(cp) {
        return cp.startsWith('--tw-')
      }
    }
Enter fullscreen mode Exit fullscreen mode

Before:

.a {
  /* prop === --tab-color , this decl will be ignored */
  --tab-color: hsl(var(--bc) / var(--tw-text-opacity, 1)); 
  /* value.includes('hsl(var(--b1)') , this will be ignored */
  --tab-bg: hsl(var(--b1) / var(--tw-bg-opacity, 1)); 
  /* will be transformed */
  --tab-border-color: hsl(var(--b3) / var(--tw-bg-opacity, 1)); 
}
Enter fullscreen mode Exit fullscreen mode

After:

.a {
  --tab-color: hsl(var(--bc) / var(--tw-text-opacity, 1));
  --tab-bg: hsl(var(--b1) / var(--tw-bg-opacity, 1));
  --ice-tab-border-color: hsl(var(--ice-b3) / var(--tw-bg-opacity, 1));
}
Enter fullscreen mode Exit fullscreen mode

ignoreProp

    'postcss-custom-property-prefixer': {
      prefix: 'ice-',
      ignoreProp(decl) {
        return decl.prop === '--tab-color'
      },
      ignoreValueCustomProperty(cp) {
        return cp.startsWith('--tw-')
      }
    }
Enter fullscreen mode Exit fullscreen mode

Before:

.a {
  /* ⬇ only ignore the prop , not value ⬇ */
  --tab-color: hsl(var(--bc) / var(--tw-text-opacity, 1)); 
  --tab-bg: hsl(var(--b1) / var(--tw-bg-opacity, 1)); 
  --tab-border-color: hsl(var(--b3) / var(--tw-bg-opacity, 1)); 
}
Enter fullscreen mode Exit fullscreen mode

After:

.a {
  /* ⬇ target prop */
  --tab-color: hsl(var(--ice-bc) / var(--tw-text-opacity, 1));
  --ice-tab-bg: hsl(var(--ice-b1) / var(--tw-bg-opacity, 1));
  --ice-tab-border-color: hsl(var(--ice-b3) / var(--tw-bg-opacity, 1));
}
Enter fullscreen mode Exit fullscreen mode

ignoreValue

    'postcss-custom-property-prefixer': {
      prefix: 'ice-',
      ignoreValue(decl) {
        return decl.value.includes('hsl(var(--b3)')
      },
      ignoreValueCustomProperty(cp) {
        return cp.startsWith('--tw-')
      }
    }
Enter fullscreen mode Exit fullscreen mode

Before:

.a {
  --tab-color: hsl(var(--bc) / var(--tw-text-opacity, 1)); 
  --tab-bg: hsl(var(--b1) / var(--tw-bg-opacity, 1));  
  /*                       ⬇ target value , ignored*/
  --tab-border-color: hsl(var(--b3) / var(--tw-bg-opacity, 1));
}
Enter fullscreen mode Exit fullscreen mode

After:

.a {
  --ice-tab-color: hsl(var(--ice-bc) / var(--tw-text-opacity, 1));
  --ice-tab-bg: hsl(var(--ice-b1) / var(--tw-bg-opacity, 1));
  --ice-tab-border-color: hsl(var(--b3) / var(--tw-bg-opacity, 1));
}
Enter fullscreen mode Exit fullscreen mode

prefix

Type: String|PrefixFunction, The prefix will be add to all custom property!

export type PrefixFunction = (decl: Declaration, target: 'prop' | 'value') => string
Enter fullscreen mode Exit fullscreen mode
    'postcss-custom-property-prefixer': {
      prefix: (decl,target)=>{
        if (target === 'prop' && decl.prop.startsWith('--bg-')) {
          return 'aaa-'
        }
        if (target === 'value' && decl.prop.startsWith('--text-')) {
          return 'bbb-'
        }
        return ''
      },
    }
Enter fullscreen mode Exit fullscreen mode

Before:

.a {
  --bg-red: hsl(var(--text-red-100));
  --text-red: hsl(var(--text-red-500));
}
Enter fullscreen mode Exit fullscreen mode

After:

.a {
  --aaa-bg-red: hsl(var(--text-red-100));
  --text-red: hsl(var(--bbb-text-red-500));
}
Enter fullscreen mode Exit fullscreen mode

propPrefix

Type: Same as prefix

you can pass different prefix to prop and value:

    'postcss-custom-property-prefixer': {
      prefix: 'ice-',
      propPrefix: 'xx-',
      ignoreValueCustomProperty(cp) {
        return cp.startsWith('--tw-')
      }
    }
Enter fullscreen mode Exit fullscreen mode
.a {
  --tab-color: hsl(var(--bc) / var(--tw-text-opacity, 1)); 
  --tab-bg: hsl(var(--b1) / var(--tw-bg-opacity, 1));  
  --tab-border-color: hsl(var(--b3) / var(--tw-bg-opacity, 1)); 
}
Enter fullscreen mode Exit fullscreen mode

After:

.a {
  --xx-tab-color: hsl(var(--ice-bc) / var(--tw-text-opacity, 1));
  --xx-tab-bg: hsl(var(--ice-b1) / var(--tw-bg-opacity, 1));
  --xx-tab-border-color: hsl(var(--ice-b3) / var(--tw-bg-opacity, 1));
}
Enter fullscreen mode Exit fullscreen mode

transformProp

Boolean: whether transform css decl's prop, default: true

transformValue

Boolean: whether transform css decl's value, default: true

License

MIT License © 2023-PRESENT sonofmagic

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

Top comments (0)

AWS Security LIVE!

Join us for AWS Security LIVE!

Discover the future of cloud security. Tune in live for trends, tips, and solutions from AWS and AWS Partners.

Learn More

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay