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. A panel cannot be placed outside a page, but this constraint will be removed in a future version.

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);

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>

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-pannel-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-pannel-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 "c". 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
@media (min-width:35em) {
/* wrap on wide viewports once open */
.ui-page-panel-open .ui-panel-content-fixed-toolbar-display-push.ui-panel-content-fixed-toolbar-position-left,
.ui-page-panel-open .ui-panel-content-fixed-toolbar-display-reveal.ui-panel-content-fixed-toolbar-position-left,
.ui-page-panel-open .ui-panel-content-wrap-display-push.ui-panel-content-wrap-position-left,
.ui-page-panel-open .ui-panel-content-wrap-display-reveal.ui-panel-content-wrap-position-left {
margin-right: 17em;
}
.ui-page-panel-open .ui-panel-content-fixed-toolbar-display-push.ui-panel-content-fixed-toolbar-position-right,
.ui-page-panel-open .ui-panel-content-fixed-toolbar-display-reveal.ui-panel-content-fixed-toolbar-position-right,
.ui-page-panel-open .ui-panel-content-wrap-display-push.ui-panel-content-wrap-position-right,
.ui-page-panel-open .ui-panel-content-wrap-display-reveal.ui-panel-content-wrap-position-right {
margin-left: 17em;
}
.ui-page-panel-open .ui-panel-content-fixed-toolbar-display-push,
.ui-page-panel-open .ui-panel-content-fixed-toolbar-display-reveal {
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-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 wrapper (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"
Class added to the page container to suppress scrolling horizontally

classes.contentFixedToolbarClosed 

Type: String
Default: "ui-panel-content-fixed-toolbar-closed"
Class added to fixed toolbars after the close animation is complete.

classes.contentFixedToolbarOpen 

Type: String
Default: "ui-panel-content-fixed-toolbar-open"
Class added to fixed toolbars when the panel is opening.

classes.contentWrap 

Type: String
Default: "ui-panel-content-wrap"
Class added to the wrapper injected around the page contents (header, content, footer), needed for positioning of the panel.

classes.contentWrapClosed 

Type: String
Default: "ui-panel-content-wrap-closed"
Class added to the page contents wrapper after the close animation is complete.

classes.contentWrapOpen 

Type: String
Default: "ui-panel-content-wrap-open"
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.

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.pagePanel 

Type: String
Default: "ui-page-panel"
Class added to the page container when a panel widget is present.

classes.pagePanelOpen 

Type: String
Default: "ui-page-panel-open"
Class added to the page when a panel is open.

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.

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. Can either push the page over ("reveal"), re-flow the content to fit the panel content as a column ("push"), or sit over the content ("overlay").

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 

Default: ":jqmData(role='panel')"
This is used to define the selectors (element types, data roles, etc.) that will automatically be initialized as panels. To change which elements are initialized, bind this option to the mobileinit event:
1
2
3
$( document ).on( "mobileinit", function() {
$.mobile.panel.prototype.options.initSelector = ".mypanel";
});

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 within 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: "c"
Sets the color scheme (swatch) for the panel. 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="a".

Code examples:

Initialize the panel with the theme option specified:

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

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", "a" );

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.3.2/jquery.mobile-1.3.2.min.css">
<script src="//code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="//code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.js"></script>
<style>
.panel-content {
padding:15px;
}
</style>
</head>
<body>
<div data-role="page" id="page1">
<div data-role="header">
<h1>jQuery Mobile Example</h1>
</div>
<div data-role="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="c" data-icon="delete" data-inline="true">Close panel</a>
</div><!-- /content wrapper for padding -->
</div><!-- /defaultpanel -->
</div>
</body>
</html>

Demo: