or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-textarea-caret

Cross-browser library for calculating precise pixel coordinates of textarea and input caret positions

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/textarea-caret@3.1.x

To install, run

npx @tessl/cli install tessl/npm-textarea-caret@3.1.0

index.mddocs/

Textarea Caret Position

Cross-browser JavaScript library that calculates precise pixel coordinates of the text caret (cursor) position in HTML textarea and input elements. Uses an invisible mirror div technique to replicate element styling and determine exact caret positioning for building sophisticated text input interfaces.

Package Information

  • Package Name: textarea-caret
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install textarea-caret

Core Imports

const getCaretCoordinates = require('textarea-caret');

For ES modules:

import getCaretCoordinates from 'textarea-caret';

Browser (global with UMD pattern):

<script src="path/to/textarea-caret/index.js"></script>
<script>
  // Function available as window.getCaretCoordinates
</script>

Basic Usage

const getCaretCoordinates = require('textarea-caret');

// Get caret coordinates for a textarea
const textarea = document.querySelector('textarea');
textarea.addEventListener('input', function() {
  const caret = getCaretCoordinates(this, this.selectionEnd);
  console.log(`Caret at (${caret.left}, ${caret.top}) with height ${caret.height}px`);
});

// Get caret coordinates for an input
const input = document.querySelector('input[type="text"]');
const position = input.selectionStart;
const coordinates = getCaretCoordinates(input, position);

// Position a dropdown at the caret
const dropdown = document.getElementById('autocomplete');
dropdown.style.position = 'absolute';
dropdown.style.left = coordinates.left + 'px';
dropdown.style.top = (coordinates.top + coordinates.height) + 'px';

Capabilities

Caret Coordinate Calculation

Calculates the precise pixel coordinates of the text caret position in textarea and input elements.

/**
 * Calculate pixel coordinates of text caret position in textarea/input elements
 * @param element - HTML element (must be textarea or input type="text")
 * @param position - Integer caret position (typically selectionStart or selectionEnd)
 * @param options - Optional configuration object
 * @returns Object with top, left, and height properties in pixels
 */
function getCaretCoordinates(element, position, options);

Parameters:

  • element (HTMLElement, required): DOM element - must be <textarea> or <input type="text">
  • position (number, required): Integer caret position (0-based index into the text content)
  • options (object, optional): Configuration object with the following properties:
    • debug (boolean): If true, keeps the mirror div visible for debugging purposes (default: false)

Return Value:

interface CaretCoordinates {
  /** Offset in pixels from element's top edge (including border) */
  top: number;
  /** Offset in pixels from element's left edge (including border) */
  left: number;
  /** Height of the caret in pixels (typically the line height) */
  height: number;
}

Advanced Features:

  • Multi-line Support: Handles text wrapping in textareas with precise line positioning
  • Font Compatibility: Works with any font family, size, weight, and style variations
  • Text Transformations: Supports uppercase, lowercase, and other CSS text transforms
  • Spacing: Handles letter-spacing, word-spacing, and tab characters
  • Border/Padding: Accounts for all border widths and padding values
  • Scrolling: Correctly positions caret even when element content is scrolled
  • RTL Support: Right-to-left text direction compatibility
  • Cross-browser: Works on Chrome, Safari, Firefox, Opera, and IE9+ with browser-specific handling

Usage Examples:

// Basic autocomplete positioning
function showAutocomplete(textarea) {
  const position = textarea.selectionStart;
  const coords = getCaretCoordinates(textarea, position);
  
  const dropdown = document.getElementById('autocomplete');
  dropdown.style.left = coords.left + 'px';
  dropdown.style.top = (coords.top + coords.height + 2) + 'px';
  dropdown.style.display = 'block';
}

// Mention system (@username)
function handleAtMention(textarea) {
  const text = textarea.value;
  const cursorPos = textarea.selectionStart;
  
  // Find @ symbol before cursor
  const atIndex = text.lastIndexOf('@', cursorPos - 1);
  if (atIndex !== -1) {
    const coords = getCaretCoordinates(textarea, cursorPos);
    showMentionDropdown(coords.left, coords.top + coords.height);
  }
}

// Debug mode to visualize the mirror div
function debugCaretPosition(element, position) {
  const coords = getCaretCoordinates(element, position, { debug: true });
  console.log('Caret coordinates:', coords);
  // Mirror div remains visible with highlighted caret position
}

// Input field with floating label
function updateFloatingLabel(input) {
  const coords = getCaretCoordinates(input, input.selectionStart);
  const label = document.getElementById('floating-label');
  
  if (input.value.length > 0) {
    label.style.left = coords.left + 'px';
    label.style.top = (coords.top - 20) + 'px';
  }
}

Error Handling:

The function throws an error if called in a non-browser environment:

// Throws: 'textarea-caret-position#getCaretCoordinates should only be called in a browser'
try {
  const coords = getCaretCoordinates(element, position);
} catch (error) {
  console.error('Must be called in browser environment:', error.message);
}

Browser Compatibility:

  • Chrome, Safari, Firefox, Opera (full support)
  • Internet Explorer 9+ (with currentStyle fallback)
  • Mobile browsers with touch support
  • Universal Module Definition (UMD) pattern for broad compatibility

Known Limitations:

  • Off-by-one positioning with spaces at end of lines in textareas (browser rendering issue)
  • Tab characters not supported in IE9
  • Edge cases with right-to-left text selection longer than input width
  • Firefox requires special overflow property handling

Implementation Details

The library works by creating an invisible mirror div that exactly replicates the styling of the target element:

  1. Mirror Creation: Creates a <div> positioned off-screen with identical styling
  2. Property Copying: Copies 47+ CSS properties from the original element (fonts, spacing, borders, etc.)
  3. Text Replication: Copies text content up to the caret position into the mirror
  4. Caret Marking: Inserts a <span> at the caret position with remaining text
  5. Coordinate Calculation: Uses the span's offset position to determine caret coordinates
  6. Cleanup: Removes the mirror div (unless debug mode is enabled)

This technique ensures pixel-perfect accuracy across different browsers and styling configurations.