Coder Social home page Coder Social logo

googlechromelabs / postcss-jit-props Goto Github PK

View Code? Open in Web Editor NEW
208.0 7.0 9.0 457 KB

A CSS custom property helper based on PostCSS. Supply a pool of variables and this plugin will add them to the stylesheet as they are used.

Home Page: https://stackblitz.com/edit/jit-open-props?file=postcss.config.js

License: Apache License 2.0

JavaScript 98.85% CSS 1.15%
postcss-plugin custom-properties bundle-size

postcss-jit-props's Introduction

PostCSS (Just In Time) Props

Only ship used variables! A CSS custom property helper based on PostCSS

Version postcss compatibility Unit Tests


postcss-jit-props watches for CSS variables and ensures a value entry exists in the stylesheet. Try in browser

This lets you provide a huge pool of properties for development and design, and rather than try and purge unused variables, only adds what was used.


Example

CSS Before / During Development:

.foo {
  color: var(--brand-1);
  padding: var(--size-1) var(--size-2);
  margin-block-start: var(--size-2);
  animation: var(--fade-in);
}

@media (--dark) {
  .foo {
    color: white;
  }
}

CSS After / Result of Plugin:

+ @custom-media --dark (prefers-color-scheme: dark);

+ :root {
+   --brand-1: #81A1C1;
+   --size-1: 1rem;
+   --size-2: 2rem;
+   --fade-in: fade-in .5s ease;
+ }

.foo {
  color: var(--brand-1);
  padding: var(--size-1) var(--size-2);
  margin-block-start: var(--size-2);
  animation: var(--fade-in);
}

@media (--dark) {
  .foo {
    color: white;
  }
}

+ @keyframes fade-in {
+   to { opacity: 1; }
+ }

Usage

Step 1: Install plugin:

npm install --save-dev postcss-jit-props

Step 2: Add the plugin to plugins in postcss.config.js and pass it your props (CSS || JS || JSON).

Pass JS objects:

module.exports = {
  plugins: [
    require('postcss-jit-props')({
      '--brand-1': '#81A1C1',
      '--size-1': '1rem',
      '--size-2': '2rem',
      '--fade-in': 'fade-in .5s ease',
      '--fade-in-@': '@keyframes fade-in {to { opacity: 1 }}',
      '--dark': '@custom-media --dark (prefers-color-scheme: dark);',
      '--text': 'white',
      '--text-@media:dark': 'black',
    }),
    require('autoprefixer'),
  ]
}

or pass CSS files

module.exports = {
  plugins: [
    require('postcss-jit-props')({files: ['./props.css']}),
    require('autoprefixer'),
  ]
}

or JSON โœจ

Javascript and JSON must use the -@ suffix on their custom property name in order for jit-props to find associated @keyframes

Configure where the selector the props are pushed to. Some CSS Module environments, for example, don't want the props in :root, so we can configure the plugin to push them where it's acceptable for the environment, like :global:

module.exports = {
  plugins: [
    require('postcss-jit-props')({
      ...MyProps,
      custom_selector: ':global'
    }),
    require('autoprefixer'),
  ]
}

Configure the @layer the props are pushed to. :

module.exports = {
  plugins: [
    require('postcss-jit-props')({
      ...MyProps,
      layer: 'design.system'
    }),
    require('autoprefixer'),
  ]
}

postcss-jit-props's People

Contributors

argyleink avatar benbender avatar eltonmesquita avatar inokawa avatar kucrut avatar mod3x avatar romainmenke avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

postcss-jit-props's Issues

Is -& or -@ suffix?

I see in the doc this passage:

Javascript and JSON must use the -& suffix on their custom property name in order for jit-props to find associated @Keyframes

But in the documentation example -@ is used instead:

require('postcss-jit-props')({
      '--fade-in-@': '@keyframes fade-in {to { opacity: 1 }}',
})

Props discovered, that contain adaptive props, dont have their dark values resolved

Shadows are a good example

--shadow-1: 0 1px 2px -1px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 9%));

jit-props finds the child props for color and strength, but only injects the light theme versions:

--shadow-color: 220 3% 15%;
--shadow-strength: 1%;
--shadow-1: 0 1px 2px -1px hsl(var(--shadow-color) / calc(var(--shadow-strength) + 9%));

Bug: Nested properties are purged if the first prop is not defined

I'm using "nested" props to encapsulate properties in components while having the ability of global defaults at the same time (in-depth explanation here)

Anyway, the following syntax isn't picked up:

border-radius: var(--button-radius, var(--radius, 0.25em));

--button-radius isn't defined, but --radius is.
--radius gets purged by the lib... ๐Ÿ˜ข
If I remove the nesting, --radius is picked up.

Error when using Astro

When using this plugin with Astro I get the following error when running astro build but no such error occurs when running astro dev interestingly.

A PostCSS plugin did not pass the `from` option to `postcss.parse`. 
This may cause imported assets to be incorrectly transformed. 
If you've recently added a PostCSS plugin that raised this warning, please contact the package author to fix the issue.

Through the process of elimination it seemed to be this plugin hence me contacting you as per the message ;-)

For reference here is the postcss.config.cjs file contents:

const openProps = require('open-props');

module.exports = {
  plugins: [
    require('postcss-nesting'),
    require('postcss-custom-media'),
    require('postcss-jit-props')(openProps),
    require('postcss-preset-env')({ stage: 0 })
  ]
};

Here is the package.json contents

{
  "name": "@example/basics",
  "type": "module",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "dev": "astro dev",
    "start": "astro dev",
    "build": "astro build",
    "preview": "astro preview",
    "astro": "astro"
  },
  "dependencies": {
    "astro": "^2.0.5",
    "open-props": "^1.5.5"
  },
  "devDependencies": {
    "postcss-custom-media": "^9.1.1",
    "postcss-jit-props": "^1.0.9",
    "postcss-nesting": "^11.1.0",
    "postcss-preset-env": "^8.0.1"
  }
}

Modifying props during development doesn't update page

Given the setup below, if I was to add/remove/change any css variables within props.css, those changes will not update during development. Unsure if this is a stipulation of this plugin.
Tested with Astro 1.6 and PostCSS 8.4.18

postcssJitProps({
  files: ['./src/styles/common/props.css'],
})

Incompatibility with some coding styles

Hello!

