Skip to content

Lightness ​

--jib-lightness() is the lightness transform as a callable value. It takes a color and returns a color, which is the whole point: a derived shade can go wherever a color goes, not only where a utility happens to exist.

The stable package covers seven surfaces with bg-lightness-* and its siblings. This page is about the properties it does not reach.

Chromium only

CSS @function ships in Chromium and nowhere else yet. Firefox and Safari drop any declaration that calls one, so every example on this page renders in Chromium and is blank elsewhere.

The utility form has no such limit. If you need a lightened background, border, text, fill, stroke, outline or accent color in every engine, reach for the stable utilities instead.

Quick reference ​

CallReturns
--jib-lightness(<color>, <number>)the color, lightened n% of the way to white
--jib-lightness(<color>, -<number>)the color, darkened n% of the way to black
--jib-lightness(<color>, <number>, <space>)the same, computed in the named color space
--jib-lighten(<color>, <number>)the same as a positive amount, named for the direction
--jib-darken(<color>, <number>)the same as a negative amount, named for the direction
--jib-<space>-lightness(<color>, <number>)the per-space function, called without the dispatch

Amount runs 0–100 and is a percentage of the remaining distance, so 50 travels halfway to white and 100 arrives exactly. The space argument is optional and defaults to oklch, matching every other transform in the library.

The directional aliases take the same three arguments and mirror the class API, so --jib-darken(c, 20) is bg-darken-20. Neither clamps: --jib-darken(c, -20) lightens, which is what lets one custom property animate through zero.

What the utility cannot reach ​

Underline color ​

An underline that is a lighter or deeper tint of the text color it sits under, derived from the one token that sets both. text-decoration-color has no utility in this library.

A shorthand elsewhere can silently win

text-decoration is a shorthand, and it resets text-decoration-color to currentColor. A stylesheet rule that sets text-decoration: underline on, say, every a will therefore throw away a derived underline color, and if that rule is unlayered it beats a Tailwind utility whatever the specificity.

Set text-decoration-line rather than the shorthand in the rule that is winning, or raise the utility into the same layer. The demos below are spans for exactly this reason: this site's own theme styles a that way.

a tinted underlinea deepened underline
html
<a
  class="text-teal-700 underline decoration-4
         decoration-[--jib-lightness(var(--color-teal-700),45)]"
>
  a tinted underline
</a>

A ring cut from the same token ​

shadow-* takes a color from the theme, but not a color derived from the one already on the element. The function does, so the halo and the fill stay locked together.

html
<div
  class="bg-teal-500
         shadow-[0_0_0_5px_--jib-lightness(var(--color-teal-500),40)]"
></div>

Both ends of a gradient, from one stop ​

This is the case with no utility answer at all. A gradient needs two colors; here you supply one and compute the other, so recoloring the whole ramp means editing a single token.

html
<div
  class="bg-[linear-gradient(90deg,var(--color-teal-600),
             --jib-lightness(var(--color-teal-600),60))]"
></div>

Text shadow ​

pressed into the page
html
<span
  class="text-teal-400
         [text-shadow:0_3px_0_--jib-lightness(var(--color-teal-400),-45)]"
>
  pressed into the page
</span>

A caret and a column rule ​

Two more properties with no utility form, both taking the function the same way.

A column rule takes a color like any border does, and the rule here is a lighter cut of the same token the text is set in, so the pair moves together.
html
<input class="caret-[--jib-lightness(var(--color-teal-500),-35)]" />

<div
  class="columns-2
         [column-rule:2px_solid_--jib-lightness(var(--color-teal-500),25)]"
></div>

Agreeing with the utility ​

Where a utility does exist, the two forms are the same arithmetic and land on the same color. The left half of each pair is the class, the right half the function.

bg-lighten-35
lightness(…,35)
bg-darken-35
lightness(…,-35)

Reach for the class when a utility covers the surface. It works in every engine, and reads better.

Per-space variants ​

The third argument names the space the arithmetic happens in. Every space also exists as a function of its own, which skips the dispatch when you already know the space you want.

Space familyFunctions
Perceptual polar--jib-oklch-lightness, --jib-lch-lightness
Perceptual rectangular--jib-oklab-lightness, --jib-lab-lightness
Legacy--jib-hsl-lightness, --jib-hwb-lightness
RGB family--jib-rgb-lightness, --jib-srgb-lightness, --jib-srgb-linear-lightness, --jib-display-p3-lightness, --jib-a98-rgb-lightness, --jib-prophoto-rgb-lightness, --jib-rec-2020-lightness
Device-independent--jib-xyz-lightness, --jib-xyz-d50-lightness, --jib-xyz-d65-lightness
Blend--jib-color-mix-lightness

An unrecognised space falls back to oklch rather than failing.

oklch
hsl
lab
rgb

The spaces render identically to the utility's /<space> modifier, because it is this function underneath. For the full per-space matrix and advice on which space to pick, see Color spaces in the stable docs.

The override ​

Importing this module also re-implements bg-lightness-*, bg-lighten-* and bg-darken-* on top of this function, on every surface, wherever @function is supported. Same class names, same output. See the overrides for how that swap is gated and why it cannot affect an engine that lacks @function.

Import ​

Order matters: source order is what carries an override, so the stable package comes first.

css
@import 'tw-jib-css';
@import 'tw-jib-css-experimental/functions';

Baseline status

What these utilities are built on, live from the Web Platform Dashboard.