Quick answer: If Mask shows the wrong area, check that the mask graphic and its RectTransform match the desired clip region; ShowMaskGraphic toggles whether the source image is also drawn. For text bleeding past the mask, ensure TMP submeshes use a mask-compatible material and call SetMaterialDirty after layout changes.

Here is how to fix Unity UI Masks that clip too much, too little, or seem to clip arbitrary unrelated elements. The Mask component uses the stencil buffer; alignment quirks, RectMask2D differences, and TextMeshPro’s independent submesh handling can produce surprising visual results. The fix depends on which mask type you are using.

The Symptom

A scrolling list cuts off the wrong rows. A circular avatar mask shows square corners. Text inside a Mask spills out past the edges. Or the mask graphic itself is invisible when you expected it to be drawn.

What Causes This

ShowMaskGraphic confusion. Mask defaults to hiding the source image (it is just a stencil reference). Without ShowMaskGraphic, the silhouette clips children but is itself invisible.

Mask vs RectMask2D semantics. RectMask2D clips along the RectTransform’s rect, regardless of the image. Mask uses the image’s alpha as the stencil shape.

TMP submesh isolation. TextMeshPro creates submeshes for material variations (e.g., different fonts in one label). Each submesh needs to be told about the mask separately.

Mismatched RectTransform anchoring. The mask’s RectTransform anchors to its parent, which may resize unexpectedly with layout changes, shifting the clip region.

The Fix

Step 1: Decide between Mask and RectMask2D.

// Mask:
//  + Any shape (rounded corners, circles, sprite alpha)
//  - Uses stencil buffer; one extra draw call per mask
//  - Nested masks limited by stencil depth

// RectMask2D:
//  + Cheap; no stencil draw call
//  + Soft-pixel clipping (better edges)
//  - Only rectangular
//  - Some shaders need to read clipping rect uniform manually

Use Mask for hero portraits, custom shapes. Use RectMask2D for scrolling lists, viewport content, anything rectangular.

Step 2: Toggle Show Mask Graphic. If you want the mask source to be visible (for example, a portrait frame around a clipped photo), check Show Mask Graphic on the Mask. Otherwise leave unchecked — the children are clipped but the mask itself is invisible.

Step 3: For RectMask2D, ensure children render with mask-aware shaders.

// Standard UI shaders (UI/Default, TMP_Default) read the clip rect
// Custom shaders need to:
//   #include "UnityUI.cginc"
//   sample _ClipRect uniform and discard outside it
fixed4 frag(v2f i) : SV_Target
{
    fixed4 col = tex2D(_MainTex, i.uv);
    col.a *= UnityGet2DClipping(i.worldPosition.xy, _ClipRect);
    return col;
}

Step 4: Refresh TMP after layout.

using TMPro;

void RefreshTextInsideMask(TextMeshProUGUI text)
{
    text.ForceMeshUpdate();
    var subs = text.GetComponentsInChildren<TMP_SubMeshUI>();
    foreach (var s in subs) s.SetMaterialDirty();
}

Call after the scroll position changes or the mask’s parent resizes.

Step 5: Avoid deeply nested masks. Stencil buffer depth is limited (effectively 8-bit, so ~8 nested Masks). Beyond that, masks misbehave. Replace deep nests with RectMask2D where possible.

Common Pitfalls

Mask on a Canvas with ScreenSpace - Camera in worldspace can produce unexpected clipping if the camera plane is angled. Use ScreenSpace - Overlay for simple masking unless you specifically need camera-space.

RectMask2D + TextMeshPro requires TMP >= 3.x for proper soft clipping. Older TMP versions hard-clip with stair-step edges.

“Mask for shapes, RectMask2D for rectangles. Show Mask Graphic when you want to see the frame.”

Related Issues

For canvas group fade issues, see CanvasGroup Alpha Children. For UI clicks blocked, see Raycaster Blocking Clicks.

Pick the right mask. Toggle Show Mask Graphic. Refresh TMP after layout. Children clip cleanly.