Skip to content
experimental

Simple Tailwind utilities for cutting-edge CSS.

Five color functions that reach where a class cannot, corner shapes past the circular arc, animation to auto, a select you can actually style, and a live WCAG rating printed on any element.

npm install -D tw-jib-css tw-jib-css-experimental
text + text-decorationcolor: base
underline: +35
bg: base
ring: −30
fill: base stroke: −35
linear-gradient stops
base → sat(−60)
override

Shadows, gradients, and more: one color, transformed.

Utilities own the single-property case: bg, text, border. A gradient stop, a layered shadow, an SVG stroke, a text-decoration color. A class cannot reach in there. These functions can, anywhere a <color> fits, on any token, with no relationship to the element's own background.

css
.card {
  /* a stop inside a gradient */
  background: linear-gradient(135deg,
    var(--color-sky-400),
    --jib-saturation(var(--color-sky-400), -60));

  /* two derived shadows */
  box-shadow:
    0 0 0 3px --jib-lightness(var(--color-sky-400), -30),
    0 16px 32px -4px --jib-lightness(var(--color-sky-400), -40);
}
button border + text
the shade, as a gradient stop
teal-500shade(aaa)
solved, not searched
solved for 7:1
override

Rings, borders, icons, and more: all auto-contrast.

text-contrast-* paints one thing: text color, on this element, from this element's own background. The function goes anywhere. A border, an SVG stroke, a gradient stop, generated content, each solved for the ratio you named, from whatever color you hand it.

css
.cta {
  /* both from one background token, solved for 7:1 */
  color:        --jib-auto-contrast(
                  var(--color-teal-500), aaa, oklch);
  border-color: --jib-auto-contrast(
                  var(--color-teal-500), aaa, oklch);
}
round
squircle
bevel
scoop
notch
square
ellipse-4
mixed
addition

Squircles, bevels, scoops and notches.

border-radius only ever drew a circular arc. corner-shape draws that same radius as a squircle, a bevel, a scoop, a notch, or any superellipse exponent you name. rounded-* still sets the size. You pick the curve.

html
<div class="rounded-2xl corner-round">
<div class="rounded-2xl corner-squircle">
<div class="rounded-2xl corner-bevel">
<div class="rounded-2xl corner-scoop">
<div class="rounded-2xl corner-notch">
<div class="rounded-2xl corner-square">

<!-- per corner, and any superellipse exponent -->
<div class="rounded-2xl corner-t-squircle corner-b-bevel">
<div class="rounded-2xl corner-4">

withparent has interpolate-keywords

withoutsame animation, no utility

Disclosure panel
Disclosure panel
addition

Animate height to auto.

0 to auto has always snapped, because CSS cannot transition to an intrinsic keyword. interpolate-size: allow-keywords lifts that, on the parent, for every child. Accordions and disclosure panels stop needing a measured height in JavaScript.

html
<!-- the utility goes on an ANCESTOR -->
<div class="interpolate-keywords">

  <!-- transition to auto -->
  <div class="group">
    <button>Expand</button>
    <div class="h-0 group-hover:h-auto
      transition-all duration-300 overflow-hidden">…</div>
  </div>

  <!-- or animate to it, as the panels here do -->
  <div class="h-0 overflow-hidden
    animate-[disclosure_6s_ease-in-out_infinite]">…</div>
</div>

a real select, open it

addition

A select you can finally style.

appearance: base-select opts a native <select> into rendering you can reach. The popup, the arrow and the checkmark each get a variant, so the dropdown takes the same classes as everything else. Still a real select, with real keyboard and accessibility behavior.

html
<select class="appearance-base-select
  picker:rounded-xl picker:shadow-lg picker:p-2
  picker-icon:text-teal-600
  open:picker-icon:rotate-180
  checkmark:text-teal-600">
  <option>Apple</option>
  <option>Banana</option>
</select>
addition

A live WCAG rating
on every element.

A dev-mode badge that prints an element's live WCAG rating. AAA, AA, AA Large or Fail. Pure CSS, no JavaScript, no build step. On while you design, off before you ship.

Change the background, the text color, hover it, animate it. The rating follows.

With text-contrast-* it adds a fifth state, Max, for when the level you asked for is unreachable from that background.

wcag badge
<div class="bg-blue-600 text-white wcag-badge"> Reads: AA </div> <!-- shade + badge together --> <div class="bg-yellow-200 text-contrast-aaa wcag-badge"> Auto-contrast, plus its rating </div> /* or call the function directly */ .label::before { content: --jib-wcag-rating( var(--bg), var(--fg)); }

wcag-badgewatch the ratings change as the colors move

Light on darkwhite on 900
Light on midwhite on 600
Dark on light900 on 400
Two near tones400 on 200