JavaScript Document caretRangeFromPoint() Method

Beginner
⏱️ 11 min read
📚 Updated: Jul 2026
🎯 5 Examples
🚀 5 Try-it labs
Non-standard
Instance method

What You’ll Learn

document.caretRangeFromPoint() is a non-standard instance method that returns a Range for the document under viewport coordinates. Learn startContainer / startOffset, when it returns null, shadow DOM limitations, how it compares to caretPositionFromPoint(), and five try-it labs.

01

Kind

Instance method

02

Args

x, y

03

Returns

Range

04

Fields

startContainer

05

Prefer

caretPosition

06

Status

Non-standard

Introduction

Before the standard caretPositionFromPoint() API, some browsers (especially WebKit-based engines) exposed document.caretRangeFromPoint(x, y) to answer: “where in the document is the text caret at this pixel?”

MDN: it returns a Range object for the document fragment under the specified coordinates. For a collapsed caret at a click point, you typically read range.startContainer and range.startOffset.

⚠️
Fallback only (MDN)

Use this method when caretPositionFromPoint is missing. MDN warns it predates shadow DOM and behaves unpredictably with ShadowRoot objects.

Related tutorials: caretPositionFromPoint(), nodeType, textContent.

Understanding document.caretRangeFromPoint()

An instance method on the page’s document object. Not part of any official specification (MDN).

  • Input — viewport x and y (MDN).
  • Output — a Range, or null.
  • Caret mappingstartContainer + startOffset at the point.
  • Null cases — negative coords, outside viewport, or no text entry node (MDN).
  • Shadow DOM — unpredictable; use standard API with shadowRoots (MDN).
  • Modern pathcaretPositionFromPoint() (Baseline 2025).

📝 Syntax

General form of Document.caretRangeFromPoint (MDN):

JavaScript
caretRangeFromPoint(x, y)

Parameters

  • x — horizontal position within the current viewport (MDN).
  • y — vertical position within the current viewport (MDN).

Return value

A Range, or null (MDN).

Common patterns

JavaScript
// Prefer standard API, fall back to caretRangeFromPoint (MDN)
function getCaretAtPoint(x, y) {
  if (document.caretPositionFromPoint) {
    const pos = document.caretPositionFromPoint(x, y);
    return pos ? { node: pos.offsetNode, offset: pos.offset } : null;
  }
  if (document.caretRangeFromPoint) {
    const range = document.caretRangeFromPoint(x, y);
    return range
      ? { node: range.startContainer, offset: range.startOffset }
      : null;
  }
  return null;
}

paragraph.addEventListener("click", (e) => {
  const caret = getCaretAtPoint(e.clientX, e.clientY);
  console.log(caret);
});

⚡ Quick Reference

GoalCode
From clickdocument.caretRangeFromPoint(e.clientX, e.clientY)
Text noderange.startContainer (nodeType 3)
Char offsetrange.startOffset
Feature-detecttypeof document.caretRangeFromPoint === "function"
Prefer firstdocument.caretPositionFromPoint
MDN statusNon-standard

🔍 At a Glance

Four facts about document.caretRangeFromPoint().

Returns
Range

or null

Origin
WebKit

legacy

Shadow
unreliable

MDN

Use as
fallback

not primary

📋 Property mapping: Range vs CaretPosition

ConceptcaretRangeFromPointcaretPositionFromPoint
Container noderange.startContainerpos.offsetNode
Offsetrange.startOffsetpos.offset
Return typeRangeCaretPosition
OptionsNone{ shadowRoots: [...] }

Examples Gallery

Examples follow MDN Document: caretRangeFromPoint() and the fallback patterns on the caretPositionFromPoint() page.

📚 Getting Started

Read a Range from pointer coordinates.

Example 1 — Click: read startContainer and startOffset

Map a click to the legacy Range API.

JavaScript
paragraph.addEventListener("click", (e) => {
  if (!document.caretRangeFromPoint) return;

  const range = document.caretRangeFromPoint(e.clientX, e.clientY);
  if (!range) return;

  console.log({
    nodeName: range.startContainer.nodeName,
    nodeType: range.startContainer.nodeType,
    offset: range.startOffset
  });
});
Try It Yourself

How It Works

For text hits, startContainer is often a text node and startOffset is the character index.

Example 2 — Progressive enhancement (MDN pattern)

Try caretPositionFromPoint first, then caretRangeFromPoint.

JavaScript
function getCaretAtPoint(x, y) {
  if (document.caretPositionFromPoint) {
    const pos = document.caretPositionFromPoint(x, y);
    return pos
      ? { node: pos.offsetNode, offset: pos.offset, via: "standard" }
      : null;
  }
  if (document.caretRangeFromPoint) {
    const range = document.caretRangeFromPoint(x, y);
    return range
      ? { node: range.startContainer, offset: range.startOffset, via: "legacy" }
      : null;
  }
  return null;
}
Try It Yourself

How It Works

MDN’s official demo uses this order so modern browsers get the standard API.

📈 Practical Patterns

Null handling, split text, and API detection.

Example 3 — Returns null for invalid coordinates

MDN: negative or out-of-viewport coordinates return null.

JavaScript
if (!document.caretRangeFromPoint) return;

const negative = document.caretRangeFromPoint(-1, -1);
console.log(negative === null); // true (MDN)
Try It Yourself

How It Works

Always guard with if (!range) return before reading startContainer.

Example 4 — MDN fallback: split text at caret

When only caretRangeFromPoint exists, use it in the split-text demo.

