npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@propjockey/doubledash.css

v0.2.2

Published

a collection of 100% CSS custom utility --functions()

Readme

Jane Ori - PropJockey.io

doubledash.css from PropJockey

NPM: https://www.npmjs.com/package/@propjockey/doubledash.css

GitHub: https://github.com/propjockey/doubledash.css

Install: $ npm install @propjockey/doubledash.css Then import the /node_modules/@propjockey/doubledash.css/doubledash.css file into your project.

OR

Use your favorite NPM CDN and include it on your page for small projects. Like so:

<link rel="stylesheet" type="text/css" href="https://unpkg.com/@propjockey/[email protected]/doubledash.css">

OR

Use your favorite NPM CDN and import specific functions straight into your CSS for small projects. Like so:

@import url("https://unpkg.com/@propjockey/[email protected]/functions/repeat/index.css");

Functions

Compare

  • /functions/compare/*
    • cmp.css --dd-cmp(--left, --right)
    • eq.css --dd-eq(--left, --right)
    • neq.css --dd-neq(--left, --right)
    • gt.css --dd-gt(--left, --right)
    • gte.css --dd-gte(--left, --right)
    • lt.css --dd-lt(--left, --right)
    • lte.css --dd-lte(--left, --right)

These all take --left and --right which must be the same type: <length>|<number>

cmp returns an integer, -1, 0, or 1 for less than, equal to, and greater than, respectively

the rest return a boolean bit flag 0 or 1 "is left gte right?"

opacity: --dd-gte(50cqw, 20rem);

--dd-repeat(--n, --x)

./functions/repeat/repeat.css

--n is an integer greater than 0, less than 256

--x is anything

Outputs --x repeated --n times.

--star-family: --dd-repeat(3, 👽);
/* 👽 👽 👽 */

--dd-repeat-join(--n, --join, --x)

./functions/repeat/repeat-join.css

--n is an integer greater than 0, less than 256

--join is a separator

--x is anything

Outputs --x repeated --n times, each separated by --join

text-shadow: --dd-repeat-join(4, {, }, 0px 0px 2px black);
/* 0px 0px 2px black, 0px 0px 2px black, 0px 0px 2px black, 0px 0px 2px black */

Iterative Looping (like for loops in JS)

./functions/repeat/loop.css

The maximum iteration count is 1024.

You can register up to 64 individual loops for use in any property contexts. (functions are global so make sure not to overwrite any of your definitions)

They must be named --dd-loop-id-0, --dd-loop-id-1, etc up to index 63.

You can alias them globally for easier use later:

:root {
  --my-first-css-loop:       --dd-loop-id-0;
  --my-other-loop-alias:     --dd-loop-id-1;
  --propjockey-ftw:          --dd-loop-id-2;
  --give-jane-ori-abundance: --dd-loop-id-3;
}

Define their output functions like so:

@function --dd-loop-id-0() {
  result: "--dd-i: " --dd-number-to-string(var(--dd-i))
    "\A --dd-x: " --dd-number-to-string(var(--dd-x), 2)
    "\A --dd-x-start: " --dd-number-to-string(var(--dd-x-start), 2)
    "\A --dd-x-end: " --dd-number-to-string(var(--dd-x-end), 2)
    "\A --dd-arg1: " --dd-to-string(var(--dd-arg1))
    "\A --dd-arg2: " --dd-to-string(var(--dd-arg2))
    "\A --dd-arg3: " --dd-to-string(var(--dd-arg3))
    "\A --dd-arg4: " --dd-to-string(var(--dd-arg4))
    "\A\A"
  ;
}

@function --dd-loop-id-3() {
  result: calc(var(--dd-i) + var(--dd-x)) calc(-1 * var(--dd-i) - var(--dd-x));
}

Your loop function body has access to the variables shown in the example.

--dd-i is the current integer iteration index, starting from 0. The maximum value is 1023 (1024 iterations)

--dd-x-start is the initial loop controller value, typically set to 0 or 1

--dd-x is the current iteration's cumulative loop controller value (if you did x = x + 2 in a for loop starting from 0, it would be i:x 0:0, 1:2, 2:4, 3:6...)

--dd-x-end is the ending sentinel value for your loop controller that a condition is checked against, typically the condition is "lt" meaning continue if --dd-x is less than this end value.

Executing your loop

To run your loop in various contexts, call --dd-loop() in a property value.

The loop is short-circuited and does not compute anything beyond where it ends.

body::after {
  white-space: pre;
  content: --dd-loop(0, lt, 10, + 1, var(--my-first-css-loop));
  /* the same as this if you don't want to use a var() alias */
  content: --dd-loop(0, lt, 10, + 1, --dd-loop-id-0);
}

The required parameters in order are:

  1. --dd-x-start a number value to begin with

    • you can cast lengths and other dimensions to a number using the cast functions if needed
  2. --dd-condition

    • One of the following identifiers:
      • eq | gt | gte | lt | lte | neq
    • Before an iteration executes, it calculates the next would-be --dd-x and compares it to the --dd-x-end value, which is the next parameter.
  3. --dd-x-end a number value to compare --dd-x to in order to determine if the loop should continue.

  4. --dd-calc-partial This is the formula applied to your initial x, then to the current x each iteration. You can provide + 1 to increase --dd-x by one each time. You can also multiply or divide initially then add or subtract from that result by providing a calc partial such as * 2 - 1. Other loop controller variations are not supported yet.

  5. --dd-use-loop - an identifier you provide that connects to the loop body function you intend to execute in this context. This is the value checked against in the --dd-global-loops function you overwrote to register your loops.

This is how you read these required parameters:

--dd-loop(0, lt, 10, + 1, var(--my-first-css-loop)); loop while 0 is less than 10 and add one each time after executing the loop body aliased by var(--my-first-css-loop).

Not dissimilar to the for (let x = 0; x < 10, x = x + 1) {...} loop in js.

The remaining parameters are optional. In order, they are:

  1. --dd-joiner - a value to output in between iterations.

    • It does not output before the first iteration nor after the last.
    • set it to the identifier none to not produce anything between iterations.
    • set it to a comma with the do-not-spread { , } syntax if you want your output to be joined by commas:
      • --dd-loop(0, + 1, lt, 10, var(--my-first-css-loop), { , });
  2. --dd-arg1 - any value you wish to pass into this context

    • It can be a color if you want to use this loop in multiple places with different colors.
    • It can be a number if you want to modify your loop in each context you use it in.
    • etc
  3. The remaining optional parameters are

    • --dd-arg2, through --dd-arg16
    • The same as --dd-arg1, can be anything or nothing.

[!NOTE] We can't pass them as actual args because the spec is overly strict with no reason provided about calling a function with more parameters than defined (but not with fewer), which means YOU would have to define all of them every time you define a loop function in order for me to pass them at all, or else it would just silently not work. 🙄 (there are a TON of extremely unfortunate and irritating authoring problems with the current CSS function spec, I hide what I can for you.)

Cast number to string

./functions/cast/number-to-string.css

--dd-number-to-string(--dd-number, --dd-fixed: 0, --dd-round: nearest)

--dd-number is the number to cast to string

--dd-fixed is an integer for the decimal precision to show in the string, defaulting to 0, maximum 6 decimal places though native CSS precision only allows up to 6 if the number is between 1 and 0, and with 6 digits left of the decimal, it doesn't have room for any decimal precision. The outuput remains fixed length in any case, using 0 as needed.

--dd-round is the rounding strategy used to reach the precision specified, defaulting to nearest.

Demo: https://codepen.io/propjockey/pen/JobdXLz?editors=0100

Cast length and other dimensions to string

./functions/cast/dimension-to-string.css

--dd-dimension-to-string(--dd-dimension, --dd-basis: 1px, --dd-unit <string>: "", --dd-fixed <integer>: 0, --dd-round: nearest)

basis (optional for length dimensions) is the single unit value of the length or other dimension provided (96dpi, 10deg, 100ms), defaulting to 1px which will show a length as pixels

unit (optional) is the string to append after the number, eg "px", defaulting to an empty string.

fixed (optional) is the decimal precision, same as in cast/number-to-string.css

round (optional) defaulting to nearest, same as in cast/number-to-string.css

Demo: https://codepen.io/propjockey/pen/dPOoMmx?editors=0100

--dd-bit-to-st(--dd-bit)

takes a bit, 0 or 1, and returns a space toggle (space if 1, initial if 0)

--dd-bit-to-ist(--dd-bit)

takes a bit, 0 or 1, and returns an inverted space toggle (initial if 1, space if 0)

--dd-st-to-bit(--dd-st)

takes a space toggle and returns a bit (1 if space, 0 if initial)

--dd-ist-to-bit(--dd-ist)

takes an inverted space toggle and returns a bit (1 if initial, 0 if space)

TODO: Document the rest shown in the changelog

So many ✨

