Install:
npm install css-bin-bits
Import:
import "node_modules/css-bin-bits/bin-bits.css"
OR<link rel="stylesheet" type="text/css" href="https://unpkg.com/css-bin-bits@0.0.3/bin-bits.css">
css-bin-bits is a CSS file that establishes an API for binary operations of --number-vars clamped to the +/- 16bit range [-65535, 65535]
No JS is involved, but it requires CSS @property support from the Houdini spec.
npm install css-bin-bits
import "node_modules/css-bin-bits/bin-bits.css"
OR<link rel="stylesheet" type="text/css" href="https://unpkg.com/css-bin-bits@0.0.3/bin-bits.css">
To attach the css-bin-bits API to an element, add the data attribute: data-bin-bits="a"
Now you can pass a number into one of the entry points for rounding or truncation.
The number can be an expression, calc(), or var() that results in a number.
Units (such as px, %, or deg) must not be part of the input.
<div data-bin-bits="a" style="--bin-a-round: -1.5;"></div>
<div data-bin-bits="a" style="--bin-a-round: 1 + 0.499;"></div>
<div data-bin-bits="a" style="--bin-a-round: (40 * 1000 + 1) * -2;"></div>
The input --bin-a-round
is clamped first to +/- 16bits [-65535, 65535],
then the rounding algorithm (+/- 0.5 away-from-zero) is applied.
Therefore the above numbers, respectively, produce: -2, 1, -65535
<div data-bin-bits="a" style="--bin-a-trunc: -1.5;"></div>
<div data-bin-bits="a" style="--bin-a-trunc: 1 + 0.499;"></div>
<div data-bin-bits="a" style="--bin-a-trunc: 67001;"></div>
The input --bin-a-trunc
is clamped first to +/- 16bits [-65535, 65535], then truncated towards 0.
Therefore the above numbers, respectively, produce: -1, 1, 65535
If both *-round and *-trunc are provided, the value from *-round is used and *-trunc is ignored.
<div data-bin-bits="a" style="--bin-a-trunc: 5; --bin-a-1: 0;"></div>
<div data-bin-bits="a" style="--bin-a-trunc: 5; --bin-a-2: 1;"></div>
<div data-bin-bits="a" style="--bin-a-trunc: 5; --bin-a-3: 0; --bin-a-4: 1;"></div>
Given the inputs above, respectively, you get:
5 (0000000000000101) with bit 1 set to 0 (0000000000000100) results in 4
5 (0000000000000101) with bit 2 set to 1 (0000000000000111) results in 7
5 (0000000000000101) with bit 3 set to 0 and bit 4 set to 1 (0000000000001001) results in 9
Each of the 16 bits from 1 to 16 can be overwritten as expected:
--bin-a-1: 0; sets the first (least significant) bit to 0
--bin-a-9: 1; sets the ninth bit to 1
--bin-a-16: 1; sets the sixteenth (most significant) bit to 1
<div data-bin-bits="a b c"
style="
--bin-a-round: -1.5;
--bin-b-trunc: 99.9;
--bin-c-round: 0;
--bin-c-3: 1;
"
></div>
You can use up to 6 input sets on a single element.
The sets are named a
, b
, c
, d
, e
, and f
.
The css-bin-bits API becomes available for an element, for each input, by
placing the set's name in the space-delimited data-bin-bits
attribute value, like in the example above.
You can provide input values from your CSS files as long as the data-bin-bits
attribute is set accordingly.
(the input values do not need to be set from the inline style="" attribute).
The inputs --bin-a-sign
, --bin-a-1
, --bin-a-16
, --bin-f-8
, etc are all outputs as well.
The sign output will contain either 1 or -1.
Each of the bits contains the expected 0 or 1: either its override, or the original expected bit from the absolute value* of the 16bit input number.
All other output from an input set is an integer result of a calculation from those bits.
* I am looking for strong opinions on this! (especially ones backed with a use case in CSS)
Cards on the table, I don't know if binary math on integers is useful in CSS because I've never considered it as a possibility when creating something.
As a result, I do no not know the use cases beyond generically helping with patterns; So negative numbers are currently handled minimally.
(In this early first release, negative numbers are treated as their absolute value, then the sign value is only considered on signed outputs.)
Should the bits from a negative number input at least be inverted? (ehh..)
Should they use two's complement? (technically, probably yes, but subjectively in this context...?)
Would either of those directions help MORE in the world of CSS art and design?
Please contact me (Jane) on Twitter with any feedback!
<div data-bin-bits="a" style="--bin-a-round: -1.5;"></div>
<div data-bin-bits="a" style="--bin-a-round: 999; --bin-a-1: 0;"></div>
<div data-bin-bits="a" style="--bin-a-round: 64537; --bin-a-3: 1;"></div>
Given the inputs above, --bin-a-VAL
will contain 2, 998, and 64541 respectively.
This is the absolute value of the bits.
Given the same inputs, --bin-a-NOT
will contain 65533, 64537, and 995 respectively.
This is the NOT of absolute value of the bits.
Given the inputs above, --bin-a-SIGNED
will contain -2, 998, and 64541 respectively.
This is the absolute value of the bits with the original sign.
Given the same inputs, --bin-a-SIGNED-NOT
will contain 65533, -64537, and -995 respectively.
This is the NOT of absolute value of the bits with the opposite of the original sign.
<div data-bin-bits="a" style="--bin-a-trunc: -1.5;"></div>
<div data-bin-bits="a" style="--bin-a-trunc: 1 + 0.499;"></div>
<div data-bin-bits="a" style="--bin-a-trunc: 67001;"></div>
--bin-a-POS
will contain a 1 if sign is 1, and will contain a 0 if sign is -1.--bin-a-NEG
will contain a 0 if sign is 1, and will contain a 1 if sign is -1.--bin-a-EVEN
will contain a 1 if the first bit is 0, else it will contain a 0.--bin-a-ODD
is an alias of the first bit. (Will be 1 for odd numbers, else 0.)
<div data-bin-bits="a" style="--bin-a-trunc: 9374; --bin-a-mod: 5;"></div>
<div data-bin-bits="a" style="--bin-a-trunc: 3; --bin-a-mod: 3;"></div>
<div data-bin-bits="a" style="--bin-a-trunc: 6; --bin-a-1: 1; --bin-a-mod: 10;"></div>
Given the inputs and --bin-a-mod
value above, respectively, --bin-a-MOD
will be: 4, 0, 7
The input (lowercase variable --bin-a-mod
) must be a positive integer greater than 0.
<div data-bin-bits="a" style="--bin-a-trunc: -23; --bin-a-shift: 1;"></div>
--bin-a-shift
must be an integer in range [0, 15]
Given the input and shift value above, you get 3 different outputs:--bin-a-LEFT
will be: 46 (absolute value of the input, shifted left 1)--bin-a-RIGHT
will be: 11 (absolute value of the input, shifted right 1 and truncated to int)--bin-a-SIGNED-RIGHT
will be: -32779
SIGNED-RIGHT is the absolute value of the input, shifted right 1 (and left-filled with 1s because the input is negative)
If passed into another input set:<div data-bin-bits="a b" style="--bin-a-trunc: -23; --bin-a-shift: 1; --bin-b-trunc: var(--bin-a-SIGNED-RIGHT);"></div>
the bits from #16 to #1 will be 1000000000001011.
⚠️ Before a version 1.0.0 release, the bit form of negative numbers will likely change and the span of 0's here are likely to be 1s from a Two's Complement representation.
(see note above)
The 6 input sets can be logically combined to produce their own set by adding its name to the data attribute:
data-bin-bits="a b ab"
The available sets are named:ab
, ac
, ad
, ae
, af
,bc
, bd
, be
, bf
,cd
, ce
, cf
,de
, df
,ef
Any or all of them can be added to a single element.
Just like the original input sets, the resulting bits can be read and/or overwritten:--bin-ab-1
... --bin-ab-16
By default, the 16 bits from each of the left and right sets will be combined with XOR.
To change the opperation, assign one of the following operators:var(--bin-NOT)
var(--bin-AND)
var(--bin-NAND)
var(--bin-OR)
var(--bin-NOR)
var(--bin-XOR)
To the set's op prop:--bin-ab-op: var(--bin-NAND);
The ab bit set would now represent a NAND b
(note the operators are global and do not specify a set in their name, unlike all other css-bin-bits variables)
The output API documented previously also works on combined sets.
Therefore, --bin-ab-NOT
, --bin-ab-EVEN
,
--bin-ab-shift & --bin-ab-RIGHT/LEFT/SIGNED-RIGHT
,
--bin-ab-mod & --bin-ab-MOD
, etc, all behave the same way, producing an integer calculated from the bits in this set.
Just like the single input set's outputs, you can pass any into another single-letter set to perform further operations
<div data-bin-bits="a b ab c d bc cd e f ef"
style="
--bin-a-trunc: 5;
--bin-b-trunc: 3;
--bin-c-trunc: var(--bin-a-trunc);
--bin-bc-op: var(--bin-OR);
--bin-d-trunc: var(--bin-b-trunc);
--bin-cd-op: var(--bin-AND);
--bin-e-trunc: var(--bin-bc-VAL);
--bin-f-trunc: var(--bin-cd-NOT);
--bin-ef-op: var(--bin-AND);
"
></div>
Given the input above, --bin-ab-VAL
will be 6 from a XOR b,
and, --bin-ef-VAL
will be 6 from c = a, d = b, then, effectively:
(a OR b) AND (NOT (a AND b))
Which is the same as an XOR.
Live demo: