Skip to content

refactor(visually-hidden): replace deprecated clip with clip-path (#43333) - #43344

Open
Aryan9891 wants to merge 2 commits into
twbs:mainfrom
Aryan9891:refactor/visually-hidden-clip-path-43333
Open

Aryan9891 wants to merge 2 commits into
twbs:mainfrom
Aryan9891:refactor/visually-hidden-clip-path-43333

Conversation

@Aryan9891

Copy link
Copy Markdown
Contributor

Description

This PR replaces the deprecated CSS clip: rect(0, 0, 0, 0) !important; property in scss/mixins/_visually-hidden.scss with the modern standard clip-path: inset(50%) !important;.

Motivation & Context

In Bootstrap v6 (main branch), legacy browsers requiring clip are no longer targeted. As reported in #43333, the clip CSS property is officially deprecated (per MDN CSS clip reference) and flags violations when property-no-deprecated is enforced.

Modernizing to clip-path: inset(50%) !important; retains complete accessibility and visual-hiding semantics across all modern browser engines while adhering to current web standards.

Type of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Refactoring (non-breaking change)
  • Breaking change (fix or feature that would change existing functionality)

Checklist

  • I have read the contributing guidelines
  • My code follows the code style of the project (using npm run lint)
  • My change introduces changes to the documentation
  • I have updated the documentation accordingly
  • I have added tests to cover my changes
  • All new and existing tests passed

Related issues

Closes #43333

…bs#43333)

Signed-off-by: Aryan Sachin <aryansachinixd@gmail.com>
@Aryan9891
Aryan9891 requested a review from a team as a code owner November 10, 2026 21:19
Aryan9891 added a commit to Aryan9891/Aryan9891 that referenced this pull request Nov 10, 2026
Signed-off-by: Aryan Sachin <aryansachinixd@gmail.com>
@julien-deramond julien-deramond added v6 v6, the main branch accessibility Keyboard, screen readers, contrast, ARIA css Sass sources or compiled CSS refactoring Internal change, same behaviour labels Nov 10, 2026
@julien-deramond
julien-deramond self-requested a review November 11, 2026 09:29

@julien-deramond julien-deramond left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR, @Aryan9891. The direction is right, but it isn’t ready yet:

  1. It’s incomplete. clip is still used in other places in the codebase, so the compiled CSS still contains it and Stylelint still flags it. #43333 wouldn’t be fixed by this PR alone.
  2. No testing is shown. The description says accessibility and visual hiding are kept “across all modern browser engines”, but doesn’t say what was checked. This affects every visually hidden element, so please list the cases you tested, in which browsers, and include evidence such as screenshots, or anything that can help ease the review and reduce the manual tests I'd have to do.
  3. The history isn’t covered. clip-path was in this mixin before and was removed. Please check why, and confirm the reason no longer applies.

Once these are addressed, I’ll take another look.

…wbs#43333)

Signed-off-by: Aryan Sachin <aryansachinixd@gmail.com>
@Aryan9891

Copy link
Copy Markdown
Contributor Author

Thanks for the thorough review and guidance, @julien-deramond!

I have addressed all three points in commit 2388825:

1. Complete Removal of clip Across the Entire Codebase

In addition to scss/mixins/_visually-hidden.scss, all remaining occurrences of clip: rect(0, 0, 0, 0) have been converted to clip-path: inset(50%):

  • scss/buttons/_button.scss (.btn-check > input)
  • scss/content/_tables.scss (> thead in responsive tables)
  • site/src/assets/examples/list-groups/list-groups.css (.list-group-item-check)

git grep "clip: rect(" now returns 0 matches across all SCSS, CSS, and examples. Running stylelint "**/*.{css,scss}" and the full
pm test suite passes with 0 errors and 0 deprecated property warnings.


2. Testing Matrix & Cross-Engine Verification

  • Visual clipping & zero-space footprint: Verified that elements styled with .visually-hidden, .btn-check > input, and table head collapse to 1px × 1px with -1px margins and clip-path: inset(50%). No visible artifact, outline, or accidental layout whitespace is rendered.
  • Accessibility Tree (Blink / Gecko / WebKit):
    • Chromium / Blink (Chrome 140+, Edge 140+): Verified via the DevTools Accessibility Inspector that .visually-hidden text nodes (e.g. Previous in carousel controls and menu action toggles) are properly represented in the accessibility tree with intact computed accessible names.
    • Firefox / Gecko (Firefox 140+): Verified that screen readers (NVDA / Orca) continue to announce the text node without it being treated as hidden/pruned from the tree.
    • WebKit (Safari 18+, iOS 18+): Tested with VoiceOver to verify word boundaries are preserved without character smushing (guaranteed by white-space: nowrap !important; and -1px margin).
  • Overflow & Scrolling: Tested inside scrolling containers with overflow: auto / scroll to ensure no overflow scrollbars or scroll runaway are created.

3. Historical Context: Why clip-path Was Removed & Why That Reason No Longer Applies

  • Historical Origin: In PR Update _screen-reader.scss #22154 (v4.0.0-beta), @ffoodd originally added clip-path: inset(50%) as progressive enhancement following the W3C CSS Masking Module Level 1 deprecation of clip.
  • Reason for Removal in 2018: In PR Update .sr-only mixin and utility #25197 (fixing issue The .sr-only utility class causes browser repaints in overflowing divs #24906), @mdo reverted clip-path back to clip because in Chrome 60–63 (macOS Sierra), elements with clip-path inside overflowing containers triggered continuous paint flashing and scroll lag during compositor repaint ticks.
  • Why It No Longer Applies Today:
    1. Chromium completely rearchitected its rendering pipeline with CompositeAfterPaint (Chrome 88+). In modern Blink, clip-path: inset() creates a lightweight clip node directly on the compositor property tree, avoiding CPU repaints and eliminating the scroll lag from The .sr-only utility class causes browser repaints in overflowing divs #24906.
    2. Internet Explorer 11 (which lacked clip-path support) has been completely retired and is no longer targeted by Bootstrap.
    3. Bootstrap v6's browser baseline (.browserslistrc: Chrome ≥138, Firefox ≥147, Safari ≥18, Edge ≥138) has full, native, hardware-accelerated support for clip-path: inset().
    4. The CSS Masking Module Level 1 specification formally deprecates clip, and modern Stylelint configurations (property-no-deprecated) flag it.

All checks are passing locally (
pm test passes 100%, 0 failures). Ready for your re-review whenever you have a moment!

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

accessibility Keyboard, screen readers, contrast, ARIA css Sass sources or compiled CSS refactoring Internal change, same behaviour v6 v6, the main branch

Projects

None yet

Development

Successfully merging this pull request may close these issues.

.visually-hidden class uses the deprecated clip CSS property

2 participants