And as soon as we have ...vargument spreading (which absolutely should have happened by default and unfortunately doesn't), maybe up to another 100 functins will be added for array processing.

Miiiight add mixins once those are here too.

CHANGELOG:

v0.2.2 - May 7th, 2026:

  • Added more optional argument parameters to --dd-loop() after looking more closely at Ana Tudor's beautiful CSS work and seeing how often she needs more than I originally shipped.
  • --dd-arg4 was the previous maximum, --dd-arg16 is now the max.

v0.2.1 - May 7th, 2026:

  • Improved loop implementation so it can do 1024 iterations max instead of 128.

v0.2.0 - May 6th, 2026:

  • /functions/repeat/*
    • loop.css --dd-loop(from, condition, to, calc stepper partial, loop-id)
  • /functions/other/*
    • is-int.css --dd-is-int(--dd-any) // returns 1 if it's an integer, otherwise 0
    • type-of.css --dd-type-of(--dd-any) // returns a string, for example:
      • "<length>"
      • "<string>"
      • "<integer>"
      • "<number>"
      • "<length-percentage>"
      • "<length-percentage>+" // space separated list
      • "<length-percentage>#" // comma separated list
      • "<custom-ident>+"
      • "<color>"
      • "<empty>" // a valid/truthy empty value, the space of a space toggle
      • "<initial>" // not "technically correct" but ultimately more useful
      • "*" // if not identified
      • etc etc etc
  • /functions/cast/*
    • removed length-to-px-number.css
    • removed length-to-string.css
    • added dimension-to-number.css --dd-dimension-to-number(--dd-dimension, --dd-basis)
      • basis is a unit value defaulting to 1px so the result would be a number in terms of px
      • change basis to 1rem for the number result to be in terms of rem, for example
    • added dimension-to-string.css --dd-dimension-to-string(--dd-dimension, --dd-basis: 1px, --dd-unit: "", --dd-fixed: 0, --dd-round: nearest)
      • basis is a unit value defaulting to 1px so the result would be a number in terms of px
      • if dimension is length, change basis to 1rem for the number result to be in terms of rem, for example
      • if dimension is time, change basis to 1s for the number result to be in terms of seconds
    • to-string.css --dd-to-string(--dd-any)
      • returns the string value of anything that can be converted into a string
      • returns the string "type-of" result if the value can't directly be stringified

v0.1.2 - May 5th, 2026:

  • Fix filename for int16-to-hex-string.css

v0.1.1 - May 5th, 2026:

  • Fixed rounding on number-to-string thanks to Jakob E
    • https://bsky.app/profile/jakob-e.bsky.social/post/3mkzgiem3322y
    • the same rounding omission affected bitwise operations so it has been fixed in two additional places as well (thank you times 3!)
  • Clean up: Corrected poor naming of several internal variables
  • Fixed all /functions/logic/int16/* functions
  • /functions/logic/int16/*
    • shift-left-int16.css --dd-shift-left-int16(--int16, --distance)
    • shift-right-int16.css --dd-shift-right-int16(--int16, --distance)
    • msb-int16.css --dd-msb-int16(--dd-int16) // most significant bit returns [0, 15]
    • byte-int16.css --dd-byte-int16(--dd-int16, --which-byte[0, 1])
    • nibble-int16.css --dd-nibble-int16(--dd-int16, --which-nibble[0, 3])
  • Added an optional base param to --dd-digit-to-string(--dd-digit, --dd-base)
    • extended the default set as base32hex number base
    • base32hex, base32, base64 are the current options
  • /functions/cast/*
    • int16-to-bit-string.css --dd-int16-to-bit-string(--dd-int16, --dd-min-length: 0)
      • maximum min length is 16
      • pads left with 0 to reach the minimum length
    • int16-to-hex-string.css --dd-int16-to-bit-string(--dd-int16, --dd-min-length: 0)
      • maximum min length is 4
      • pads left with 0 to reach the minimum length
    • dcb-to-int16.css --dd-dcb-to-int16(--dd-arg1, --dd-arg2, --dd-arg3, --dd-arg4)
      • dcb = decimal coded binary.
      • allows you to write binary in CSS
      • decimal number 11 is interpreted as binary so it equals 3
      • the most significant bit is the first bit of the first argument
      • the least significant bit is the last bit of the last argument you provide
      • only --dd-arg1 is required, each arg is 4 bits (a nibble)
      • --dd-dcb-to-int16(11,1001,1101) = 925
      • --dd-dcb-to-int16(0011,1001,1101) = 925
      • --dd-dcb-to-int16(1111,1111,1111,1110) = 65534
    • int16-to-dcb-nibble.css --dd-int16-to-dcb-nibble(--dd-int16, --which-nibble[0, 3])

v0.1.0 - May 3rd, 2026:

  • Added --dd- prefix
  • Organized into folders
    • /repeat/repeat.css
    • /repeat/repeat-join.css
  • Added index.css files in each folder that includes all functions from that folder
    • /repeat/index.css
  • /functions/compare/*
    • cmp.css --dd-cmp(--left, --right)
    • eq.css --dd-eq(--left, --right)
    • neq.css --dd-neq(--left, --right)
    • gt.css --dd-gt(--left, --right)
    • gte.css --dd-gte(--left, --right)
    • lt.css --dd-lt(--left, --right)
    • lte.css --dd-lte(--left, --right)
  • /functions/cast/*
    • bit-to-space-toggle.css --dd-bit-to-st(--dd-bit)
    • space-toggle-to-bit.css --dd-st-to-bit(--dd-st)
    • bit-to-inverted-space-toggle.css --dd-bit-to-ist(--dd-bit)
    • inverted-space-toggle-to-bit.css --dd-ist-to-bit(--dd-ist)
    • digit-to-string.css --dd-digit-to-string(--digit)
    • number-to-string.css --dd-number-to-string(--dd-number, --dd-fixed: 0, --dd-round: nearest)
  • /functions/logic/*
    • bit/*
      • and-bit.css --dd-and-bit(--bit-a, --bit-b)
      • nand-bit.css --dd-nand-bit(--bit-a, --bit-b)
      • nor-bit.css --dd-nor-bit(--bit-a, --bit-b)
      • not-bit.css --dd-not-bit(--bit)
      • or-bit.css --dd-or-bit(--bit-a, --bit-b)
      • xnor-bit.css --dd-xnor-bit(--bit-a, --bit-b)
      • xor-bit.css --dd-xor-bit(--bit-a, --bit-b)
    • int16/*
      • and-int16.css --dd-and-int16(--int16-a, --int16-b)
      • nand-int16.css --dd-nand-int16(--int16-a, --int16-b)
      • nor-int16.css --dd-nor-int16(--int16-a, --int16-b)
      • not-int16.css --dd-not-int16(--int16)
      • or-int16.css --dd-or-int16(--int16-a, --int16-b)
      • xnor-int16.css --dd-xnor-int16(--int16-a, --int16-b)
      • xor-int16.css --dd-xor-int16(--int16-a, --int16-b)
      • toggle-int16.css --dd-toggle-int16(--int16, --which-bit)
      • set-int16.css --dd-set-int16(--int16, --which-bit, --to-bit-value)
      • get-int16.css --dd-get-int16(--int16, --which-bit)
      • bitwise.css --dd-bitwise(--int16-a, --operator, --int16-b-or-which-bit, --set-to: 0)
    • space-toggle/*
      • and-st.css --dd-and-st(--st-a, --st-b)
      • nand-st.css --dd-nand-st(--st-a, --st-b)
      • nor-st.css --dd-nor-st(--st-a, --st-b)
      • not-st.css --dd-not-st(--st)
      • or-st.css --dd-or-st(--st-a, --st-b)
      • xnor-st.css --dd-xnor-st(--st-a, --st-b)
      • xor-st.css --dd-xor-st(--st-a, --st-b)
    • inverted-space-toggle/*
      • and-ist.css --dd-and-ist(--ist-a, --ist-b)
      • nand-ist.css --dd-nand-ist(--ist-a, --ist-b)
      • nor-ist.css --dd-nor-ist(--ist-a, --ist-b)
      • not-ist.css --dd-not-ist(--ist)
      • or-ist.css --dd-or-ist(--ist-a, --ist-b)
      • xnor-ist.css --dd-xnor-ist(--ist-a, --ist-b)
      • xor-ist.css --dd-xor-ist(--ist-a, --ist-b)

v0.0.2 - May 3rd, 2026:

  • --repeat-join(--n, --join, --x);

v0.0.0 - May 3rd, 2026:

  • Initial release
  • --repeat(--n, --x);

Open Contact 👽

Please do reach out if you need help with any of this, have feature requests, or want to share what you've created!

| PropJockey | CodePen | DEV Blog | GitHub | | :---: | :---: | :---: | :---: | | PropJockey.io | CodePen | DEV Blog | GitHub |

| Mastodon | LinkedIn | X | Bluesky | | :---: | :---: | :---: | :---: | | Mastodon | LinkedIn | X | Bluesky |

My heart is open to receive abundance in all forms,flowing to me in many expected and unexpected ways.

| PayPal | Ko-fi | Venmo | | :---: | :---: | :---: | | PayPal | Ko-fi | Venmo |

| BTC | XRP | ETH | | :---: | :---: | :---: | | BTC bc1qe2ss8hvmskcxpmk046msrjpmy9qults2yusgn9 | XRP rw2ciyaNshpHe7bCHo4bRWq6pqqynnWKQg : 459777128 | ETH 0x674D4191dEBf9793e743D21a4B8c4cf1cC3beF54 | | bc1qe...usgn9 | rw2ci...nWKQg: 459777128 | 0x674...beF54 |