Opacity
Opacity utilities make a whole element, including its content and children, partly transparent. Each step is a token on its own scale, so opacity-50, opacity(50) and token(opacity-50) all mean the same value.
How opacity works
Section titled “How opacity works”- Own scale. Keys come from the
$opacitiesmap. It is separate from$percentages, which sizes widths and heights, so the two can change independently. - Keys read as percentages. Key
50is0.5, key75is0.75. The class name is the key:opacity-50. - Tokens. Each key is emitted as
--nu-opacity-{key}. Classes and mixins outputvar(--nu-opacity-{key}). - State variants. Every class has
hover:,focus:,active:andgroup-hover:forms, and each of those has responsive variants.
Generated from the compiled core build.
| Key | Token | Value |
|---|---|---|
0 | --nu-opacity-0 | 0 |
5 | --nu-opacity-5 | 0.05 |
10 | --nu-opacity-10 | 0.1 |
20 | --nu-opacity-20 | 0.2 |
25 | --nu-opacity-25 | 0.25 |
30 | --nu-opacity-30 | 0.3 |
33 | --nu-opacity-33 | 0.33 |
40 | --nu-opacity-40 | 0.4 |
50 | --nu-opacity-50 | 0.5 |
60 | --nu-opacity-60 | 0.6 |
66 | --nu-opacity-66 | 0.66 |
70 | --nu-opacity-70 | 0.7 |
75 | --nu-opacity-75 | 0.75 |
80 | --nu-opacity-80 | 0.8 |
90 | --nu-opacity-90 | 0.9 |
100 | --nu-opacity-100 | 1 |
Opacity classes
Section titled “Opacity classes”<div class="flex wrap gap-2"> <div class="opacity-100 p-3 bg-brand text-on-brand rounded">100</div> <div class="opacity-75 p-3 bg-brand text-on-brand rounded">75</div> <div class="opacity-50 p-3 bg-brand text-on-brand rounded">50</div> <div class="opacity-25 p-3 bg-brand text-on-brand rounded">25</div> <div class="opacity-10 p-3 bg-brand text-on-brand rounded">10</div> <div class="opacity-0 p-3 bg-brand text-on-brand rounded">0</div></div>.thumbnail--muted { @include apply(opacity(50));}opacity-0 hides an element visually but keeps its space, keeps it clickable and keeps it in the accessibility tree. To remove an element, use hide instead.
Opacity or a subtle colour
Section titled “Opacity or a subtle colour”Opacity fades everything inside the element: text, borders, images and children. It cannot be undone by a child: a child of an opacity-50 element cannot be fully opaque.
To tint only a background, use a subtle colour instead. NuvoUI has no alpha colour syntax; the -subtle classes (bg-brand-subtle, bg-danger-subtle) are solid colours that follow the theme.
<div class="grid cols-2 gap-4"> <div class="opacity-50 p-3 bg-brand text-on-brand rounded">opacity-50: the text fades too</div> <div class="p-3 bg-brand-subtle text-brand rounded">bg-brand-subtle: only the background is light</div></div>State variants
Section titled “State variants”hover:, focus:, active: and group-hover: apply a key while the element is hovered, focused or pressed, or while the nearest ancestor with the group class is hovered.
<div class="flex wrap gap-4 x-center"> <button type="button" class="opacity-70 hover:opacity-100 transition-opacity">opacity-70 hover:opacity-100</button> <div class="group p-3 border rounded"> <span>Hover this card</span> <span class="opacity-0 group-hover:opacity-100 transition-opacity ms-2">Edit</span> </div></div>.card__actions { @include apply(opacity(0), transition-opacity);}.card:hover .card__actions,.card:focus-within .card__actions { @include apply(opacity(100));}| Prefix | Selector |
|---|---|
hover: |
.hover\:opacity-{key}:hover |
focus: |
.focus\:opacity-{key}:focus |
active: |
.active\:opacity-{key}:active |
group-hover: |
.group:hover .group-hover\:opacity-{key} |
Add transition-opacity to fade between values instead of switching at once. See Transitions.
Responsive variants
Section titled “Responsive variants”Every opacity class, including the state forms, has a responsive variant with an @{breakpoint} suffix: opacity-50@md, hover:opacity-100@lg. Variants apply from their breakpoint upwards.
<div class="opacity-100 opacity-50@md p-3 bg-brand text-on-brand rounded"> opacity-100 opacity-50@md: resize the window</div>.hint { @include apply(opacity(100), opacity(50) md);}| Suffix | Media query |
|---|---|
@xs | @media (min-width: 480px) |
@sm | @media (min-width: 640px) |
@md | @media (min-width: 768px) |
@lg | @media (min-width: 1024px) |
@xl | @media (min-width: 1280px) |
@2xl | @media (min-width: 1536px) |
opacity() accepts a key, a percentage, calc() or var().
@use "@nuvoui/core" as *;
.ghost { @include apply(opacity(75), opacity(100) hover);}.ghost { opacity: var(--nu-opacity-75);}.ghost:hover { opacity: var(--nu-opacity-100);}Keys, percentages and errors
Section titled “Keys, percentages and errors”A unitless number must be a key. A bare decimal such as 0.5 is not accepted, because it would mean something different from the class opacity-50. Write a percentage for a value that is not on the scale.
| Input | Output |
|---|---|
opacity(50) |
opacity: var(--nu-opacity-50) (0.5 by default) |
opacity(42%) |
opacity: 42% |
opacity(var(--overlay-opacity)) |
opacity: var(--overlay-opacity) |
opacity(0.5) |
Error |
opacity(7) |
Error |
Both errors give the same message:
opacity(0.5): use a $opacities key (0, 5, 10, 20, 25, 30, 33, 40, 50, 60, 66, 70, 75, 80, 90, 100) such as 50 for var(--nu-opacity-50), a percentage (50%), calc() or var().Tokens in your own CSS
Section titled “Tokens in your own CSS”.overlay { background-color: token(black); opacity: token(opacity-60);}Configuration
Section titled “Configuration”Pass your own $opacities map. Keys name the classes and tokens, values are opacity numbers from 0 to 1. The map replaces the default map; it is not merged.
@use "@nuvoui/core" with ( $generate-utility-classes: true, $opacities: (0: 0, 25: 0.25, 50: 0.5, 75: 0.75, 100: 1));Turn the classes off with the opacity feature flag. The tokens and the mixin stay available.
@use "@nuvoui/core" with ( $generate-utility-classes: true, $feature-flags: ("opacity": false));CSS variables
Section titled “CSS variables”| Variable | Description |
|---|---|
--nu-opacity-{key} |
One token per key of $opacities. Fixed across themes. See Scale. |
Class reference
Section titled “Class reference”Generated from the compiled core build. Each rule lists the class and its state forms. Responsive variants are not listed.
Opacity (16 rules)
| Selector | Declarations | Default value |
|---|---|---|
.opacity-0,
.hover:opacity-0:hover,
.focus:opacity-0:focus,
.active:opacity-0:active,
.group:hover .group-hover:opacity-0 | opacity: var(--nu-opacity-0) | 0 |
.opacity-5,
.hover:opacity-5:hover,
.focus:opacity-5:focus,
.active:opacity-5:active,
.group:hover .group-hover:opacity-5 | opacity: var(--nu-opacity-5) | 0.05 |
.opacity-10,
.hover:opacity-10:hover,
.focus:opacity-10:focus,
.active:opacity-10:active,
.group:hover .group-hover:opacity-10 | opacity: var(--nu-opacity-10) | 0.1 |
.opacity-20,
.hover:opacity-20:hover,
.focus:opacity-20:focus,
.active:opacity-20:active,
.group:hover .group-hover:opacity-20 | opacity: var(--nu-opacity-20) | 0.2 |
.opacity-25,
.hover:opacity-25:hover,
.focus:opacity-25:focus,
.active:opacity-25:active,
.group:hover .group-hover:opacity-25 | opacity: var(--nu-opacity-25) | 0.25 |
.opacity-30,
.hover:opacity-30:hover,
.focus:opacity-30:focus,
.active:opacity-30:active,
.group:hover .group-hover:opacity-30 | opacity: var(--nu-opacity-30) | 0.3 |
.opacity-33,
.hover:opacity-33:hover,
.focus:opacity-33:focus,
.active:opacity-33:active,
.group:hover .group-hover:opacity-33 | opacity: var(--nu-opacity-33) | 0.33 |
.opacity-40,
.hover:opacity-40:hover,
.focus:opacity-40:focus,
.active:opacity-40:active,
.group:hover .group-hover:opacity-40 | opacity: var(--nu-opacity-40) | 0.4 |
.opacity-50,
.hover:opacity-50:hover,
.focus:opacity-50:focus,
.active:opacity-50:active,
.group:hover .group-hover:opacity-50 | opacity: var(--nu-opacity-50) | 0.5 |
.opacity-60,
.hover:opacity-60:hover,
.focus:opacity-60:focus,
.active:opacity-60:active,
.group:hover .group-hover:opacity-60 | opacity: var(--nu-opacity-60) | 0.6 |
.opacity-66,
.hover:opacity-66:hover,
.focus:opacity-66:focus,
.active:opacity-66:active,
.group:hover .group-hover:opacity-66 | opacity: var(--nu-opacity-66) | 0.66 |
.opacity-70,
.hover:opacity-70:hover,
.focus:opacity-70:focus,
.active:opacity-70:active,
.group:hover .group-hover:opacity-70 | opacity: var(--nu-opacity-70) | 0.7 |
.opacity-75,
.hover:opacity-75:hover,
.focus:opacity-75:focus,
.active:opacity-75:active,
.group:hover .group-hover:opacity-75 | opacity: var(--nu-opacity-75) | 0.75 |
.opacity-80,
.hover:opacity-80:hover,
.focus:opacity-80:focus,
.active:opacity-80:active,
.group:hover .group-hover:opacity-80 | opacity: var(--nu-opacity-80) | 0.8 |
.opacity-90,
.hover:opacity-90:hover,
.focus:opacity-90:focus,
.active:opacity-90:active,
.group:hover .group-hover:opacity-90 | opacity: var(--nu-opacity-90) | 0.9 |
.opacity-100,
.hover:opacity-100:hover,
.focus:opacity-100:focus,
.active:opacity-100:active,
.group:hover .group-hover:opacity-100 | opacity: var(--nu-opacity-100) | 1 |
Accessibility and RTL
Section titled “Accessibility and RTL”- Contrast drops with opacity. Faded text blends into its background and loses contrast. Check faded text against WCAG 1.4.3 (4.5:1 for body text) and faded controls against WCAG 1.4.11 (3:1).
- Transparent is not hidden.
opacity-0content is still read by screen readers and still receives clicks and focus. Pair it withinvisibleorhidewhen the content should be unavailable, or reveal it on focus as well as hover. - Disabled controls. Core expresses disabled text with opacity rather than a token. Keep the
disabledattribute oraria-disabled="true"on the control; opacity alone does not tell assistive technology anything. - RTL. Opacity does not depend on direction.