Quick answer: The TMP InputField caret is invisible because its color matches the background, its width is too small, or another UI element covers it. Set Caret Color to contrast with the input background, ensure Caret Width is at least 2, and check Canvas sort order and sibling hierarchy.

Here is how to fix a TextMeshPro InputField caret that is not visible. You add a TMP_InputField to your UI, type in it at runtime, and text appears — but there is no blinking cursor showing where the insertion point is. The input works, text is being entered, but the user has no visual feedback about cursor position. This is a UI polish issue that confuses players and makes text entry frustrating.

The Symptom

The TMP InputField accepts keyboard input and displays text, but:

The input field is functional — characters are inserted correctly — but the visual caret is missing or invisible.

Cause 1: Caret Color Matches Background

The default TMP InputField caret color is black (#000000). If your input field has a dark background, the caret is present but invisible against it. This is the most common cause.

Fix: Select the TMP InputField component. In the Inspector, find Caret Color under the Input Field settings and change it to a color that contrasts with your background. White for dark backgrounds, black for light backgrounds.

// Set caret color in code
using TMPro;

TMP_InputField inputField = GetComponent<TMP_InputField>();
inputField.caretColor = Color.white; // visible on dark backgrounds
inputField.customCaretColor = true; // must be true for caretColor to take effect

The customCaretColor flag is critical. If it is false, the caret uses the text color, which might also blend into the background. Set it to true to use the explicitly set caretColor.

Cause 2: Caret Width Too Small

The Caret Width property defaults to 1 pixel. On high-DPI displays or with Canvas Scaler set to a high reference resolution, 1 pixel can be sub-pixel and invisible after scaling.

inputField.caretWidth = 3; // 3 pixels wide, visible on high-DPI

Set it to 2 or 3 for reliable visibility across screen resolutions. This is a small visual tweak that makes a big difference on 4K displays.

Cause 3: Canvas Render Order

The caret is a generated UI graphic rendered within the InputField’s RectTransform. If another UI element sits on top of the InputField — a transparent panel, an overlay image, a tooltip background — the caret renders behind it and is hidden.

Fix: Check the hierarchy. The InputField should not have opaque siblings rendered after it (later in the hierarchy means rendered on top). Move overlapping elements earlier in the hierarchy or to a Canvas with a lower Sort Order.

A common culprit is a full-screen transparent Image used for catching clicks to close menus. If its Raycast Target is enabled and it sits above the InputField in the hierarchy, it both blocks clicks and covers the caret.

Cause 4: Missing GraphicRaycaster or EventSystem

The caret only appears when the InputField is focused, and focusing requires clicking it. Clicking requires a GraphicRaycaster on the parent Canvas and an EventSystem in the scene.

// Check at runtime if the required components exist
void ValidateInputSetup()
{
    if (FindObjectOfType<UnityEngine.EventSystems.EventSystem>() == null)
        Debug.LogError("No EventSystem in scene. InputField clicks will not work.");

    Canvas canvas = GetComponentInParent<Canvas>();
    if (canvas != null && canvas.GetComponent<UnityEngine.UI.GraphicRaycaster>() == null)
        Debug.LogError("Canvas missing GraphicRaycaster. InputField will not receive clicks.");
}

Without these components, the InputField never receives pointer events, never focuses, and the caret never spawns. Add them from Component > Event > GraphicRaycaster and Component > UI > Event System.

Cause 5: Raycast Target Disabled

The InputField’s background Image must have Raycast Target enabled. If you disabled it (common when optimizing UI raycasting performance), clicks pass through the InputField and it never activates.

Check both the InputField’s Image component and any child text components. The TMP text child does not need Raycast Target, but the background Image does.

Focus Without Click

If you want the caret to appear without a click (for example, auto-focusing a chat input), activate the InputField in code:

void Start()
{
    TMP_InputField inputField = GetComponent<TMP_InputField>();
    inputField.ActivateInputField();
    inputField.Select();
}

Both ActivateInputField and Select are needed. Select sets the EventSystem’s selected object, and ActivateInputField opens the input for typing and shows the caret.

“The caret is always there. It is just hiding behind something — the background color, an overlay panel, or the absence of an EventSystem. Find what is covering it.”

Related Issues

For TMP InputField text not appearing at all, check that the Text Component reference is assigned in the InputField inspector. For input not working on mobile, ensure you have the appropriate Input Module (Standalone or Touch). For caret position being wrong after changing font size, call ForceLabelUpdate() after changing the font size at runtime.

Caret color contrast. customCaretColor = true. Width >= 2. Check hierarchy order. Verify EventSystem exists.