Skip to content
A JavaScript library for positioning elements
JavaScript
Find file
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.
LICENSE.md
README.md Updated copyright year
bower.json Create bower.json
jquery.popo.js Updated copyright year
jquery.popo.min.js Updated copyright year
popo.js
popo.min.js

README.md

popo.js

A JavaScript library for positioning HTML elements

Popo.js is a cross-browser JavaScript library that attempts to simplify the process of positioning HTML elements relative to other HTML elements regardless of their whereabouts in the DOM tree. The library is heavily influenced by jQuery UI Position plugin, but does not require jQuery or any other library to work. It's completely stand-alone.

Popo.js has been tested on most modern browsers (Chrome, Firefox, Opera, Safari, IE7+) and should be working nicely also on most mobile browsers.

If you're using jQuery or Zepto you might want to grab the jQuery adapter plugin also.

You can also play around with the popo.js demo to test how the positioning works in practice.

Download

v1.0 - Production (4.1kb minified)
v1.0 - Development (16.4kb uncompressed)

Getting started

Include the popo.js script in your site.

<script src="popo.min.js"></script>

If you're using jQuery add the adapter script after jQuery and popo.js.

<script src="popo.min.js"></script>
<script src="jquery.js"></script>
<script src="jquery.popo.min.js"></script>

Usage

// The format
popo( element [, method ] [, options ] );

// and with the jQuery adapter
$( element ).popo( [, method ] [, options ] );

element (type: element) (required)
Provide the element that you want to position.

method (type: string) (optional)
Provide a method — "set" or "get". Defaults to "set", if not specified.

options (type: object) (optional)
Provide an options object. The default options are stored in window.popo.defaults object.

Methods

set

Positions the target element by setting the target element's left and top CSS properties according to the position calculations.

get

Returns an object containing the calculated position of the target element. The returned object has two properties: left and top.

Options

base

Type: Element, Array  —  Default value: window

Defines which element the target element is positioned against. Alternatively you can define a point within an element using the following format: [x-coordinate, y-coordinate, element].


container

Type: Element, Array  —  Default value: null

Defines an optional container element that is used for collision detection. Alternatively you can define a point within an element using the following format: [x-coordinate, y-coordinate, element].


position

Type: String  —  Default value: 'center center center center'

Defines the target element's position relative to the base element. The format is "targetX targetY baseX baseY". Use "left", "right" and "center" to set the horizontal positions (targetX and baseX) and "top", "bottom" and "center" to set the vertical positions (targetY and baseY).


offset

Type: String  —  Default value: '0'

Defines a horizontal and a vertical offset in pixels. Accepts a single value or a pair for horizontal/vertical (e.g. "5" or "10 -5").


collision

Type: String, Function  —  Default value: 'none'

Defines what to do when one of the target element's sides overflows the container element's matching side. The container element must be defined for this option to have any effect. You can use one of the built-in collision methods ("push" or "push+") or alternatively a callback function which allows you to create your own collision handling logic.

Using the built-in collision methods

Use one of the following formats to define a built-in collision method for each side:
left top right bottom (e.g. "push push none push+")
left top-bottom right (e.g. "push none push+")
left-right top-bottom (e.g. "push none")
left-right-top-bottom (e.g. "push")

"push" method tries to keep the targeted sides of the target element within the container element's boundaries. If the container element is smaller than the target element and you want to make sure that a specific side will always be pushed fully inside the container element's area you can use forced push ("push+").

Using the callback function

Check out example 3 for an in-depth explanation.

Examples

Example 1

// Position target element on top of base element.
popo(document.getElementById("target"), {
  position: "center bottom center top",
  base: document.getElementById("base")
});

Example 2

// Use get method to retrieve target's position without actually positioning the target.
var position = popo(document.getElementById("target"), 'get', {
  position: "left top right center",
  base: document.getElementById("base")
});

// position.left => returns the final left position of target element 
// position.top => returns the final top position of target element

Example 3

// Using the jQuery adapter
$('#target').popo({
  // First let's define where we want target to be moved.
  // In this case we are aligning target element's left top corner
  // with base element's right top corner.
  position: "left top right top",
  // Let's give target some offset (5px to right, 10px to bottom).
  offset: '5 -10',
  // Notice that we're providing elements here, not jQuery objects,
  // if you're wondering about the [0] in the end.
  base: $('#base')[0],
  container: $('#container')[0],
  // Let's define a custom collision function that gives us
  // access to the positioning data and allows us to manipulate the
  // outcome of the positioning process.
  collision: function(targetPosition, targetOverlap, positionData) {

    // targetPosition is an object which contains the left 
    // and top coordinates of the new position. You can manipulate
    // the left and top property of this object and it will affect the
    // outcome of the positioning.

    // targetPosition.left => left value in pixels
    // targetPosition.top => top value in pixels

    // targetOverlap is an object which tells us how much (in pixels)
    // the target overlaps the container element from each side.

    // targetOverlap.left => left overlap in pixels
    // targetOverlap.right => right overlap in pixels
    // targetOverlap.top => top overlap in pixels
    // targetOverlap.bottom => bottom overlap in pixels

    // positionData object contains all the data 
    // (heights, widths and offsets) that was needed to calculate
    // the stuff in previous objects. Useful for creating your own
    // collision methods if you're not happy with the built-in 
    // 'push' and 'push+' methods.

    // positionData.target => target element's data
    // positionData.base => base element's data
    // positionData.container => container element's data

  }
});

Good to know

  • The CSS display property of target, base and container elements must not be none during positioning.
  • The target element's margin affects the final position so consider the margin as an extra offset. This is a feature, not a bug.
  • You can use popo to position elements within iframes, but you have to make sure that the target, base and container elements exist within the same window.
  • Popo.js uses the outer width/height (includes scrollbar, borders and padding) of the element when calculating positions. However, in the case of documentElement the scrollbar width/height is omitted.

License

Copyright © 2012 Niklas Rämö. Licensed under the MIT license.

Something went wrong with that request. Please try again.