CSS Cursor Not Showing on Clickable Component (Chrome Mac ARM)

I’m experiencing a strange cursor behavior where clickable components don’t show a pointer cursor in certain areas, but the onClick functionality still works perfectly. This issue appears to be specific to the topmost component when multiple components are stacked. Critical Detail: The bug only occurs when Chrome is in full screen mode AND scaled (either via Cmd+ zoom or when browser font size is configured to be larger). When Chrome is scaled but not in full screen, everything works perfectly.

  1. Browser: Chrome on Mac ARM (everything latest)
  2. CSS Reset: Using modern-normalize v3.0.1 with custom reset via CSS @layer
  3. Framework: React with CSS Modules
  4. Trigger Condition: Issue only occurs when Chrome is both full screen AND scaled (Cmd+ or larger font configured)

What I’ve Tried

  1. Multiple Component Test: I placed multiple clickable components in the same position using absolute positioning
  2. Observation: Only the topmost component exhibits the cursor issue
  3. Functionality Check: Added onClick handler to the entire component - the click events fire correctly even in areas where the cursor doesn’t change to pointer

Expected Behavior

Hovering over clickable elements should show cursor: pointer. The pointer cursor should appear consistently across the entire clickable area.

Actual Behavior

  • Some areas of the component show the default cursor instead of pointer
  • Click functionality works everywhere, but cursor visual feedback is inconsistent
  • Only affects the topmost component in a stack
function Sidebar({
    isCollapsed,
    currentOrganization,
    organizations,
    navLinks,
}: SidebarProps) {
    return (
        <div
            className={`${styles.sidebar} ${isCollapsed ? styles.collapsed : styles.expanded}`}
            data-collapsed={isCollapsed}
        >
            <SidebarHeader>
                <SidebarButton variant="dropdown" size="lg" icon={HomeIcon}>
                    <span>Company</span>
                    <span>Starter</span>
                </SidebarButton> // <-- Only this component has issues.
                <SidebarButton variant="dropdown" size="lg" icon={HomeIcon}>
                    <span>Company</span>
                    <span>Starter</span>
                </SidebarButton>
                <SidebarButton variant="dropdown" size="lg" icon={HomeIcon}>
                    <span>Company</span>
                    <span>Starter</span>
                </SidebarButton>
                <SidebarButton variant="dropdown" size="lg" icon={HomeIcon}>
                    <span>Company</span>
                    <span>Starter</span>
                </SidebarButton>
            </SidebarHeader>
            <SidebarContent>
                <SidebarMenu>
                    <SidebarButton
                        variant="default"
                        size="md"
                        icon={LayoutPanelTopIcon}
                    >
                        <p>Dashboard</p>
                    </SidebarButton>
                </SidebarMenu>
            </SidebarContent>
        </div>
    );
}

Component itself:

function SidebarButton({
    variant,
    size,
    children,
    className,
    icon: Icon,
}: CombinedSidebarButtonProps) {
    switch (size) {
        case "lg":
            return (
                <button
                    type="button"
                    className={clsx(
                        sidebarButtonVariants({ variant, size }),
                        styles.base,
                        className,
                    )}
                >
                    <div className={styles.leftIconWrapper}>
                        <Avatar
                            contentType="icon"
                            size="md"
                            icon={HomeIcon}
                            variant="circular"
                        />
                    </div>
                    <div className={styles.collapsibleWrapper}>
                        <div className={styles.textWrapper}>{children}</div>
                        <div className={styles.rightIconWrapper}>
                            <ChevronsUpDown />
                        </div>
                    </div>
                </button>
            );
        case "md":
            switch (variant) {
                case "default":
                    return (
                        <button
                            type="button"
                            className={clsx(
                                sidebarButtonVariants({ variant, size }),
                                styles.base,
                                className,
                            )}
                        >
                            <div className={styles.leftIconWrapper}>
                                <Icon className={styles.leftIcon} />
                            </div>
                        </button>
                    );
            }
    }
    return null;
}

It’s CSS:

.base {
    display: flex;
    align-items: center;
    align-self: stretch;
    background: var(--color-sidebarbutton-bg);
    cursor: pointer;
    overflow: hidden;
    background: yellow;

    .leftIconWrapper {
        display: flex;
        align-items: center;
        background: blue;

        .leftIcon {
            width: 1rem;
            height: 1rem;
        }
    }

    .collapsibleWrapper {
        width: 12rem;
        display: flex;
        align-items: center;
        flex: 0 0 auto;
        background: green;

        .textWrapper {
            display: flex;
            padding: 0 0.5rem;
            flex-direction: column;
            align-items: flex-start;
            flex: 1 0 0;
            background: cyan;
            cursor: pointer !important;

            span {
                font-size: 0.75rem;
                line-height: 1rem;
            }

            span:nth-child(2) {
                color: var(--color-text-placeholder);
                background: red;
            }
        }

        .rightIconWrapper {
            display: flex;
            padding: 0.5rem;
            justify-content: center;
            align-items: center;

            svg {
                width: 1rem;
                height: 1rem;
            }
        }
    }

    &:hover {
        background: var(--color-sidebarbutton-bg-hover);
    }
}

