jQuery .position() Method

Beginner
⏱️ 10 min read
📚 Updated: Jul 2026
🎯 5 Examples
🚀 5 Try-it labs
Offset parent

What You’ll Learn

The .position() method reads an element’s coordinates relative to its offset parent as a PlainObject { top, left } — ideal for layout inside positioned containers, aligning widgets near siblings, and keyboard nudging within a stage. This tutorial covers the getter-only API since jQuery 1.2, how to move elements with .css("top")/.css("left") when no setter exists, comparisons with .offset(), .css(), and getBoundingClientRect(), and practical measurement patterns.

01

Getter

.position() → { top, left }

02

No setter

Use .css()

03

Parent

Offset parent

04

vs offset

Document coords

05

Local layout

Same container

06

Since 1.2

Getter API

Introduction

After learning document coordinates with .offset(), you often need placement inside a positioned wrapper — a modal panel, a game stage, or a relatively positioned sidebar. jQuery’s .position() returns a plain object with top and left pixel distances from the element’s offset parent, ready for local math without converting from page coordinates.

Available since jQuery 1.2, .position() is a getter with no arguments and no setter overload. It reads offset-parent coordinates from the first matched element only. Unlike .offset(), which always answers “where is this on the page?”, .position() answers “where is this inside its containing positioned element?” — more useful when positioning one element near another within the same DOM subtree.

If you have worked with native DOM APIs, remember that getBoundingClientRect() returns viewport-relative coordinates. jQuery’s .position() is neither document-relative nor viewport-relative — it is local to the offset parent’s padding box. For page-level placement or a built-in setter, use .offset() instead.

Understanding the .position() Method

Given a jQuery object, .position() returns the current offset-parent coordinates of the first matched element as a PlainObject { top, left }. Both values are numbers measured in pixels from the padding edge of the offset parent to the margin edge of the element.

Think of .position() as a local map inside a positioned container. .offset() is a GPS pin on the full page. Use .position() when aligning a tooltip arrow to a chip inside a panel, nudging a draggable box within a stage, or listing tile coordinates in a grid — anywhere offset-parent-relative placement matters.

💡
Beginner Tip

A box inside #wrap { position: relative; padding: 20px; } might report .position() as { top: 0, left: 0 } at the padding origin, while .offset() returns much larger document coordinates that include the wrap’s margin and the page scroll position.

📝 Syntax

jQuery .position() has one form — a getter with no arguments:

Get — no arguments (since 1.2)

jQuery
.position()  // -> { top: Number, left: Number }
  • Returns a PlainObject with top and left from the first matched element.
  • Coordinates are relative to the offset parent (padding box of parent, margin box of element).
  • Returns undefined when the jQuery set is empty.
  • Values may be fractional on sub-pixel or zoomed layouts.
  • Does not support hidden elements; does not account for margins on the html element.

How to move without a setter

Because .position() has no setter, reposition elements with explicit CSS:

jQuery
// 1. Ensure the element is positioned
$el.css( "position", "absolute" );

// 2. Read current local coords, adjust, write back
var p = $el.position();
p.left += 10;
$el.css({ top: p.top, left: p.left });
  • Set position: absolute or position: relative so top and left take effect.
  • Read with .position(), mutate the numbers, write with .css({ top, left }).
  • For document-level moves, use .offset({ top, left }) setter instead (since 1.4).

Return value

  • Getter — PlainObject { top, left }. Empty set → undefined.
  • No setter — passing arguments has no effect; jQuery does not provide .position({ top, left }).

Important note

⚠️
Hidden elements

.position() does not support hidden (display:none) elements — readings are unreliable because the browser has not laid out the element. Measure after showing the element, clone it off-screen, or defer measurement until visibility is restored.

Official jQuery API example

jQuery
var p = $( "p" ).first();
var position = p.position();
$( "p" ).last().text( "left: " + position.left + ", top: " + position.top );

⚡ Quick Reference

GoalCode
Read offset-parent coordinates (PlainObject)$("div").position()
Move element inside offset parentvar p = $("div").position(); p.left += 10; $("div").css({ top: p.top, left: p.left })
Ensure element can be moved with top/left$("div").css("position", "absolute")
Coords relative to document$("div").offset()
Read CSS top/left strings$("div").css("top")
Viewport rect (native)el.getBoundingClientRect()
Show click target local coordsvar p = $(this).position(); alert(p.left + ", " + p.top)
Arrow-key move inside stagevar p = $box.position(); p.left += 10; $box.css({ top: p.top, left: p.left })

📋 .position() vs .offset() vs .css() vs getBoundingClientRect()

Four ways to read or write placement — offset-parent coords, document coords, raw CSS strings, and viewport-native rectangles.

💡
Which one should I use?

Layout inside a position: relative wrapper or same containing element? → .position() getter. Need page-level placement or a setter? → .offset(). Need the literal CSS value "auto" or "50%"? → .css("top"). Building without jQuery and only care about viewport? → getBoundingClientRect() plus scroll offsets for document coords.

.position()
parent

Getter only — coords relative to offset parent; no setter

.offset()
document

Get/set { top, left } relative to the document — jQuery PlainObject

.css()
"10px"

General CSS getter/setter — top/left return strings with units or auto

getBoundingClientRect()
viewport

Native DOMRect vs viewport — add scroll offsets for document coords

MethodReference frameSetter?Return type
.position()Offset parentNo{ top, left } PlainObject
.offset()DocumentYes (1.4+){ top, left } PlainObject
.css("top")CSS cascadeYesString ("10px", "auto")
getBoundingClientRect()ViewportNo (read-only)DOMRect (top, left, width, height)

Examples Gallery

Example 1 follows the official jQuery API documentation inside a padded container. Examples 2–5 compare .position() with .offset(), log chip coords on click, move a box with arrow keys inside a stage, and enumerate grid tile positions. Use DevTools or the Try-it links to run each snippet.

📚 Getting Started

Official jQuery demo for reading offset-parent coordinates inside a padded div.

Example 1 — Official Demo: Get First Paragraph Position

Read the offset-parent left and top of the first <p> and display them in the last paragraph inside a padded div.

jQuery
var p = $( "p" ).first();
var position = p.position();
$( "p" ).last().text( "left: " + position.left + ", top: " + position.top );
Try It Yourself

How It Works

No-argument .position() returns a PlainObject with numeric top and left properties measured from the offset parent’s padding edge. Only the first matched element is read when multiple elements are selected.

📈 Practical Patterns

Compare placement APIs, log local coords on click, and build keyboard-driven movement inside containers.

Example 2 — Compare .position() and .offset() in #wrap

See how a relatively positioned wrapper changes .position() but not the document meaning of .offset().

