jQuery .offset() Method

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

What You’ll Learn

The .offset() method gets or sets an element’s coordinates relative to the document as a PlainObject { top, left } — ideal for tooltips, click tracking, and drag-and-drop at page level. This tutorial covers getter and setter overloads, comparisons with .position(), .css("top")/.css("left"), and getBoundingClientRect(), callback setters since 1.4, and practical keyboard-move patterns.

01

Getter

.offset() → { top, left }

02

Setter

Since 1.4

03

Document

Page-relative

04

vs position

Offset parent

05

Callback

Since 1.4

06

Since 1.2

Getter API

Introduction

After learning dimension methods like .height() and .innerWidth(), you often need to know where an element sits on the page — not just how big it is. jQuery’s .offset() returns a plain object with top and left pixel distances from the document origin, ready for math, logging, and repositioning without parsing CSS strings.

Available since jQuery 1.2 as a getter, .offset() gained setter and callback forms in jQuery 1.4. The getter reads document coordinates from the first matched element; the setter moves every matched element to new document coordinates. Unlike .position(), which is relative to the offset parent, .offset() always answers “where is this on the page?”

If you have worked with native DOM APIs, element.getBoundingClientRect() returns viewport-relative coordinates. To convert to document coords you add window.scrollX and window.scrollY. jQuery’s .offset() performs that style of calculation for you and wraps it in a familiar jQuery API with optional setter support.

Understanding the .offset() Method

Given a jQuery object, .offset() either returns the current document coordinates of the first matched element as a PlainObject { top, left } (getter), or repositions every matched element to the coordinates you pass (setter). Both values are numbers measured in pixels from the top-left corner of the document.

Think of .offset() as a GPS pin on the full page. .position() is a local map inside a positioned container. Use .offset() when placing overlays at click coordinates, aligning popovers to page landmarks, or moving draggable widgets with arrow keys — anywhere document-relative placement matters.

💡
Beginner Tip

A box inside #wrap { position: relative; margin: 40px; } might report .position() as { top: 0, left: 0 } but .offset() as roughly { top: 40, left: 40 } plus padding — because offset measures from the document, not the wrapper.

📝 Syntax

jQuery .offset() has three argument forms — one getter and two setters:

Get — no arguments (since 1.2)

jQuery
.offset()  // -> { top: Number, left: Number }
  • Returns a PlainObject with top and left from the first matched element.
  • Coordinates are relative to the document, not the viewport or offset parent.
  • Returns undefined when the jQuery set is empty.
  • Values may be fractional on sub-pixel or zoomed layouts.

Set — coordinates object (since 1.4)

jQuery
.offset( { top: value, left: value } )  // -> jQuery
  • top / left — target document coordinates as Numbers (e.g. { top: 10, left: 30 }).
  • Applies to every matched element; returns the original jQuery object for chaining.
  • On position: static elements, jQuery sets position: relative before applying coordinates.

Set — callback function (since 1.4)

jQuery
.offset( function( index, coords ) {
  // return new { top, left } object
} )
  • index — zero-based position of the element in the matched set.
  • coords — current { top, left } of this element before the change.
  • Return a new coords object per element; jQuery applies it and returns the jQuery object.
jQuery
$( ".tile" ).offset( function( index, coords ) {
  return {
    top: coords.top,
    left: coords.left + ( index * 24 )
  };
});

Each tile shifts 24px further right based on its index — useful for fan-out animations and grid corrections without manual loops.

Return value

  • Getter — PlainObject { top, left }. Empty set → undefined.
  • Setter — the original jQuery object for chaining.

Important note

⚠️
Hidden elements

.offset() on display:none or hidden elements is unreliable — jQuery may return { top: 0, left: 0 }. Measure after showing the element, clone it off-screen, or use a visibility trick before reading.

Official jQuery API example

jQuery
var p = $( "p" ).last();
var offset = p.offset();
p.html( "left: " + offset.left + ", top: " + offset.top );

⚡ Quick Reference

GoalCode
Read document coordinates (PlainObject)$("div").offset()
Move element to document position$("div").offset({ top: 10, left: 30 })
Nudge position per callback$("div").offset(function(i, c){ return { top: c.top - 5, left: c.left }; })
Coords relative to offset parent$("div").position()
Read CSS top/left strings$("div").css("top")
Viewport rect (native)el.getBoundingClientRect()
Show click target coordsvar o = $(this).offset(); alert(o.left + ", " + o.top)
Arrow-key move (read/write offset)var o = $box.offset(); o.left += 10; $box.offset(o)

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

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

💡
Which one should I use?

Need page-level placement or a setter? → .offset(). Layout inside a position: relative wrapper? → .position() getter. 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.

.offset()
document

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

.position()
parent

Getter only — coords relative to offset parent; no setter

.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
.offset()DocumentYes (1.4+){ top, left } PlainObject
.position()Offset parentNo{ top, left } PlainObject
.css("top")CSS cascadeYesString ("10px", "auto")
getBoundingClientRect()ViewportNo (read-only)DOMRect (top, left, width, height)

Examples Gallery

Examples 1–3 follow the official jQuery API documentation. Examples 4–5 compare .offset() with .position() and build keyboard-driven movement. Use DevTools or the Try-it links to run each snippet.

📚 Getting Started

Official jQuery demos for reading and setting document coordinates.

Example 1 — Official Demo: Get Last Paragraph Offset

Read the document left and top of the last <p> and display them in the paragraph.

jQuery
var p = $( "p" ).last();
var offset = p.offset();
p.html( "left: " + offset.left + ", top: " + offset.top );
Try It Yourself

How It Works

No-argument .offset() returns a PlainObject with numeric top and left properties measured from the document origin. Only the first matched element is read when multiple elements are selected.

Example 2 — Official Demo: Click Any Element to Show Coords

Attach a click handler to every element in document.body and display its tag name with document offset.

jQuery
$( "*", document.body ).on( "click", function( event ) {
  var offset = $( this ).offset();
  event.stopPropagation();
  $( "#result" ).text(
    this.tagName + " coords ( " + offset.left + ", " + offset.top + " )"
  );
});
Try It Yourself

How It Works

$(this).offset() gives document coordinates for whichever element was clicked — paragraphs, spans, or an absolutely positioned box. event.stopPropagation() keeps nested clicks from bubbling to parent handlers.

Example 3 — Official Demo: Set Offset with { top: 10, left: 30 }

Reposition the last paragraph to document coordinates top: 10, left: 30 on page load.

jQuery
$( "p" ).last().offset({ top: 10, left: 30 });
Try It Yourself

How It Works

.offset({ top: 10, left: 30 }) moves the element so its top-left corner sits at those document coordinates. jQuery may set position: relative on static elements to achieve the placement. The setter returns the jQuery object for chaining.

📈 Practical Patterns

Compare placement APIs and build keyboard-driven repositioning.

Example 4 — Compare .offset() and .position() 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 5 — Arrow Keys Move Box with .offset() Setter

Read current document coords, adjust by 10px per arrow key, and write back with the setter — a simple drag-and-drop alternative.

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

How It Works

This read-modify-write pattern is the core of many drag helpers: getter returns current document position, you adjust numbers, setter applies the new coords. For mouse dragging, run the same logic on mousemove with pointer coordinates minus element dimensions.

💡
Drag-and-drop tip

On mousedown, store var start = $el.offset() and pointer start. On mousemove, compute deltaX/deltaY and call $el.offset({ top: start.top + deltaY, left: start.left + deltaX }). Use Math.round() if you need pixel-perfect integer steps.

🚀 Common Use Cases

  • Click coordinate logging$(this).offset() on click to show where the user hit an element on the page.
  • Tooltip and popover placement — position overlays at document coords derived from a trigger’s .offset() plus width/height.
  • Drag-and-drop helpers — read .offset(), update on mousemove, write with the setter (see Example 5).
  • Keyboard nudging — arrow-key handlers that increment/decrement top and left in fixed steps.
  • Layout debugging — compare .offset() and .position() to trace offset-parent vs document mismatches.
  • Absolute repositioning.offset({ top: 10, left: 30 }) to snap widgets to known document landmarks on load.
  • Scroll-aware overlays — combine trigger .offset() with .outerHeight() / .outerWidth() to anchor menus below buttons.
  • Staggered callback placement.offset(function(i, c){ return { top: c.top + i * 20, left: c.left }; }) for cascaded panels.

🧠 How .offset() Reads and Writes Coordinates

1

Match elements

jQuery object holds DOM elements to measure or move.

Input
2

Detect mode

No args → getter. Object or function → setter on each element (1.4+).

Route
3

Measure or apply

Getter walks offset-parent chain to document. Setter may set position: relative on static elements, then applies top/left.

DOM
4

Return result

Getter → PlainObject { top, left } (or undefined if empty). Setter → same jQuery object for chaining.

📝 Notes

  • Getter available since jQuery 1.2 — setter and callback since 1.4.
  • Getter returns PlainObject { top, left } from the first matched element only.
  • Coordinates are document-relative, not viewport-relative (contrast getBoundingClientRect()).
  • Setter on position: static elements internally applies position: relative.
  • .position() is offset-parent-relative and has no setter — do not confuse the two.
  • Empty jQuery set → getter returns undefined.
  • Unreliable on hidden (display:none) elements — may return { top: 0, left: 0 }.
  • Values can be fractional (e.g. 82.5) on sub-pixel or zoomed displays.
  • Setter returns the original jQuery object — e.g. .offset(o).addClass("moved").

Browser Support