.md {
    padding: 0;
    border-radius: 0.375rem;

    .leftIconWrapper {
        padding: 0.5rem;
    }
}

.lg {
    padding: 0.5rem;
}

Debugging Steps Taken

  • Confirmed onClick works everywhere in the component
  • Verified cursor: pointer is applied via dev tools
  • Tested with cursor: pointer !important - no change
  • Confirmed issue only affects topmost component in stack
  • Tried removing CSS reset - issue persists
  • Discovered issue only occurs in full screen + scaled Chrome
  • Confirmed bug disappears when Chrome is windowed (even when still scaled)
  • Not seeing this bug in Safari and Firefox under the same conditions

Questions

  • Is this a known Chrome bug on Mac ARM? Specifically related to full screen mode with browser scaling?
  • Why would scaling + full screen affect cursor rendering? The issue doesn’t occur in windowed mode with the same scaling
  • Why would only the topmost component be affected? Lower components in the same stack work fine
  • Could this be related to CSS reset/normalize interference?
  • Any workarounds to force consistent cursor behavior in full screen scaled Chrome?

You’re describing a very specific and reproducible bug that looks like a Chrome rendering issue on macOS ARM, especially under full screen + scaling conditions. Here’s a plain, human-written breakdown of what’s happening and what to do about it:


What’s Actually Happening

You’re applying cursor: pointer properly, and onClick works everywhere — but Chrome isn’t showing the pointer cursor in certain parts of your topmost absolutely stacked component only when:

  • Chrome is full screen, and
  • Chrome is scaled (either via Cmd + or system font size)

That means this isn’t a problem with your code or CSS — it’s likely a bug in Chrome’s rendering layer on macOS when compositing scaled, full screen layers.


Why Only the Top Component?

Only the topmost stacked component has the issue, probably because Chrome is mishandling pointer hit-testing or z-index compositing in that specific full screen + scaled mode. Since the visual and click behavior still works, it suggests a cursor rendering glitch, not layout or event handling.


What You’ve Already Confirmed

  • Not caused by your CSS or resets: you’ve tested with and without modern-normalize
  • Scoped to Chrome on Mac ARM: no repro on Safari or Firefox
  • Only happens in full screen + zoom: windowed + zoomed is fine
  • Doesn’t matter if cursor: pointer !important is used: so it’s not a specificity issue

Workarounds & Fixes

Until Chrome fixes this (and this kind of bug may live for a while), here are some practical options:

1. Force a GPU Layer

Sometimes cursor bugs are fixed by forcing Chrome to treat the element as a new GPU layer. Add this to the problem component:

will-change: transform;
transform: translateZ(0);

Apply that to .base or the outermost button wrapper.

2. Add pointer-events: auto Explicitly

Even though it shouldn’t matter, Chrome sometimes misbehaves with pointer-events during zoom. Try:

.base {
  pointer-events: auto;
}

3. Add Transparent Outline or Border

This forces Chrome to re-evaluate mouse boundaries, and sometimes fixes weird pointer bugs:

.base {
  outline: 1px solid transparent;
}

4. Avoid Full Screen in Dev

If you’re doing pixel-perfect dev work, maybe avoid full screen mode until this is resolved. Not ideal, but it’s the only way to 100% avoid it right now.


To Your Questions

Is this a known Chrome bug?
Yes, cursor-related bugs in Chrome’s compositor have popped up in the past — especially under scaling or full screen mode. You’re probably hitting one that’s specific to Chrome on macOS ARM.

Why does scaling + full screen affect it?
Chrome uses GPU compositing to render layers. When scaled and full screen, it uses different rendering paths that are more likely to miscalculate mouse hit areas or cursor styles, especially in absolutely positioned elements.

Why only the top component?
Likely because Chrome merges or flattens lower components correctly but treats the top one differently in GPU memory — possibly using a transparent layer that intercepts cursor state incorrectly.

Could normalize/reset be affecting it?
You ruled this out already — the bug persists without the reset.

Any reliable workaround?
Try the transform: translateZ(0) trick. If that doesn’t work, combine it with outline: 1px solid transparent. These kinds of rendering glitches are often fixed by forcing Chrome to redraw the GPU layer differently.


Summary (TL;DR)

You’re hitting a Chrome-on-macOS ARM rendering bug where the cursor doesn’t always update properly in full screen + scaled mode. It’s not your fault, and your CSS is fine. Try using:

transform: translateZ(0);
will-change: transform;
outline: 1px solid transparent;

on the .base button wrapper to fix or mitigate it. Keep Chrome updated, and test windowed for now if needed.