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:
- No blinking caret is visible
- Caret appears briefly then vanishes
- Caret shows only when text is selected (highlight works but caret does not)
- Caret appears in the wrong position (offset from text)
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.