jQuery
var $box = $( "#box" );
var off = $box.offset();
var pos = $box.position();
$( "#out" ).html(
  ".offset()   → left: " + off.left + ", top: " + off.top + " (document)
" + ".position() → left: " + pos.left + ", top: " + pos.top + " (offset parent)" );
Try It Yourself

How It Works

.offset() always reports document coordinates. .position() reports placement inside the nearest offset parent — here #wrap with position: relative. The box sits at the origin of its parent locally, but far from the document origin globally.

Example 3 — Click Chips in #panel to Show Position

Attach click handlers to chip elements and display each chip’s offset-parent coordinates inside the panel.

jQuery
$( "#panel .chip" ).on( "click", function() {
  var pos = $( this ).position();
  $( "#result" ).text(
    this.textContent + " position ( " + pos.left + ", " + pos.top + " )"
  );
});
Try It Yourself

How It Works

$(this).position() gives local coordinates for whichever chip was clicked — ideal when aligning a tooltip or highlight to the clicked chip inside the same panel without converting from document coords.

Example 4 — Arrow Keys Move Box Inside #stage via .position() + .css()

Read current offset-parent coords, adjust by 10px per arrow key, and write back with .css() — the standard pattern when no setter exists.

jQuery
var step = 10;
$( document ).on( "keydown", function( e ) {
  var $box = $( "#box" );
  var p = $box.position();
  if ( e.key === "ArrowLeft" )  p.left -= step;
  if ( e.key === "ArrowRight" ) p.left += step;
  if ( e.key === "ArrowUp" )    p.top  -= step;
  if ( e.key === "ArrowDown" )  p.top  += step;
  if ( /Arrow/.test( e.key ) ) {
    e.preventDefault();
    $box.css({ top: p.top, left: p.left });
  }
});
Try It Yourself

How It Works

This read-modify-write pattern is the core of in-container movement: getter returns current offset-parent position, you adjust numbers, .css() applies the new coords. The box stays bounded relative to #stage rather than the full document — unlike an .offset() setter approach.

💡
Stage movement tip

Ensure #box { position: absolute; } inside #stage { position: relative; } so top and left are meaningful. Use Math.round() on p.top and p.left if you need pixel-perfect integer steps.

Example 5 — List Tile Positions in #grid

Loop over grid tiles and log each tile’s .position() relative to the grid container.

jQuery
var lines = [];
$( "#grid .tile" ).each( function( i ) {
  var pos = $( this ).position();
  lines.push( "Tile " + ( i + 1 ) + ": left " + pos.left + ", top " + pos.top );
});
$( "#out" ).html( lines.join( "
" ) );
Try It Yourself

How It Works

Calling .position() inside .each() reads the first (and only) element in each jQuery wrapper, giving per-tile local coordinates. Compare with .offset() if you need document coords for drag-and-drop across the page.

🚀 Common Use Cases

  • Local click coordinate logging$(this).position() on click to show where the user hit an element inside a panel.
  • Tooltip and popover alignment — position overlays relative to a trigger’s .position() plus width/height inside the same container.
  • In-container drag helpers — read .position(), update on mousemove, write with .css({ top, left }) (see Example 4).
  • Keyboard nudging inside a stage — arrow-key handlers that increment/decrement local top and left without affecting document coords.
  • Layout debugging — compare .position() and .offset() to trace offset-parent vs document mismatches.
  • Grid and tile enumeration — loop tiles and log each .position() to verify flex or float layout (see Example 5).
  • Relative widget placement — position one element near another within the same containing DOM element without scroll math.
  • Animation starting points — capture local coords before .animate({ top, left }) for in-container motion paths.

🧠 How .position() Reads Offset-Parent Coordinates

1

Match elements

jQuery object holds DOM elements to measure.

Input
2

Find offset parent

jQuery walks ancestors to locate the nearest offset parent (positioned ancestor or body).

Route
3

Measure local offset

Compute distance from parent padding box to element margin box. Hidden elements are not supported.

DOM
4

Return result

Getter → PlainObject { top, left } from first element (or undefined if empty). No setter — use .css() to move.

📝 Notes

  • Getter available since jQuery 1.2 — no arguments, no setter, no callback.
  • Getter returns PlainObject { top, left } from the first matched element only.
  • Coordinates are offset-parent-relative, not document-relative (contrast .offset()).
  • Measured from offset parent padding box to element margin box.
  • Does not account for margins on the html element.
  • Empty jQuery set → getter returns undefined.
  • Does not support hidden (display:none) elements — readings are unreliable.
  • Values can be fractional (e.g. 82.5) on sub-pixel or zoomed displays; zoom may affect accuracy.
  • To move elements, set position in CSS and use .css("top") / .css("left").

Browser Support

.position() getter has been part of jQuery since 1.2+. It wraps cross-browser offset-parent coordinate math with no browser-specific quirks beyond jQuery itself.

jQuery 1.2+

jQuery .position()

Supported in jQuery 1.x, 2.x, and 3.x across all modern browsers and IE with supported jQuery builds. Native equivalent: walk offsetParent chain or use getBoundingClientRect() with ancestor math — jQuery adds collection semantics and PlainObject returns.

100% With jQuery loaded
Google Chrome All versions · Desktop & Mobile
Full support
Mozilla Firefox All versions · Desktop & Mobile
Full support
Apple Safari All versions · macOS & iOS
Full support
Microsoft Edge All versions · Chromium & Legacy
Full support
Internet Explorer IE 6+ · Legacy environments
Full support
Opera All modern versions
Full support
.position() Universal

Bottom line: Safe in any jQuery project. Use .position() inside positioned containers; use .offset() for document placement; use .css() to write top/left when moving locally.

Conclusion

The jQuery .position() method reads offset-parent coordinates as a PlainObject { top, left } — the right placement helper when you need local position inside a positioned container for chips, stages, and grids. It complements document-level .offset() and contrasts with .css("top"), which returns CSS strings rather than computed local coords.

Remember the official demo: $( "p" ).first().position() reads offset-parent coords inside a padded div, and the last paragraph displays them. Because there is no setter, move elements with .css({ top, left }) after reading .position() — but never trust readings from hidden elements without showing them first.

💡 Best Practices

✅ Do

  • Use .position() for layout inside a positioned container
  • Use .offset() when you need document-relative coordinates or a setter
  • Read-modify-write .position() + .css() for in-container keyboard nudging
  • Set position: absolute or relative before writing top/left
  • Compare .position() and .offset() when debugging layout mismatches

❌ Don’t

  • Confuse .position() with .offset() — different reference frames
  • Expect a setter — .position({ top, left }) does not exist
  • Trust .position() on hidden elements — jQuery does not support them
  • Expect the getter to read all matched elements — only the first
  • Assume .css("top") equals local coords — it returns CSS strings like "auto"

Key Takeaways

Knowledge Unlocked

Six things to remember about .position()

Offset-parent coordinates — ready for local layout.

6
Core concepts
x 02

No setter

Use .css()

Move
par 03

Parent

Offset parent

Frame
off 04

vs offset

Document

Compare
box 05

Margin box

Padding origin

Measure
hide 06

Hidden

Unsupported

Caveat

❓ Frequently Asked Questions

The offset parent is the nearest ancestor element used as the reference frame for .position(). It is usually the closest ancestor with position: relative, absolute, fixed, or sticky — or the document body if none qualify. .position() returns { top, left } measured from the padding edge of that offset parent to the margin edge of the element. Understanding which element is the offset parent explains why two siblings can share the same .position() origin inside a positioned wrapper.
.position() measures distance from the offset parent — ideal when positioning one element near another inside the same containing DOM element. .offset() measures distance from the document origin (page-level coordinates). An element at the top-left corner of a position:relative wrapper may report .position() { top: 0, left: 0 } while .offset() returns much larger document coordinates that include margins, padding, and ancestor offsets. Use .position() for local layout; use .offset() for page-level placement.
.position() is getter-only. To reposition an element relative to its offset parent, set position explicitly in CSS (position: absolute or relative) and use .css('top', value) and .css('left', value). A common pattern is read-modify-write: var p = $el.position(); p.left += 10; $el.css({ top: p.top, left: p.left }). For document-level moves, use .offset() setter instead. Never expect .position({ top, left }) to work — jQuery does not provide that overload.
No — jQuery does not support .position() on hidden (display:none or otherwise non-rendered) elements. The browser has not laid out the element, so readings are unreliable and may be wrong or zero. Temporarily show the element, clone it off-screen, or measure after making it visible before trusting getter results. The same caution applies to .offset() on hidden elements.
According to the jQuery API, .position() calculates coordinates relative to the offset parent, using the offset parent's padding box as the origin and the element's margin box as the measured edge. That means parent padding shifts the local origin inward, and the element's own margin is included in the reported top/left. jQuery also does not account for margins on the html element when walking the offset-parent chain — a subtle edge case on full-page layouts.
Yes — .position() may return fractional numbers (e.g. 82.5) on sub-pixel layouts, zoomed displays, or transformed elements. Browser zoom can affect accuracy. Use Math.round() when you need integer steps for keyboard movement or grid snapping. An empty jQuery set returns undefined from the getter, not a coords object.
Did you know?

jQuery’s .position() getter has existed since version 1.2 — with no setter overload ever added. Coordinates are measured from the offset parent’s padding box to the element’s margin box, which is why parent padding shifts the local origin. jQuery deliberately does not account for margins on the html element when walking the chain. Fractional values like 82.5 are normal on zoomed or sub-pixel layouts. When you need document-level placement or a one-call setter, reach for .offset() instead — but for positioning one widget near another inside the same panel or stage, .position() keeps the math local and simple.

Next: .scrollLeft()

Learn how to read and set horizontal scroll position on overflow elements.

.scrollLeft() tutorial →

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