Panel Widget


Panel Widgetversion added: 1.3

Description: Creates a panel widget

QuickNavExamples

Methods

Panels are designed to be as flexible as possible to make it easy to create menus, collapsible columns, drawers, inspectors panes and more.

Where panel markup goes in a page

A panel must be a sibling to the header, content, and footer elements inside a jQuery Mobile page. You can add the panel markup either before or after these elements, but not in between.

Here is an example of the panel before the header, content and footer in the source order:

1
2
3
4
5
6
7
8
9
10
11
<div data-role="page">
<div data-role="panel" id="mypanel">
<!-- panel content goes here -->
</div><!-- /panel -->
<!-- header -->
<!-- content -->
<!-- footer -->
</div><!-- page -->

Alternately, it's possible to add the panel markup after the header, content and footer in the source order, just before the end of the page container. Where in the source order you place the panel markup will depend on how you want to page content to read for people experiencing the page in a C-grade device (HTML only) or for a screen reader.

If a page contains a panel the framework wraps the header, content and footer sections in a div. When opening a panel with display mode "reveal" or "push" the transition is applied to this wrapper. An exception is fixed headers and footers. Those are not included in the wrapper, but will transition in sync with it. Be aware of the fact that all your visible page content should live inside those page sections.

CSS Multi-column Layout

To avoid blinks when opening a panel, we force hardware acceleration on WebKit browsers. The CSS that is used to do this can cause issues with buttons and form elements on the page if their container has a CSS multi-column layout (column-count). To resolve this you have to set the following rule for the element or its container:

1
-webkit-transform: translate3d( 0, 0, 0 );

External Panels

Since jQuery Mobile 1.4.0, it is also possible to have external panels. This means that you can now have panels located outside the page. Panels outside of a page must be initalized manually and will not be handled by auto init. Panels outside of pages will remain in the DOM (unless manually removed) as long as you use Ajax navigation, and can be opened or closed from any page. This can be handy when you want to use the same panel on more than one page.

Here is an example of an external panel:

1
2
3
4
5
6
7
8
9
<div data-role="page">
<!-- header -->
<!-- content -->
<!-- footer -->
</div><!-- page -->
<div data-role="panel" id="mypanel">
<!-- panel content goes here -->
</div><!-- /panel -->

The panel can be enhanced manually as follows:

1
2
3
$( function() {
$( "#mypanel" ).panel();
} );

Note that if the panel contains other jQuery Mobile widgets, such as listviews, these will need to be enhanced manually as well.

Panel markup conventions

A panel consists of a container with a data-role="panel" attribute and a unique ID. This ID will be referenced by the link or button to open and close the panel. The most basic panel markup looks like this:

1
2
3
<div data-role="panel" id="mypanel">
<!-- panel content goes here -->
</div>

The position of the panel on the screen is set by the data-position attribute. The position defaults to left, meaning it will appear from the left edge of the screen. Specify data-position="right" for it to appear from the right edge instead.

The display mode of the panel is set by the data-display attribute. The defaults to reveal, meaning the panel will sit under the page and reveal as the page slides away. Specify data-display="overlay" for the panel to appear on top of the page contents. A third mode, data-display="push" animates both the panel and page at the same time.

Here is an example of a panel with a custom position and display option set:

1
2
3
<div data-role="panel" id="mypanel" data-position="right" data-display="push">
<!-- panel content goes here -->
</div>

Dynamic content

When you dynamically add content to a panel or make hidden content visible while the panel is open, you have to trigger the updatelayout event on the panel.

1
$( "#mypanel" ).trigger( "updatelayout" );

The framework will check the new height of the panel contents and, in case this exceeds the screen height, set the page min-height to this height and unfix panels with data-position-fixed="true". See also Panel positioning.

Opening a panel

A panel's visibility is toggled by a link somewhere on the page or by calling the panel's open method directly. The defaults place the panel on the left in "reveal" mode. Open a panel programmatically like this:

1
$( "#idofpanel" ).panel( "open" , optionsHash );

To control a panel from a link, point the href to the ID of the panel you want to toggle (mypanel in the example below). This instructs the framework to bind the link to the panel. This link will toggle the visibility of the panel so tapping it will open the panel, and tapping it again will close it.

1
<a href="#mypanel">Open panel</a>

When using markup to control panels, you can only have a single panel open at once. Clicking a link to open a panel while one is already open will auto-close the first. This is done to keep the markup-only configuration simple.

Closing a panel

Clicking the link that opened the panel, swiping left or right, or tapping the Esc key will close the panel. To turn off the swipe-to-close behavior, add the data-swipe-close="false" attribute to the panel.

By default, panels can also be closed by clicking outside the panel onto the page contents. To prevent this behavior, add the data-dismissible="false" attribute to the panel. It's possible to have the panel and page sit side-by-side at wider screen widths and prevent the click-out-to-close behavior only above a certain screen width by applying a media query. See the responsive section below for details.

A panel can also be closed by calling the panel's close method directly.

1
$( "#idofpanel" ).panel( "close" );

It's common to also add a close button inside the panel. To add the link that will close the panel, add the data-rel="close" attribute to tell the framework to close that panel when clicked. It's important to ensure that this link also makes sense if JavaScript isn't available, so we recommend that the href points to the ID of the page to which the user should jump when closing. For example, if the button to open the panel is in the header bar that has and ID of my-header, the close link in the panel should be:

1
<a href="#my-header" data-rel="close">Close panel</a>

Panel animations

Panels will animate if the browser supports 3D transforms. The presence of such support is established by the same criteria for CSS animation support we use for page transitions. Panel animations use translateX CSS transforms to ensure they are hardware accelerated and smooth.

The framework has a feature test to detect if the required CSS properties are supported and will fall back to a simple hide/show if not available. After thorough testing, we decided to not animate panels on less capable platforms because the choppier animations weren't a better experience than a simple hide/show.

The animate option allows you to turn off panel animations for all devices. To turn off animations via markup, add the data-animate="false" attribute to the panel container.

The use of hardware acceleration is triggered during initialization of the page to prevent blinks when opening a panel. Because this increases memory use you have to be aware of performance issues if you use long lists or scripts to dynamically inject content on a page with an animated panel.

Panel positioning

The panel will be displayed with the position:absolute CSS property, meaning it will scroll with the page. When a panel is opened the framework checks to see if the bottom of the panel contents is in view and, if not, scrolls to the top of the page.

You can set a panel to position:fixed, so its contents will appear no matter how far down the page you're scrolled, by adding the data-position-fixed="true" attribute to the panel. The framework also checks to see if the panel contents will fit within the viewport before applying the fixed positioning because this property would prevent the panel contents from scrolling and using overflow is not well supported enough to use at this time. If the panel contents are too long to fit within the viewport, the framework will simply display the panel without fixed positioning.

In general, we recommend that you place the buttons that open the panel at the very top of the screen which is the most common UI pattern for panels. This will avoid the need to scroll and also makes the transitions a bit smoother.

Note that there are issues with fixed positioning within Android WebView applications (not the browser) that can cause layout issues, especially when hardware acceleration isn't enabled. We recommend not to use the fixed position panel option if deploying to an Android app. Also, if you have a fixed panel on a page with fixed toolbars, the toolbars might not transition together with the page content.

Styling panels

By default, panels have very simple styles to let you customize them as needed. Panels are essentially just simple blocks with no margins that sit on either side of the page content. The framework wraps the panel content in a div with class ui-panel-inner which has a padding of 15 pixels. If needed you can override this with custom CSS or use option classes.panelInner to set a different class name for the div.

Panels have a fixed width of 17em (272 pixels) which is narrow enough to still show some of the page contents when open to make clicking out to close easy, and still looks good on wider tablet or desktop screens. The styles to set widths on panels are fairly complex but these can be overridden with CSS as needed.

Note that adding padding, borders, or margins directly to the panel container will alter the overall dimensions and could cause the positioning and animation to be affected. To avoid this, apply styles to the panel content wrapper (.ui-panel-inner).