I'm a fan of putting a space after the opening and before the closing function parens (for multiple reasons), and it seems like this plugin is not compatible with that type of coding style because it's using (too) specific sub-string to match when collecting the properties, ie var(--.

Perhaps something like this would make it more forgiving?

Declaration (node, {Declaration}) {
	// bail early
	if (node[processed]) return

	let matches = node.value.match(/var\(\s*[\w\d-]+\s*\)/g);

	if (!matches) return;

	let props = matches.map(v => v.match(/var\(\s*([\w\d-]+)\s*\)/)[1])

	// ...
}

Disclaimer: My regex-fu is questionable ๐Ÿ˜

Optimization

  • should check if :root is in the stylesheet already or not
  • should check if that existing :root has props already before injecting
:root {
  --red: red;
}

p {
  color: var(--blue);
}

should be:

:root {
  --red: red;
  --blue: blue;
}

p {
  color: var(--blue);
}

not:

:root {
  --red: red;
}

:root {
  --blue: blue;
}

p {
  color: var(--blue);
}

Breaks local fonts folder being visible in the browser Sources folder tree

I have this working entirely except the one thing it is breaking is my local @fontface fonts. I am using:

  • @import rules for buttons, normalize
  • postcss.config for jitprops(and loading open-props):
const postcssJitProps = require('postcss-jit-props');
const OpenProps = require('open-props');
module.exports = {
  plugins: [postcssJitProps(OpenProps), require('autoprefixer')],
};
  • VITE to build a WordPress project

The problem appears to be that despite the font folder building as normal to /assets/dist/fonts and is physically there, it fails to show up in the Sources location when inspecting in the browser?!? Otherwise all the style references are the same and correct.

Breaks when the source file only contains @at rules.

Hello!

When processing a source file which only contains at-rules, the plugin breaks.

From my error code and brief skim, it seems to occur from Line 123 of index.js.

The error reported reads as: Cannot read properties of undefined (reading 'source').

The problem file in question is a file from open-props: open-props/media.css.

I will do a workaround and create a pull request once I get home.

Thanks

Should work with a client side switch

see #14 (comment)

either this plugin should automatically place the props under a class/data attribute/etc with a generic set of selectors OR it should allow specifying what selector to additionally put the props under.

Feature request: Support file-globbing

It would be really nice, if the plugin would support glob-path like { files: ["./src/styles/props/*.css"] } for input. That, btw, would align with vscode's cssvars-plugin.

Compatibility issues with Astro

It seems like there are some compatibility issues with Astros fences used inside of .astro files.
If I'm trying to integrate it into an astro project but I always run into the following error (e.g.):

Unknown word
    1  |  ---
       |   ^
    2  |  import Button from '../helper/Button.astro';
    3  |  ---

It seems like it's trying to scan the whole file, even though the CSS is only inside of the <style> block.
I have no other plugins installed besides postcss-jit-props.

module.exports = {
  plugins: [
    require('postcss-jit-props')({
      '--xl': '(min-width: 1200px)',
    }),
  ],
};

Includes all variables when passed in from file

When i include a file with css vars rather than input the vars directly into the postcss-jit-props as an option, the entire css file with all the unused vars is included in the build. I'm using Astro to build.

Here is my postcss.config.js stripped down for brevity:

module.exports = {
    plugins: [
        require("postcss-jit-props")({
            "--size-15": "30rem",
            "--size-14": "20rem",
            "--size-13": "15rem",
            "--size-12": "10rem",
            "--size-11": "7.5rem",
            "--size-10": "5rem",
            "--size-9": "4rem",
            "--size-8": "3rem",
            "--size-7": "2rem",
            "--size-6": "1.75rem",
            "--size-5": "1.5rem",
            "--size-4": "1.25rem",
            "--size-3": "1rem",
            "--size-2": ".5rem",
            "--size-1": ".25rem",
            "--size-00": "-.25rem",
            "--size-000": "-.5rem",
            files: [ "./src/styles/colors.css" ]
        })
    ]
}

The --size-* vars are included only when used in my css, but the colors.css file included in the files option is included in full. I'm not using the :root selector in my colors.css file, I am using two selectors to have different palettes for light and dark mode. I wonder if that is causing the issue. The selectors used are .light, [data-color-mode=light] and .dark, [data-color-mode=dark].

Using with lit and astro

Using this package doesn't work with lit and Astro. it doesn't recognize the props being used in lit components. I'm using typescript. It recognizes props on .astro files just fine.

html inline style attributes corrupted

I was building a site with eleventy, open-props, postcss-jit-props and stumbled across this build problem.

The following inline style attribute

<section class='nested' style="background-image: url(/images/me.jpg)">
  <h2>{{title}}</h2>
</section>

gets transformed to

    <section class='nested' style=":root {}
background-image: url(/images/me.jpg)">
      <h2>is this image broken?</h2>
    </section>

I am assuming by postcss-jit-props.

I have created a simple repo to reproduce the bug in https://github.com/andystevenson/weird-inline-style-build-bug.

To reproduce run

npm install
npm run dev

You will observe 2 images (first one is unsplash)

image

Then run

npm run build
npm run preview

and observe the second image is missing because of the above issue.

image

Bug: "does not pass the 'from' option to 'postcss.parse'"

Vite 3 shows the following warning when this plugin is enabled:

A PostCSS plugin did not pass the `from` option to `postcss.parse`. This may cause imported assets to be incorrectly transformed. If you've recently added a PostCSS plugin that raised this warning, please contact the package author to fix the issue.

The docs for postcss.parse are here.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.