JavaScript
function insertBreakAtPoint(e) {
  let textNode, offset;

  if (document.caretPositionFromPoint) {
    const pos = document.caretPositionFromPoint(e.clientX, e.clientY);
    textNode = pos?.offsetNode;
    offset = pos?.offset;
  } else if (document.caretRangeFromPoint) {
    const range = document.caretRangeFromPoint(e.clientX, e.clientY);
    textNode = range?.startContainer;
    offset = range?.startOffset;
  } else {
    return;
  }

  if (textNode?.nodeType === 3) {
    const replacement = textNode.splitText(offset);
    const br = document.createElement("br");
    textNode.parentNode.insertBefore(br, replacement);
  }
}
Try It Yourself

How It Works

Same UX as the standard API demo; only the property names differ on the legacy path.

Example 5 — Detect which caret API exists

Log support status for teaching and debugging.

JavaScript
const support = {
  caretPositionFromPoint: typeof document.caretPositionFromPoint === "function",
  caretRangeFromPoint: typeof document.caretRangeFromPoint === "function"
};

if (support.caretPositionFromPoint) {
  console.log("Use standard caretPositionFromPoint (MDN)");
} else if (support.caretRangeFromPoint) {
  console.log("Fallback to non-standard caretRangeFromPoint (MDN)");
} else {
  console.log("No caret-from-point API");
}
Try It Yourself

How It Works

MDN’s live sample shows a green message when the standard API exists, orange for legacy fallback only.

🚀 Common Use Cases

  • Legacy browser fallback — when caretPositionFromPoint is missing (MDN).
  • Rich text editors — map clicks to text offsets on older WebKit.
  • Maintaining old code — understand existing caretRangeFromPoint calls.
  • Teaching API evolution — compare non-standard vs Baseline 2025 standard.
  • Not for shadow DOM — MDN warns of unpredictable results; use standard API.
  • Not for new apps alone — always pair with feature detection and standard-first logic.

🧠 How caretRangeFromPoint() Works

1

Provide viewport x, y

Typically clientX / clientY from a pointer event (MDN).

Input
2

Hit-test document

Browser finds fragment under point; shadow DOM behavior is unreliable (MDN).

Resolve
3

Build Range

startContainer + startOffset describe the caret.

Range
4

Return Range or null

Invalid coords or no text entry node → null (MDN).

📝 Notes

  • MDN: Non-standard — not part of any specification.
  • Not Deprecated or Experimental on MDN — but not recommended for new code.
  • Prefer caretPositionFromPoint() when available (MDN).
  • Predates shadow DOM — unpredictable with ShadowRoot (MDN).
  • Coordinates are viewport-relative, not document/page coordinates.
  • Related: nodeType, textContent.

Browser Support

Document.caretRangeFromPoint() is Non-standard on MDN. Logos use the shared browser-image-sprite.png sprite. Historically supported in WebKit/Blink; prefer caretPositionFromPoint() where available.

Non-standard · Legacy fallback

Document.caretRangeFromPoint()

WebKit-era Range API — use caretPositionFromPoint() as the primary path.

Legacy Fallback only
Google Chrome Supported (legacy)
Yes
Apple Safari Supported (legacy)
Yes
Microsoft Edge Chromium legacy
Partial
Mozilla Firefox Prefer caretPositionFromPoint
Partial
Opera Chromium legacy
Partial
Internet Explorer Not supported
No
caretRangeFromPoint() WebKit

Bottom line: Feature-detect caretPositionFromPoint first. Use caretRangeFromPoint only as a fallback on engines that lack the standard API.

Conclusion

document.caretRangeFromPoint(x, y) is a legacy, non-standard way to get a Range at viewport coordinates. MDN recommends caretPositionFromPoint() instead when supported, and warns about shadow DOM unpredictability.

Continue with clear(), caretPositionFromPoint(), or the JavaScript hub.

💡 Best Practices

✅ Do

  • Try caretPositionFromPoint before this API (MDN)
  • Feature-detect typeof document.caretRangeFromPoint === "function"
  • Guard against null return values
  • Use clientX / clientY from pointer events
  • Normalize to a shared { node, offset } helper

❌ Don’t

  • Build new features only on this non-standard API
  • Rely on it inside shadow DOM components (MDN)
  • Assume every browser implements it
  • Skip the standard API when both exist
  • Use page coordinates without scroll adjustment

Key Takeaways

Knowledge Unlocked

Five things to remember about caretRangeFromPoint()

Legacy Range API — fallback, not your first choice.

5
Core concepts
🚫02

Status

non-standard

MDN
🔗03

Map

startContainer

offset
⚠️04

Shadow

unreliable

MDN
🛡05

Prefer

standard API

2025

❓ Frequently Asked Questions

It returns a Range object (or null) for the document fragment under viewport coordinates x and y — typically with startContainer and startOffset describing the caret position (MDN).
MDN marks it Non-standard only — not Deprecated or Experimental. It is not part of any official specification and is not recommended for new production code when a standard alternative exists.
MDN: use document.caretPositionFromPoint() on supporting browsers (Baseline 2025). It is standard and supports shadowRoots. Keep caretRangeFromPoint() as a fallback for older WebKit-based engines.
A Range, or null if x/y are negative, outside the viewport, or there is no text entry node at that point (MDN).
MDN warns it predates shadow DOM and returns unpredictable, implementation-specific results when ShadowRoot objects are present. Prefer caretPositionFromPoint() with shadowRoots.
range.startContainer ≈ pos.offsetNode and range.startOffset ≈ pos.offset for collapsed caret ranges at a single point.
Did you know?

MDN’s caretPositionFromPoint() live sample uses caretRangeFromPoint() as the WebKit fallback when the standard method is missing—mapping startContainer / startOffset to the same logic as offsetNode / offset.

Next: clear()

Learn why the deprecated document.clear() method is a no-op and what to use instead.

clear() →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

6 people found this page helpful