.offset() getter has been part of jQuery since 1.2+. Setter and callback forms arrived in 1.4+. It wraps cross-browser document coordinate math with no browser-specific quirks beyond jQuery itself.

jQuery 1.2+

jQuery .offset()

Supported in jQuery 1.x, 2.x, and 3.x across all modern browsers and IE with supported jQuery builds. Native equivalent: getBoundingClientRect() plus scroll offsets for document coords — jQuery adds collection semantics, PlainObject returns, setter support, and callback chaining.

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
.offset() Universal

Bottom line: Safe in any jQuery project. Use .offset() for document placement; use .position() inside positioned containers; use getBoundingClientRect() when viewport coords suffice.

Conclusion

The jQuery .offset() method gets or sets document coordinates as a PlainObject { top, left } — the right placement helper when you need page-level position for clicks, tooltips, and drag-and-drop. It complements dimension methods like .innerWidth() and contrasts with .position(), which is local to the offset parent.

Remember the official demo: $( "p" ).last().offset() reads document coords, and the setter .offset({ top: 10, left: 30 }) repositions elements anywhere on the page. Use the callback form to nudge each element independently, and pair read-modify-write .offset() calls for keyboard or mouse movement — but never trust readings from display:none elements without showing them first.

💡 Best Practices

✅ Do

  • Use .offset() when you need document-relative coordinates
  • Use .position() for layout inside a positioned container
  • Read-modify-write .offset() for keyboard nudging and simple drags
  • Use the callback setter to adjust each matched element independently
  • Set position explicitly in CSS when you need long-term control

❌ Don’t

  • Confuse .offset() with .position() — different reference frames
  • Trust .offset() on display:none elements — it may return zeros
  • Expect the getter to read all matched elements — only the first
  • Assume .css("top") equals document coords — it returns CSS strings
  • Forget that an empty jQuery set returns undefined from the getter

Key Takeaways

Knowledge Unlocked

Six things to remember about .offset()

Document coordinates — ready for placement.

6
Core concepts
= 02

Setter

1.4+

Write
doc 03

Document

Page coords

Frame
fn 04

Callback

1.4+

Index
pos 05

vs position

Parent rel

Compare
hide 06

Hidden

Unreliable

Caveat

❓ Frequently Asked Questions

Calling .offset() with no arguments is the getter — it returns a PlainObject { top, left } with the current coordinates of the first matched element relative to the document. Calling .offset({ top, left }) or .offset(function) is the setter — it repositions every matched element in the document and returns the original jQuery object for chaining. The getter has been available since jQuery 1.2; setters and the callback form arrived in jQuery 1.4.
.offset() measures distance from the document origin (top-left of the page, ignoring scroll only in the sense that it accounts for document layout). .position() measures distance from the element's offset parent — usually the nearest positioned ancestor. An element inside a position:relative wrapper may have .position() { top: 0, left: 0 } while .offset() returns much larger document coordinates. Use .offset() for page-level placement; use .position() for layout inside a positioned container.
jQuery temporarily sets position: relative on elements that are position: static before applying top and left values derived from your target coordinates. That is how the setter can move elements that were not already positioned. If you need long-term CSS control, set position explicitly yourself and prefer .css('top') / .css('left') or .position() for offset-parent-relative moves.
No — .offset() on display:none or otherwise non-rendered elements is unreliable and may return { top: 0, left: 0 } or incorrect values because the browser has not laid out the element. Temporarily show the element, clone it off-screen, or measure after making it visible before trusting getter results.
Yes — since jQuery 1.4, .offset(function(index, coords)) receives the zero-based index and the element's current { top, left } object; return a new coords object to reposition each element independently. Getter and setter coordinates can be fractional (e.g. 82.5) on sub-pixel layouts, zoomed displays, or transformed elements; use Math.round() when you need integer steps for keyboard or grid movement.
.offset() is ideal when you need document-relative coordinates — for example, reading where the user clicked, placing a tooltip at page coordinates, or moving a draggable box with arrow keys by reading current .offset(), adjusting top/left, and writing back with the setter. For drag inside a scrollable or positioned container, combine .offset() with scroll offsets or prefer .position() relative to the offset parent. Modern alternatives include getBoundingClientRect() plus scroll math, but .offset() remains the jQuery-native shortcut.
Did you know?

jQuery’s .offset() getter has existed since version 1.2 — setters and callbacks arrived in 1.4. When you call the setter on a position: static element, jQuery temporarily promotes it to position: relative so top and left can take effect. That is why a paragraph can jump to { top: 10, left: 30 } without you writing CSS first. The callback setter mirrors .css() dimension callbacks — return a different { top, left } per index for staggered placement. For viewport-only math, native getBoundingClientRect() is often enough; add window.scrollX and scrollY when you need document coords without jQuery.

Next: .position()

Learn how to read coordinates relative to the offset parent.

.position() 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