The foundation of your next design system — CSS variables to accelerate development and encourage consistency

  • By Bokeh
  • Last update: Dec 28, 2022
  • Comments: 16



Faster, more consistent, more maintainable CSS


Version Size

Pollen is a configurable library of CSS variables. It lets you write faster, more consistent, and more maintainable styles. Use it in any stack and easily extend it as a build tool for your own custom design systems.

What it looks like

Pollen's low-level design tokens can be used to build any project. They're easy to customise and extend, and they're globally responsive. They don't require preprocessors, class naming conventions, or any new non-standard syntax.


Read the full documentation at



  • 1

    Fluid sizes

    I've been using Pollen for the last 2 weeks and it's amazing.

    I think that one addition that would be nice is a fluid sizing system. I've seen the same in Open Props although I think that their implementation is not great.

    I know that I can configure fluid sizes myself, but it would be really great to have them out of the box since I think this is a good pattern that should be encouraged.

    The Open Props implementation is very simple:

      --font-size-fluid-0: clamp(.75rem, 2vw, 1rem);
      --font-size-fluid-1: clamp(1rem, 4vw, 1.5rem);
      --font-size-fluid-2: clamp(1.5rem, 6vw, 2.5rem);
      --font-size-fluid-3: clamp(2rem, 9vw, 3.5rem);

    but I think that this is too simple, since this means that fonts will shrink at different speeds and reach their min and max at different viewport widths.

    What I have been using is based on this css-tricks article and it works perfectly. The downside with this method is, that it's not possible to use the --scale-X custom properties in CSS because it involves doing some math that can't be done with <dimension> types.

    I'm not 100% sure how to solve this best, but one suggestion would be to add a linearClamp function that takes a viewport min and max width in px and a size min and max in rem and spits out the clamp([...]) property. This can then be used to generate the default values in pollen.css but also by users of the library to generate their own fluid sizes.

    What do you think? If you like this idea I can create a PR to discuss this further.

  • 2

    [RFC] Generate variables with build process

    Thank you. This project is great. Simple, easy, and high value. I really appreciate this. And while I'm happy to just build, build, build with the defaults, we have some design standards that fall outside of those defaults.

    Our current solution is overrides, but I can already see value in being able to generate values instead for the variables already defined in pollen. Both the colors addon and are features that could leverage this.

    Is there interest in supporting something like this as part of this project?

    Example: Pseudo-TypeScript method of defining gray as #1e1e20 could yield this overly verbose result.

    type Colors = {
      gray?: string;
      // other colors
    let brandColors: Colors = {
      gray: "#1e1e20",
      // other colors
        --color-gray-rbg: 30, 30, 30;
        --color-gray-100: #1e1e1e;
        --color-gray-80:  #4a4a4a;
        --color-gray-60:  #777777;
        --color-gray-40:  #a3a3a3;
        --color-gray-24:  #c7c7c7;
        --color-gray-16:  #d8d8d8;
        --color-gray-08:  #eaeaea;
        --color-gray-80a: rgba(var(--color-gray-rbg), .8);
        --color-gray-60a: rgba(var(--color-gray-rbg), .6);
        --color-gray-40a: rgba(var(--color-gray-rbg), .4);
        --color-gray-24a: rgba(var(--color-gray-rbg), .24);
        --color-gray-16a: rgba(var(--color-gray-rbg), .16);
        --color-gray-08a: rgba(var(--color-gray-rbg), .08);
  • 3

    Support shadow DOM

    Currently variables are generated in this fashion:

    :root {
      --scale-0: 1rem;
      --scale-1: 1.125rem;
      --scale-2: 1.25rem;
      --scale-3: 1.5rem;
      --scale-4: 1.875rem;
      --scale-5: 2.25rem;
      --scale-6: 3rem;
      --scale-7: 3.75rem;
      --scale-8: 4.5rem;

    Would it be possible to omit :root { to support scoped usage? Eg. in shadow DOM.

  • 4

    Support for wider color gamuts

    Safari supports eye-popping colors using the the color() function. I wonder if it'd be neat to maybe add support for this with graceful fallback to regular old hex/hsl.

    I have successfully used this on the Svelte Summit website and I think the result is pretty nice. You can see the difference by visiting on Chrome vs Safari.

    It would be as simple as figuring out what colors that would be nice to have and then just adding support via something like this (example taken from the WebKit explainer page):

    :root {
        --bright-green: rgb(0, 255, 0);
    /* Display-P3 color, when supported. */
    @supports (color: color(display-p3 1 1 1)) {
        :root {
            --bright-green: color(display-p3 0 1 0);

    Another idea is to support the lch() and lab() functions.

    Here's a site where you can compare between the two - you need to use Safar on a Mac or iPhone to see differences.

  • 5

    [RFC] A sugary `defineConfig()` function annotation for pollen's config file

    Per this issue comment ( and this one (, I'm glad that there will be a pollen.config.js to extend pollen. I'm just wondering that it might be a good idea to add a little sugar to the config file without forcing the non-typescript users (at this point of writing, I don't know whether pollen's config file supports the .ts extension or not) to use JSdoc annotation for /** @type import("pollen.Config") */.

    I'm suggesting something like Vite's (link) and WindiCSS' (link) config file.

    So, it would be something like:

    /** pollen.config.js */
    import pollen, { defineConfig } from "pollen";
    export default defineConfig({
      output: 'styles/pollen.css',
      modules: {
        font: { sans: `"Inter", sans-serif` },
        letter: { ...pollen.letter, sm: '-0.02em' },
        radius: { ...pollen.radius, xs: '4px ' },
        grid: { ...pollen.grid, pageGutter: 'var(--grid-gap)' },
        color: {
          grey100: '#f2f4f7',

    Or, if import pollen from "pollen" sounds like a no for you, because you might need to export some other things on the pollen.js file, we could make the exported configs on a separate file (this wouldn't cause any breaking change tho).

    import { defineConfig } from "pollen/helpers";
    import { letter } from "pollen/typography";
    import { radius } from "pollen/ui";
    import { grid } from "pollen/grid";
    export default defineConfig({
      output: 'styles/pollen.css',
      modules: {
        font: { sans: `"Inter", sans-serif` },
        letter: { ...letter, sm: '-0.02em' },
        radius: { ...radius, xs: '4px ' },
        grid: { ...grid, pageGutter: 'var(--grid-gap)' },
        color: {
          grey100: '#f2f4f7',

    or if you want to make it a bit neat and put everything on the entry point which you'll only need to do export * from "./typography"...

    import { defineConfig, defaults } from "pollen";
    export default defineConfig({
      output: 'styles/pollen.css',
      modules: {
        font: { sans: `"Inter", sans-serif` },
        letter: { ...defaults.letter, sm: '-0.02em' },
        radius: { ...defaults.radius, xs: '4px ' },
        grid: { ...defaults.grid, pageGutter: 'var(--grid-gap)' },
        color: {
          grey100: '#f2f4f7',

    If there's another feedback, I'd love to hear it. I might get to work on the PR as soon as I can :)

  • 6

    [RFC] Make unit scales consistent

    Carrying on from #32, with a probable v3 breaking change coming it could be a good opportunity to rethink some fundamentals that Pollen blindly inherited from Tailwind. Namely, inconsistent unit scales.

    We currently use:

    • Numerical (eg: --size-2)
    • Sizes (eg: width-xs)
    • Descriptive (eg: tracking-tight).

    If Pollen was to standardise on a scale I feel like it should be numeric, since that's the most obvious, extensible, and easiest to understand.

    Great discussion on Tailwind that was abandoned due to breaking change friction on a large project:

  • 7

    Feature: Add ability to export json file of tokens

    Currently the official docs site is the only place you could see a list of all available tokens and their values and if you customize any of them, this would no longer stay in sync with the officially supported tokens.

    By adding the ability to export a JSON (or yaml?) file with all customizations applied, you would be able to use this JSON output to generate your own dictionary reference/docs site so that your entire team can now stay in sync. It would also make it easier to build out utility classes out of the tokens as you could convert JSON to SCSS easily with existing packages.

    Perhaps something like this in the config file?

    module.exports = {
      outputjson: 'some/path/pollen.json',
      modules: {
        // Module config

    Example output could be something like:

      "size": {
        "0": "2px",
        "1": "4px",
        "2": "8px",
        "3": "12px"
      "blur": {
        "sm": "blur(4px)",
        "md": "blur(8px)",
        "lg": "blur(16px)",
        "xl": "blur(24px)",
        "2xl": "blur(40px)"
  • 8

    Add typeset defaults?

    Opinionated pairings of line heights with the modular font scale for sans and serif font families.

    • Applies to: font
    • Property group: sans- and serif-

    Values eg:

    :root {
    	--sans-0: var(--scale-0)/1.5, var(--font-sans);


    .paragraph {
      font: var(--sans-0);
  • 9

    Remove width scale?

    The width scale was lifted straight from Tailwind as an extension of the size scale. However now that Pollen has an extended prose width scale, based on character size, is there really a need for a dedicated scale for max-widths? It's needed in tailwind since they are classes, but as raw values it seems like an antipattern compared to encouraging people to use typgraphic-based widths.

    Open for comment on this one since I'm not sure.

  • 10

    [RFC] Rename `leading` and `tracking`?

    Pollen inherited Tailwind's naming conventions for leading (line-height) and tracking (letter-spacing). These are the correct typographic names for these measurements, but developers are much more familiar with line-height and letter-spacing than leading and tracking.

    With a probable v3 breaking change coming for #31, it might be a good opportunity to rename these and correct a possible misstep by Tailwind. But the full property names are too verbose, leading- and tracking- are at least nice and concise.

    So I'm thinking:

    • line- for line-height, eg: line-sm
    • letter- for letter-spacing, eg: letter-tight

    Not sure how much more memorable they are than leading- and tracking- though, since we already have measure- (which has no concise replacement I can think of) anyway

  • 11

    Add screenshots

    Thanks for publishing this nice-looking library.

    This issue is to suggest a new docs feature for the gitdocs page and for the README. Putting some screenshots on the docs pages and in the README would help new users get to know the library, get a sense for what it can do visually.

  • 12

    Bump minimist from 1.2.5 to 1.2.7

    Bumps minimist from 1.2.5 to 1.2.7.


    Sourced from minimist's changelog.

    v1.2.7 - 2022-10-10


    • [meta] add auto-changelog 0ebf4eb
    • [actions] add reusable workflows e115b63
    • [eslint] add eslint; rules to enable later are warnings f58745b
    • [Dev Deps] switch from covert to nyc ab03356
    • [readme] rename and add badges 236f4a0
    • [meta] create FUNDING.yml; add funding in package.json 783a49b
    • [meta] use npmignore to autogenerate an npmignore file f81ece6
    • Only apps should have lockfiles 56cad44
    • [Dev Deps] update covert, tape; remove unnecessary tap 49c5f9f
    • [Tests] add aud in posttest 228ae93
    • [meta] add safe-publish-latest 01fc23f
    • [meta] update repo URLs 6b164c7

    v1.2.6 - 2022-03-21


    • test from prototype pollution PR bc8ecee
    • isConstructorOrProto adapted from PR c2b9819
    • security notice for additional prototype pollution issue ef88b93
    • c590d75 v1.2.7
    • 0ebf4eb [meta] add auto-changelog
    • e115b63 [actions] add reusable workflows
    • 01fc23f [meta] add safe-publish-latest
    • f58745b [eslint] add eslint; rules to enable later are warnings
    • 228ae93 [Tests] add aud in posttest
    • 236f4a0 [readme] rename and add badges
    • ab03356 [Dev Deps] switch from covert to nyc
    • 49c5f9f [Dev Deps] update covert, tape; remove unnecessary tap
    • 783a49b [meta] create FUNDING.yml; add funding in package.json
    • Additional commits viewable in compare view
    Maintainer changes

    This version was pushed to npm by ljharb, a new releaser for minimist since your current version.

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.

    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

  • 13

    postcss and postcss-jit-props integration

    I was wondering if there were ever any thoughts of integrating this with postcss and postcss-jit-props to remove unused variable definitions from the final project.

    This would make the experience as simple as tailwindcss with the benefit of using plain CSS only.

  • 14

    system-ui in --font-sans font stack

    Hey folks, I'm just seeing that we have system-ui in the sans font variable

    and I was wondering if we should remove it as a default, since it's problematic for some users


    At the moment I work around it by overwriting the default in my project via

    :root { --font-sans: .. }

    Also wondering how we came up with the font stack, and if we can rely on something like

  • 15

    Colors: colorful (warm/cold) greys

    Hey folks, I'm playing around with pollen and really like it so far :heart:

    I'm using greys as a base for my pages and want to give them a slight touch of color - most often a cold (blue'ish) or a warm (yellow'ish) touch, to make the overall page design feel either colder or warmer.

    What I'm doing so far is taking the pollen greys to a color picker and then adding a touch of blue/yellow eye-balling the results.

    Do you think this is a use case pollen should support in its color palette?

    I have been looking at the competition :eyes: :see_no_evil: how they do it, and it seems like they have Slate and Stone for cold/warm greys, respectively.

  • 16


    This project looks (concept-wise) really cool! I think it'd be an easy sell if there were something demoable to look at, to see what's possible with all the design tokens out of the box. I personally dislike Tailwind in terms of the utility classes mindset, but there's no denying it became popular quickly because it just presents extremely well and seems easy to pick up and run with.