Other than the theme background, width and 100% height styles, panels have very little styling on their own. The default theme for panels is "a". You can set a different theme for the panel by adding a data-theme to the panel container, or set data-theme="none" and add your own classes to style it as needed.

The framework applies the theme that is used for the page to the content wrapper. Before opening a panel that has display mode reveal or push, the page theme will be set to the same theme that is used for the panel. This is done to mask that most mobile browsers haven't finished painting the panel background when the animation to open it has already started. If you use a background image for a page, you have to set it for the ui-body-* class of the theme that you use for the page so it will be used as background of the content wrapper.

Making the panel responsive

When the push or reveal display is used, a panel pushes the page aside when it opens. Since some of the page is pushed offscreen, the panel is modal and must be closed to interact with the page content again. On larger screens, you may want to have the panel work more like a collapsible column that can be opened and used alongside the page to take better use of the screen real estate.

To make the page work alongside the open panel, it needs to re-flow to a narrower width so it will fit next to the panel. This can be done purely with CSS by adding a left or right margin equal to the panel width (17em) to the page contents to force a re-flow. Second, the invisible layer placed over the page for the click out to dismiss behavior is hidden with CSS so you can click on the page and not close the menu.

Here is an example of these rules wrapped in a media query to only apply this behavior above 35em (560px):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@media (min-width:35em) {
/* wrap on wide viewports once open */
.ui-panel-page-content-open.ui-panel-page-content-position-left {
margin-right: 17em;
}
.ui-panel-page-content-open.ui-panel-page-content-position-right {
margin-left: 17em;
}
.ui-panel-page-content-open {
width: auto;
}
/* disable "dismiss" on wide viewports */
.ui-panel-dismiss {
display: none;
}
/* same as the above but for panels with display mode "push" only */
.ui-panel-page-content-open.ui-panel-page-content-position-left.ui-panel-page-content-display-push {
margin-right: 17em;
}
.ui-panel-page-content-open.ui-panel-page-content-position-right.ui-panel-page-content-display-push {
margin-left: 17em;
}
.ui-panel-page-content-open.ui-panel-page-content-display-push {
width: auto;
}
.ui-panel-dismiss-display-push {
display: none;
}
}

Applying a preset breakpoint

Included in the widget styles is a breakpoint preset for this behavior that kicks in at 55em (880px). This breakpoint is not applied by default to make it easier for you to write custom breakpoints that work best for your content and design. To apply the breakpoint preset, add the ui-responsive-panel class to the page (not the panel).

Options

animate 

Type: Boolean
Default: true
Sets whether the panel will animate when opening and closing. If set to false, the panel will just appear and disappear without animation. This is recommended for fastest performance.

This option is also exposed as a data attribute:data-animate="false" on the panel container.

Code examples:

Initialize the panel with the animate option specified:

1
2
3
$( ".selector" ).panel({
animate: false
});

Get or set the animate option, after initialization:

1
2
3
4
5
// Getter
var animate = $( ".selector" ).panel( "option", "animate" );
// Setter
$( ".selector" ).panel( "option", "animate", false );

classes.animate 

Type: String
Default: "ui-panel-animate"
Class added to the panel, page contents wrapper and fixed toolbars when option animate is true and the 3D transform feature test returns true.

classes.contentFixedToolbar 

Type: String
Default: "ui-panel-fixed-toolbar-wrap"
Note: This class is no longer used as of 1.4.0, so setting this option will have no effect on the panel.

Class added to the page container to suppress scrolling horizontally

(version removed: 1.4)

classes.contentFixedToolbarClosed 

Type: String
Default: "ui-panel-content-fixed-toolbar-closed"
Note: This class is no longer used as of 1.4.0, so setting this option will have no effect on the panel.

Class added to fixed toolbars after the close animation is complete.

(version removed: 1.4)

classes.contentFixedToolbarOpen 

Type: String
Default: "ui-panel-content-fixed-toolbar-open"
Note: This class is no longer used as of 1.4.0, so setting this option will have no effect on the panel.

Class added to fixed toolbars when the panel is opening.

(version removed: 1.4)

classes.contentWrap 

Type: String
Default: "ui-panel-content-wrap"
Note: This class is no longer used as of 1.4.0, so setting this option will have no effect on the panel.

Class added to the wrapper injected around the page contents (header, content, footer), needed for positioning of the panel.

(version removed: 1.4)

classes.contentWrapClosed 

Type: String
Default: "ui-panel-content-wrap-closed"
Note: This class is no longer used as of 1.4.0, so setting this option will have no effect on the panel.

Class added to the page contents wrapper after the close animation is complete.

(version removed: 1.4)

classes.contentWrapOpen 

Type: String
Default: "ui-panel-content-wrap-open"
Note: This class is no longer used as of 1.4.0, so setting this option will have no effect on the panel.

Class added to the wrapper injected around the page contents (header, content, footer) when the panel is opening. Used for targeting hardware acceleration only during transitions.

(version removed: 1.4)

classes.modal 

Type: String
Default: "ui-panel-dismiss"
Class added to the overlay on the page to dismiss the panel when hidden.

classes.modalOpen 

Type: String
Default: "ui-panel-dismiss-open"
Class added to the invisible overlay over the page when the panel is open. Used to dismiss the panel.

classes.pageContainer 

Type: String
Default: "ui-panel-page-container"
Class applied to the page container.

classes.pageContentPrefix 

Type: String
Default: "ui-panel-page-content"
Used for wrapper and fixed toolbars position, display and open classes.

classes.pageFixedToolbar 

Type: String
Default: "ui-panel-fixed-toolbar"
Class applied to any fixed toolbars.

classes.pagePanel 

Type: String
Default: "ui-page-panel"
Note: This class is no longer used as of 1.4.0, so setting this option will have no effect on the panel.

Class added to the page container when a panel widget is present.

(version removed: 1.4)

classes.pagePanelOpen 

Type: String
Default: "ui-page-panel-open"
Note: This class is no longer used as of 1.4.0, so setting this option will have no effect on the panel.

Class added to the page when a panel is open.

(version removed: 1.4)

classes.panel 

Type: String
Default: "ui-panel"
Class added to the panel.

classes.panelClosed 

Type: String
Default: "ui-panel-closed"
Class added to the panel when closed.

classes.panelFixed 

Type: String
Default: "ui-panel-fixed"
Class added to the panel when fixed positioning is applied.

classes.panelInner 

Type: String
Default: "ui-panel-inner"
Class added to the panel contents wrapper div.

classes.panelOpen 

Type: String
Default: "ui-panel-open"
Class added to the panel when opening. Used for targeting hardware acceleration only during transitions.

defaults 

Type: Boolean
Default: false
Seting this option to true indicates that other widgets options have default values and causes jQuery Mobile's widget autoenhancement code to omit the step where it retrieves option values from data attributes. This can improve startup time.

This option is also exposed as a data attribute: data-defaults="true".

Code examples:

Initialize the panel with the defaults option specified:

1
2
3
$( ".selector" ).panel({
defaults: true
});

Get or set the defaults option, after initialization:

1
2
3
4
5
// Getter
var defaults = $( ".selector" ).panel( "option", "defaults" );
// Setter
$( ".selector" ).panel( "option", "defaults", true );

disabled 

Type: Boolean
Default: false
Disables the panel if set to true.

This option is also exposed as a data attribute: data-disabled="true".

Code examples:

Initialize the panel with the disabled option specified:

1
2
3
$( ".selector" ).panel({
disabled: true
});

Get or set the disabled option, after initialization:

1
2
3
4
5
// Getter
var disabled = $( ".selector" ).panel( "option", "disabled" );
// Setter
$( ".selector" ).panel( "option", "disabled", true );

dismissible 

Type: Boolean
Default: true
Sets whether the panel can be closed by clicking outside onto the page.

This option is also exposed as a data attribute:data-dismissible="false" on the link that opens the panel.

Code examples:

Initialize the panel with the dismissible option specified:

1
2
3
$( ".selector" ).panel({
dismissible: false
});

Get or set the dismissible option, after initialization:

1
2
3
4
5
// Getter
var dismissible = $( ".selector" ).panel( "option", "dismissible" );
// Setter
$( ".selector" ).panel( "option", "dismissible", false );

display 

Type: String
Default: "reveal"
The relationship of the panel to the page contents. This option accepts one of three values:
"reveal" Push the page over
"push" Re-flow the content to fit the panel content as a column
"overlay" Sit over the content

This option is also exposed as a data attribute:data-display="push" on the link that opens the panel.

Code examples:

Initialize the panel with the display option specified:

1
2
3
$( ".selector" ).panel({
display: "overlay"
});

Get or set the display option, after initialization:

1
2
3
4
5
// Getter
var display = $( ".selector" ).panel( "option", "display" );
// Setter
$( ".selector" ).panel( "option", "display", "overlay" );

initSelector 

Type: Selector
Default: See below

The default initSelector for the panel widget is:

1
":jqmData(role='panel')"

Note: This option is deprecated in 1.4.0 and will be removed in 1.5.0.
As of jQuery Mobile 1.4.0, the initSelector is no longer a widget option. Instead, it is declared directly on the widget prototype. Thus, you may specify a custom value by handling the mobileinit event and overwriting the initSelector on the prototype:

1
2
3
$( document ).on( "mobileinit", function() {
$.mobile.panel.prototype.initSelector = "div.custom";
});

Note: Remember to attach the mobileinit handler after you have loaded jQuery, but before you load jQuery Mobile, because the event is triggered as part of jQuery Mobile's loading process.

The value of this option is a jQuery selector string. The framework selects elements based on the value of this option and instantiates panel widgets on each of the resulting list of elements.

(version deprecated: 1.4.0)

position 

Type: String
Default: "left"
The side of the screen the panel appears on. Values can be "left" or "right".

This option is also exposed as a data attribute:data-position="right" on the link that opens the panel.

Code examples:

Initialize the panel with the position option specified:

1
2
3
$( ".selector" ).panel({
position: "right"
});

Get or set the position option, after initialization:

1
2
3
4
5
// Getter
var position = $( ".selector" ).panel( "option", "position" );
// Setter
$( ".selector" ).panel( "option", "position", "right" );

positionFixed 

Type: Boolean
Default: false
Sets whether the panel has fixed positioning so the contents are in view even if the page is scrolled down. This also allows the page to scroll while the panel stays fixed. We recommend not to enable this feature when panels are used withing Android apps because of poor performance and display issues.

This option is also exposed as a data attribute:data-position-fixed=true on the panel.

Code examples:

Initialize the panel with the positionFixed option specified:

1
2
3
$( ".selector" ).panel({
positionFixed: true
});

Get or set the positionFixed option, after initialization:

1
2
3
4
5
// Getter
var positionFixed = $( ".selector" ).panel( "option", "positionFixed" );
// Setter
$( ".selector" ).panel( "option", "positionFixed", true );

swipeClose 

Type: Boolean
Default: true
Sets whether the panel can be closed by swiping left or right over the panel.

This option is also exposed as a data attribute:data-swipe-close=false on the panel.

Code examples:

Initialize the panel with the swipeClose option specified:

1
2
3
$( ".selector" ).panel({
swipeClose: false
});

Get or set the swipeClose option, after initialization:

1
2
3
4
5
// Getter
var swipeClose = $( ".selector" ).panel( "option", "swipeClose" );
// Setter
$( ".selector" ).panel( "option", "swipeClose", false );

theme 

Type: String
Default: null, inherited from parent
Sets the color scheme (swatch) for the panel widget. It accepts a single letter from a-z that maps to the swatches included in your theme.

Possible values: swatch letter (a-z).

This option is also exposed as a data attribute: data-theme="b".

Code examples:

Initialize the panel with the theme option specified:

1
2
3
$( ".selector" ).panel({
theme: "b"
});

Get or set the theme option, after initialization:

1
2
3
4
5
// Getter
var theme = $( ".selector" ).panel( "option", "theme" );
// Setter
$( ".selector" ).panel( "option", "theme", "b" );

Methods

close()Returns: jQuery (plugin only)

closes a panel.
  • This method does not accept any arguments.
Code examples:

Invoke the close method:

1
$( ".selector" ).panel( "close" );

open()Returns: jQuery (plugin only)

opens a panel.
  • This method does not accept any arguments.
Code examples:

Invoke the open method:

1
$( ".selector" ).panel( "open" );

toggle()Returns: jQuery (plugin only)

toggles the visibility the panel so it will open a closed panel or close and open panel.
  • This method does not accept any arguments.
Code examples:

Invoke the toggle method:

1
$( ".selector" ).panel( "toggle" );

Events

beforeclose( event, ui )Type: panelbeforeclose

Triggered at the start of the process of closing a panel

Note: The ui object is empty but included for consistency with other events.

Code examples:

Initialize the panel with the beforeclose callback specified:

1
2
3
$( ".selector" ).panel({
beforeclose: function( event, ui ) {}
});

Bind an event listener to the panelbeforeclose event:

1
$( ".selector" ).on( "panelbeforeclose", function( event, ui ) {} );

beforeopen( event, ui )Type: panelbeforeopen

Triggered at the start of the process of opening a panel

Note: The ui object is empty but included for consistency with other events.

Code examples:

Initialize the panel with the beforeopen callback specified:

1
2
3
$( ".selector" ).panel({
beforeopen: function( event, ui ) {}
});

Bind an event listener to the panelbeforeopen event:

1
$( ".selector" ).on( "panelbeforeopen", function( event, ui ) {} );

close( event, ui )Type: panelclose

Triggered when the process (and animation) of closing a panel is finished

Note: The ui object is empty but included for consistency with other events.

Code examples:

Initialize the panel with the close callback specified:

1
2
3
$( ".selector" ).panel({
close: function( event, ui ) {}
});

Bind an event listener to the panelclose event:

1
$( ".selector" ).on( "panelclose", function( event, ui ) {} );

create( event, ui )Type: panelcreate

Triggered when a panel is created

Note: The ui object is empty but included for consistency with other events.

Code examples:

Initialize the panel with the create callback specified:

1
2
3
$( ".selector" ).panel({
create: function( event, ui ) {}
});

Bind an event listener to the panelcreate event:

1
$( ".selector" ).on( "panelcreate", function( event, ui ) {} );

open( event, ui )Type: panelopen

Triggered when the process (and animation) of opening a panel is finished

Note: The ui object is empty but included for consistency with other events.

Code examples:

Initialize the panel with the open callback specified:

1
2
3
$( ".selector" ).panel({
open: function( event, ui ) {}
});

Bind an event listener to the panelopen event:

1
$( ".selector" ).on( "panelopen", function( event, ui ) {} );

Example:

A basic example of a panel.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>panel demo</title>
<link rel="stylesheet" href="//code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.css">
<script src="//code.jquery.com/jquery-1.10.2.min.js"></script>
<script src="//code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js"></script>
<style>
.panel-content {
padding: 1em;
}
</style>
</head>
<body>
<div data-role="page" id="page1">
<div data-role="header">
<h1>jQuery Mobile Example</h1>
</div>
<div role="main" class="ui-content">
<a href="#defaultpanel" data-role="button" data-inline="true" data-icon="bars">Default panel</a>
</div>
<!-- defaultpanel -->
<div data-role="panel" id="defaultpanel" data-theme="b">
<div class="panel-content">
<h3>Default panel options</h3>
<p>This panel has all the default options: positioned on the left with the reveal display mode. The panel markup is <em>before</em> the header, content and footer in the source order.</p>
<p>To close, click off the panel, swipe left or right, hit the Esc key, or use the button below:</p>
<a href="#demo-links" data-rel="close" data-role="button" data-theme="a" data-icon="delete" data-inline="true">Close panel</a>
</div><!-- /content wrapper for padding -->
</div><!-- /defaultpanel -->
</div>
</body>
</html>

Demo: