From all the Open Props to only the Open Props I use

essential love drawn in color on a chalkboard

Photo by Sharon McCutcheon on Unsplash

As I wrote in my last post, I started using Open Props to define the colors, fonts, and font sizes for this site. I also used Open Props to define the radius and animation you see when you hover over the site's links.

There are a lot of available props and my site's use of them only scratches the surface, using less than 20 of them as of this writing.

So, the question is: How can I have the 100s of Open Props available during development, yet have my production CSS file only contain the ones I use?

Here's how I incorporate Open Props in my CSS (I'm using Sass) during development:

@use "variables";
@use "reset";
@use "desktop";
@use "mobile";
@import "https://unpkg.com/open-props/open-props.min.css";

Enter postcss-jit-props. It's a plugin for PostCSS that takes your CSS file, scans it for the Open Props you actually use and adds them to your CSS file.

But wait, I wondered how can I have that @import line in my CSS file, but not have it present in production. If I left it in during production, the process of adding only the props I use would not help in file size reduction at all.

I'm using Sass for my CSS and there's no apparent way to conditionally import a file. If you know of some way, I'm all ears. Let me know on Twitter.

So I posed this question to Adam Argyle on the Open Props Discord. He was equally stumped, but suggested that I consider having two Sass files, one for dev and one for production. The dev version would have the import and the production version would not (and would use postcss-jit-props to bring in the props I used).

Since this is a small, personal project, that seemed the way to go. And since I'm building the site with 11ty, it would be relatively straightforward to have separate scripts in my package.json, one for dev and one for production (which I already had). Each would simply invoke the Sass build from different main Sass files that did all the importing.

Backing up a little bit here, PostCSS has a CLI and can use a config file, i.e., postcss.config.js, to specify the plugins and options that it should use. Here's a look at mine, as suggested on the Open Props site:

// postcss.config.js
const postcssJitProps = require("postcss-jit-props");
const OpenProps = require("open-props");

module.exports = {
plugins: [postcssJitProps(OpenProps)],
};

With that in place, here's what my 11ty package.json file looks like with the relevant build scripts to handle dev and production. Note that one is called main-dev.scss and the other is called main-prod.scss (oddly enough).

{
"name": "bobmonsour.com",
"version": "1.0.0",
"description": "This is a base set of files needed to start a project in Eleventy. Make a project directory and put these files in it.",
"main": ".eleventy.js",
"scripts": {
"watch:sass": "sass --no-source-map --watch src/sass/main-dev.scss:_site/css/main.css",
"watch:eleventy": "eleventy --serve",
"build:sass": "sass --no-source-map src/sass/main-prod.scss:_site/css/main.css",
"build:eleventy": "eleventy",
"postbuild": "postcss _site/css/main.css -o _site/css/main.css",
"start": "npm-run-all --parallel watch:*",
"build": "npm-run-all build:sass build:eleventy",
"clean": "rimraf ./_site"
},
"keywords": [],
"author": "Bob Monsour",
"license": "ISC",
"devDependencies": {
"@11ty/eleventy": "^1.0.0",
"@11ty/eleventy-plugin-syntaxhighlight": "^4.0.0",
"npm-run-all": "^4.1.5",
"open-props": "^1.3.8",
"postcss": "^8.4.6",
"postcss-cli": "^9.1.0",
"postcss-jit-props": "^1.0.4",
"rimraf": "^3.0.2",
"sass": "^1.48.0"
}
}

This works great.

I have to point out one thing that took me a while to figure out and maybe others wonder about this too. One of the people I find most inspirational as I learn more about 11ty and all it is capable of is Stephanie Eckles. She has produced so very many useful posts and resources all about 11ty. As I looked at this particular repository of her 11ty-sass-skeleton and examined the package.json file, I could not for the life of me figure out how the "postbuild" script would ever be invoked. Clearly it seems that it would be run after a "build." But how? It took a while, thinking and googling, to finally find that a script named "postbuild" was the one that would be invoked after the "build" script. While intuitive, I took me more time than I expected to learn this little tidbit. In short, if you name a script as "post" followed by the name of another script, it runs after it. Similarly, if you name a script as "pre" followed by the name of another script, it runs before it.

Anyway, that's all for now as I continue my journey into the world of 11ty, CSS, and other stuff.