Skip to content

Where applicable, convert SVG usage from background-image to mask-image #41289

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
2 tasks done
CaraesNaur opened this issue Mar 11, 2025 · 2 comments
Open
2 tasks done

Comments

@CaraesNaur
Copy link

Prerequisites

Proposal

SVGs used as background-image do not exist in the DOM, and therefore cannot make use of CSS color values in the document stylesheet.

Monochromatic SVG images (accordion-button, close-button, etc) could instead be used as a mask-image, where setting the background-color makes the shape visible. That color value would be easy to inherit as from an ancestor's CSS properties and become themeable.

State-based opacity and background-color change could still be used for interactivity cues.

For example:

.btn-close {
    /*
    Optionally reference theme color CSS variables from an ancestor: primary, success, danger, etc.
    These colors are obviously placeholders.
    */
    --bs-btn-close-color: light-dark(#fff, #000);
    --bs-btn-close-bg: light-dark(#000, #fff);
    /* The SVG's colors don't matter, it's just a mask */
    --bs-btn-close-mask: url([snipped for brevity]);
    --bs-btn-close-opacity: 0.25;
    --bs-btn-close-hover-opacity: 0.5;
    --bs-btn-close-focus-opacity: 1;
    --bs-btn-close-disabled-opacity: 0.25;
    box-sizing: content-box;
    width: 1em;
    height: 1em;
    padding: 0.25em 0.25em;
    color: var(--bs-btn-close-color);
    border: 0;
    border-radius: var(--bs-border-radius);
    opacity: var(--bs-btn-close-opacity);
}
.btn-close::before {
    content: '';
    inset: 0;
    background-color: var(--bs-btn-close-bg);
    mask-image: var(--bs-btn-close-mask);
    mask-repeat: no-repeat;
    mask-clip: content-box;
    mask-origin: content-box;
}

Unfortunately, using the existing SVGs directly on an element masks things like border and drop-shadow, so the mask would be placed on a pseudo-element.

At that point I'm pretty sure the SVGs could be moved to :root or one of the @layers.

Motivation and context

This change would make many SVG decorations more easily themed (such as #39481).

@mdo
Copy link
Member

mdo commented Apr 8, 2025

This is possible for elements like the close button, but we can't do this for forms unfortunately. Background images are unfortunately still the best bet universally, but we might end up with a mixed approach in v6. TBD.

@mdo
Copy link
Member

mdo commented Apr 10, 2025

What could be converted:

  • Accordion icons
  • Navbar toggler
  • Close button
  • Carousel controls
  • Bonus: Dropdown toggles (moving from generated pseudo-element arrow)

What can't be converted:

  • Select
  • Checkbox
  • Radio (could be converted to using borders though)
  • Switches
  • Form validation icons

Unsure if I've missed anything else.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants