Skip to content

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.

  • Own scale. Keys come from the $opacities map. It is separate from $percentages, which sizes widths and heights, so the two can change independently.
  • Keys read as percentages. Key 50 is 0.5, key 75 is 0.75. The class name is the key: opacity-50.
  • Tokens. Each key is emitted as --nu-opacity-{key}. Classes and mixins output var(--nu-opacity-{key}).
  • State variants. Every class has hover:, focus:, active: and group-hover: forms, and each of those has responsive variants.

Generated from the compiled core build.

KeyTokenValue
0--nu-opacity-00
5--nu-opacity-50.05
10--nu-opacity-100.1
20--nu-opacity-200.2
25--nu-opacity-250.25
30--nu-opacity-300.3
33--nu-opacity-330.33
40--nu-opacity-400.4
50--nu-opacity-500.5
60--nu-opacity-600.6
66--nu-opacity-660.66
70--nu-opacity-700.7
75--nu-opacity-750.75
80--nu-opacity-800.8
90--nu-opacity-900.9
100--nu-opacity-1001
100
75
50
25
10
0
<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>

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 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.

opacity-50: the text fades too
bg-brand-subtle: only the background is light
<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>

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.

Hover this card Edit
<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>
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.

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.

opacity-100 opacity-50@md: resize the window
<div class="opacity-100 opacity-50@md p-3 bg-brand text-on-brand rounded">
opacity-100 opacity-50@md: resize the window
</div>
SuffixMedia 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);
}

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().
.overlay {
background-color: token(black);
opacity: token(opacity-60);
}

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)
);
Variable Description
--nu-opacity-{key} One token per key of $opacities. Fixed across themes. See Scale.

Generated from the compiled core build. Each rule lists the class and its state forms. Responsive variants are not listed.

Opacity (16 rules)
SelectorDeclarationsDefault value
.opacity-0, .hover:opacity-0:hover, .focus:opacity-0:focus, .active:opacity-0:active, .group:hover .group-hover:opacity-0opacity: var(--nu-opacity-0)0
.opacity-5, .hover:opacity-5:hover, .focus:opacity-5:focus, .active:opacity-5:active, .group:hover .group-hover:opacity-5opacity: 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-10opacity: 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-20opacity: 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-25opacity: 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-30opacity: 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-33opacity: 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-40opacity: 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-50opacity: 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-60opacity: 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-66opacity: 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-70opacity: 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-75opacity: 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-80opacity: 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-90opacity: 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-100opacity: var(--nu-opacity-100)1
  • 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-0 content is still read by screen readers and still receives clicks and focus. Pair it with invisible or hide when 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 disabled attribute or aria-disabled="true" on the control; opacity alone does not tell assistive technology anything.
  • RTL. Opacity does not depend on direction.