textarea-caret-position

Calculates pixel-precise caret coordinates in textareas and text inputs for building autocomplete UIs.

Library
npm
v3.1.0
617stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
40/100Fair
Development Activity0
Maintenance20
Community60
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
56/100Fair
Architecture55
Code Quality30
Innovation75
Learning Curve65

textarea-caret-position is a dependency-free browser utility that returns the pixel (x, y) coordinates of the text caret inside a <textarea> or <input type=“text”> element. It works by creating an off-screen mirror <div> that replicates every relevant computed style of the target element — fonts, padding, borders, line-height, and text-transform — then inserting a <span> at the caret’s character position to read its offset.

The library is commonly used to build inline autocomplete and mention-style dropdowns (a la GitHub or Twitter’s @mentions) that need to appear directly beneath the cursor as the user types, rather than anchored to the whole input’s bounding box.

What You Get

  • Pixel-accurate caret coordinates for both <textarea> and <input type="text"> elements
  • A mirror-div technique that replicates padding, border, font, and line-height so positions match the real rendered text exactly
  • Cross-browser handling for Firefox-specific overflow quirks and an IE currentStyle fallback
  • RTL (right-to-left) text support
  • Zero runtime dependencies and a tiny single-file footprint

Common Use Cases

  • Positioning an @mention or #hashtag autocomplete dropdown at the caret in a comment box
  • Building inline emoji pickers that appear next to the cursor while typing
  • Implementing custom spell-check or syntax-highlight overlays anchored to caret position
  • Powering rich text editor toolbars that need to track cursor location in a plain textarea

Under The Hood

Architecture The entire library is a single IIFE in index.js exposing one function, getCaretCoordinates(element, position, options), exported via module.exports for CommonJS/bundler consumption or attached to window as a global fallback. There is no internal layering to speak of by design: the function builds a properties list of CSS attributes to copy, creates an off-screen mirror <div>, transfers each computed style from the target element onto it, splits the element’s text at the caret position into a text node plus a trailing <span>, appends the mirror to document.body, reads the span’s offsetTop/offsetLeft, and tears the mirror down again. Nothing here would break under change because there is effectively one code path and one exported surface.

Tech Stack Plain vanilla JavaScript with no runtime dependencies, no TypeScript, and no build step — package.json lists a single index.js as its entire files array. It targets DOM APIs directly (getComputedStyle, createElement, appendChild, offsetTop/offsetLeft) and includes an IE8/9 currentStyle fallback path. Distribution is dual: published to npm as textarea-caret and separately registered as a Component/Bower package (component.json) under the name textarea-caret-position, reflecting its 2014-era front-end tooling origins.

Code Quality No automated test suite exists — the test/ directory holds only a static index.html demo page and accompanying CSS meant for manual/visual verification in a browser, not an executable test runner, and no CI configuration (Travis, GitHub Actions, or otherwise) is present in the repo. Naming is clear and the code carries extensive explanatory comments documenting cross-browser quirks (Firefox’s incorrect overflow reporting, IE’s inability to compute shorthand CSS properties), which partially offsets the lack of tests and type safety. There is no linter or formatter configuration beyond a single legacy /* jshint browser: true */ directive.

API Design The public surface is a single function taking an element, a caret position integer (typically element.selectionStart/selectionEnd), and an optional options.debug flag, returning a plain {top, left, height} object. This makes the library deliberately unopinionated about what “the caret” means — callers decide which selection boundary to pass — and integration requires no configuration objects, subclassing, or setup beyond a single require and function call, which keeps the barrier to first use very low despite the README being the only documentation source.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search