Sheet Modal
Sheet Modal is a special overlay type which is similar to Picker/Calendar’s overlay. Such modal allows to create custom overlays with custom content
Sheet Layout
Sheet layout is pretty simple:
<body>
...
<!-- Sheet Modal Container -->
<div class="sheet-modal">
<!-- Sheet Modal Toolbar, optional -->
<div class="toolbar">
<div class="toolbar-inner">
<div class="left"></div>
<div class="right">
<a href="#" class="link sheet-close">Done</a>
</div>
</div>
</div>
<!-- Sheet Modal Inner -->
<div class="sheet-modal-inner">
<!-- Sheet Modal content -->
<div class="block">
<p>Integer mollis nulla id nibh elementum finibus...</p>
</div>
</div>
</div>
</body>
Sheet Top Layout
By default sheet modal opens from the bottom of the screen. It is also possible to open it from the top of the screen. In this case we need to add sheet-modal-top
class to sheet element. It is also recommended to use bottom toolbar in this case:
<!-- Additional "sheet-modal-top" class to open it from top -->
<div class="sheet-modal sheet-modal-top">
<!-- Bottom toolbar for top sheet -->
<div class="toolbar toolbar-bottom">
<div class="toolbar-inner">
<div class="left"></div>
<div class="right">
<a href="#" class="link sheet-close">Done</a>
</div>
</div>
</div>
<!-- Sheet Modal Inner -->
<div class="sheet-modal-inner">
<!-- Sheet Modal content -->
<div class="block">
<p>Integer mollis nulla id nibh elementum finibus...</p>
</div>
</div>
</div>
Sheet App Methods
Let’s look at related App methods to work with Sheet:
app.sheet.create(parameters)- create Sheet instance
- parameters - object. Object with sheet parameters
Method returns created Sheet’s instance
app.sheet.destroy(el)- destroy Sheet instance
- el - HTMLElement or string (with CSS Selector) or object. Sheet element or Sheet instance to destroy.
app.sheet.get(el)- get Sheet instance by HTML element
- el - HTMLElement or string (with CSS Selector). Sheet element.
Method returns Sheet’s instance
app.sheet.open(el, animate)- opens Sheet
- el - HTMLElement or string (with CSS Selector). Sheet element to open.
- animate - boolean. Open Sheet with animation.
Method returns Sheet’s instance
app.sheet.close(el, animate)- closes Sheet
- el - HTMLElement or string (with CSS Selector). Sheet element to close.
- animate - boolean. Close Sheet with animation.
Method returns Sheet’s instance
app.sheet.stepOpen(el)- open/expand Sheet swipe step
- el - HTMLElement or string (with CSS Selector). Sheet element to open swipe step.
Method returns Sheet’s instance
app.sheet.stepClose(el)- close/collapse Sheet swipe step
- el - HTMLElement or string (with CSS Selector). Sheet element to close swipe step.
Method returns Sheet’s instance
app.sheet.stepToggle(el)- toggle (open or close) Sheet swipe step
- el - HTMLElement or string (with CSS Selector). Sheet element to toggle swipe step.
Method returns Sheet’s instance
Sheet Parameters
Now let’s look at list of available parameters we need to create Sheet:
Parameter | Type | Default | Description |
---|---|---|---|
el | HTMLElement | Sheet element. Can be useful if you already have Sheet element in your HTML and want to create new instance using this element | |
content | string | Full Sheet HTML layout string. Can be useful if you want to create Sheet element dynamically | |
backdrop | boolean | Enables Sheet backdrop (dark semi transparent layer behind). By default it is true for MD and Aurora themes and false for iOS theme | |
backdropEl | HTMLElement string | HTML element or string CSS selector of custom backdrop element | |
scrollToEl | HTMLElement string | HTML element or string (with CSS selector) of element. If specified, then sheet will try to scroll page content to this element on open | |
closeByBackdropClick | boolean | true | When enabled will be closed on backdrop click |
closeByOutsideClick | boolean | false | When enabled will be closed on when click outside of it |
closeOnEscape | boolean | false | When enabled will be closed on ESC keyboard key press |
animate | boolean | true | Whether the Sheet should be opened/closed with animation or not. Can be overwritten in .open() and .close() methods |
swipeToClose | boolean | false | Whether the Sheet can be closed with swipe gesture |
swipeToStep | boolean | false | When enabled it will be possible to split opened sheet into two states: partially opened and fully opened that can be controlled with swipe |
swipeHandler | HTMLElement string | If not passed, then whole Sheet can be swiped to close. You can pass here HTML element or string CSS selector of custom element that will be used as a swipe target. (swipeToClose or swipeToStep must be also enabled) | |
push | boolean | false | When enabled it will push view behind on open. Works only when top safe area is in place. It can also be enabled by adding sheet-modal-push class to Sheet element. |
on | object | Object with events handlers. For example:
|
Note that all following parameters can be used in global app parameters under sheet
property to set defaults for all sheets. For example:
var app = new Framework7({
sheet: {
closeByBackdropClick: false,
}
});
If you use auto-initialized sheet modals (e.g. you don’t create them via app.sheet.create
), it is possible to pass all available sheet parameters via data-
attributes. For example:
<!-- Pass parameters as kebab-case data attributes -->
<div class="sheet-modal" data-close-on-escape="true" data-swipe-to-close="true">
...
</div>
Sheet Methods & Properties
So to create Sheet we have to call:
var sheet = app.sheet.create({ /* parameters */ })
After that we have its initialized instance (like sheet
variable in example above) with useful methods and properties:
Properties | |
---|---|
sheet.app | Link to global app instance |
sheet.el | Sheet HTML element |
sheet.$el | Dom7 instance with sheet HTML element |
sheet.backdropEl | Backdrop HTML element |
sheet.$backdropEl | Dom7 instance with backdrop HTML element |
sheet.params | Sheet parameters |
sheet.opened | Boolean prop indicating whether sheet is opened or not |
Methods | |
sheet.open(animate) | Open sheet. Where
|
sheet.close(animate) | Close sheet. Where
|
sheet.stepOpen() | Open/expand sheet swipe step |
sheet.stepClose() | Close/collapse sheet swipe step |
sheet.stepToggle() | Toggle (open or close) sheet swipe step |
sheet.setSwipeSet() | Update step position. Required to call after content of sheet modal has been modified manually when it is opened |
sheet.destroy() | Destroy sheet |
sheet.on(event, handler) | Add event handler |
sheet.once(event, handler) | Add event handler that will be removed after it was fired |
sheet.off(event, handler) | Remove event handler |
sheet.off(event) | Remove all handlers for specified event |
sheet.emit(event, …args) | Fire event on instance |
Control Sheet With Links
It is possible to open and close required sheet (if you have them in DOM) using special classes and data attributes on links:
To open sheet we need to add “sheet-open“ class to any HTML element (prefered to link)
To close sheet we need to add “sheet-close“ class to any HTML element (prefered to link)
If you have more than one sheet in DOM, you need to specify appropriate sheet via additional data-sheet=”.my-sheet” attribute on this HTML element
According to above note:
<!-- In data-sheet attribute we specify CSS selector of sheet we need to open -->
<p><a href="#" data-sheet=".my-sheet" class="sheet-open">Open Sheet</a></p>
<!-- And somewhere in DOM -->
<div class="sheet-modal my-sheet">
<div class="sheet-modal-inner">
<!-- Link to close sheet -->
<a class="link sheet-close">Close</a>
</div>
</div>
Swipe Step
If you pass swipeToStep
parameter, then sheet will be opened partially, and with swipe it can be further expanded. To make it work, we also need to define that first/initial step in sheet HTML, so Framework7 can know on how much Sheet should be opened.
To make it work, we need to wrap initial Sheet content with <div class="sheet-modal-swipe-step">
element, and set height:auto
on that Sheet modal:
<div class="sheet-modal" style="height: auto">
<div class="sheet-modal-inner">
<!-- initial sheet modal content -->
<div class="sheet-modal-swipe-step">
...
</div>
<!-- rest of the content that will be opened with extra swipe -->
...
</div>
</div>
For top-positioned Sheet modal, this swipe step should be at the bottom:
<div class="sheet-modal sheet-modal-top" style="height: auto">
<div class="sheet-modal-inner">
<!-- rest of the content that will be opened with extra swipe -->
...
<!-- initial sheet modal content -->
<div class="sheet-modal-swipe-step">
...
</div>
</div>
</div>
Sheet Events
Sheet will fire the following DOM events on sheet element and events on app and sheet instance:
DOM Events
Event | Target | Description |
---|---|---|
sheet:open | Sheet Element<div class=”sheet”> | Event will be triggered when Sheet starts its opening animation |
sheet:opened | Sheet Element<div class=”sheet”> | Event will be triggered after Sheet completes its opening animation |
sheet:close | Sheet Element<div class=”sheet”> | Event will be triggered when Sheet starts its closing animation |
sheet:closed | Sheet Element<div class=”sheet”> | Event will be triggered after Sheet completes its closing animation |
sheet:stepopen | Sheet Element<div class=”sheet”> | Event will be triggered on Sheet swipe step open/expand |
sheet:stepclose | Sheet Element<div class=”sheet”> | Event will be triggered on Sheet swipe step close/collapse |
sheet:stepprogress | Sheet Element<div class=”sheet”> | Event will be triggered on Sheet swipe step between step opened and closed state. As event.detail it receives step open progress number (from 0 to 1 ) |
App and Sheet Instance Events
Sheet instance emits events on both self instance and app instance. App instance events has same names prefixed with popup
.
Event | Arguments | Target | Description |
---|---|---|---|
open | sheet | sheet | Event will be triggered when Sheet starts its opening animation. As an argument event handler receives sheet instance |
sheetOpen | sheet | app | |
opened | sheet | sheet | Event will be triggered after Sheet completes its opening animation. As an argument event handler receives sheet instance |
sheetOpened | sheet | app | |
close | sheet | sheet | Event will be triggered when Sheet starts its closing animation. As an argument event handler receives sheet instance |
sheetClose | sheet | app | |
closed | sheet | sheet | Event will be triggered after Sheet completes its closing animation. As an argument event handler receives sheet instance |
sheetClosed | sheet | app | |
beforeDestroy | sheet | sheet | Event will be triggered right before Sheet instance will be destroyed. As an argument event handler receives sheet instance |
sheetBeforeDestroy | sheet | app | |
stepOpen | sheet | sheet | Event will be triggered on Sheet swipe step open/expand |
sheetStepOpen | sheet | app | |
stepClose | sheet | sheet | Event will be triggered on Sheet swipe step close/collapse |
sheetStepClose | sheet | app | |
stepProgress | sheet,progress | sheet | Event will be triggered on Sheet swipe step between step opened and closed state. As progress it receives step open progress number (from 0 to 1 ) |
sheetStepProgress | sheet,progress | app |
CSS Variables
Below is the list of related CSS variables (CSS custom properties).
:root {
--f7-sheet-height: 260px;
--f7-sheet-border-color: transparent;
--f7-sheet-transition-duration: 300ms;
--f7-sheet-push-border-radius: 10px;
--f7-sheet-push-offset: var(--f7-safe-area-top);
--f7-sheet-bg-color: #fff;
}
:root .theme-dark,
:root.theme-dark {
--f7-sheet-bg-color: #202020;
}
.ios {
--f7-sheet-border-color: var(--f7-bars-border-color);
}
Examples
<body>
...
<div class="page">
<div class="navbar">
<div class="navbar-bg"></div>
<div class="navbar-inner">
<!-- In data-sheet attribute we specify CSS selector of sheet we need to open-->
<div class="title">Sheet Modal</div>
<div class="right"><a class="link sheet-open" href="#" data-sheet=".my-sheet">Open Sheet</a></div>
</div>
</div>
<div class="page-content">
<div class="block">
<!-- In data-sheet attribute we specify CSS selector of sheet we need to open-->
<p><a class="button sheet-open" href="#" data-sheet=".my-sheet">Open Sheet</a></p>
<!-- Button to close sheet-->
<p><a class="button sheet-close" href="#" data-sheet=".my-sheet">Close Sheet</a></p>
<p><a class="button dynamic-sheet" href="#">Create Dynamic Sheet</a></p>
<!-- Button to open another top sheet-->
<p><a class="button sheet-open" href="#" data-sheet=".my-sheet-top">Open Top Sheet</a></p>
<!-- Button to open swipe-to-close sheet-->
<p><a class="button sheet-open" href="#" data-sheet=".my-sheet-swipe-to-close">Swipe To Close</a></p>
<!-- Button to open swipe-to-step sheet-->
<p><a class="button sheet-open" href="#" data-sheet=".my-sheet-swipe-to-step">Swipe To Step</a></p>
<!-- Button to open sheet push -->
<p><a class="button sheet-open" href="#" data-sheet=".my-sheet-push">Sheet Push</a></p>
</div>
</div>
</div>
...
<!-- Default bottom sheet -->
<div class="sheet-modal my-sheet">
<div class="toolbar">
<div class="toolbar-inner">
<div class="left"></div>
<div class="right"><a class="link sheet-close" href="#">Done</a></div>
</div>
</div>
<div class="sheet-modal-inner">
<div class="block">
<h4>Info</h4>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque ac diam ac quam euismod porta vel a nunc. Quisque sodales scelerisque est, at porta justo cursus ac.</p>
</div>
</div>
</div>
<!-- Top sheet -->
<div class="sheet-modal sheet-modal-top my-sheet-top">
<div class="toolbar toolbar-bottom">
<div class="toolbar-inner">
<div class="left"></div>
<div class="right"><a class="link sheet-close" href="#">Done</a></div>
</div>
</div>
<div class="sheet-modal-inner">
<div class="block">
<h4>Info</h4>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque ac diam ac quam euismod porta vel a nunc. Quisque sodales scelerisque est, at porta justo cursus ac.</p>
</div>
</div>
</div>
<!-- Swipe to close sheet -->
<div class="sheet-modal my-sheet-swipe-to-close" style="height:auto; --f7-sheet-bg-color: #fff;">
<div class="sheet-modal-inner">
<div class="page-content">
<div class="block-title block-title-large">Hello!</div>
<div class="block">
<p><b>Swipe me down to close</b></p>
<p>Eaque maiores ducimus, impedit unde culpa qui...</p>
</div>
</div>
</div>
</div>
<!-- Swipe to step sheet -->
<div class="sheet-modal my-sheet-swipe-to-step" style="height:auto; --f7-sheet-bg-color: #fff;">
<div class="sheet-modal-inner">
<div class="sheet-modal-swipe-step">
<div class="display-flex padding justify-content-space-between align-items-center">
<div style="font-size: 18px"><b>Total:</b></div>
<div style="font-size: 22px"><b>$500</b></div>
</div>
<div class="padding-horizontal padding-bottom">
<a class="button button-large button-fill">Make Payment</a>
<div class="margin-top text-align-center">Swipe up for more details</div>
</div>
</div>
<div class="block-title block-title-medium margin-top">Your order:</div>
<div class="list no-hairlines">
<ul>
<li class="item-content">
<div class="item-inner">
<div class="item-title">Item 1</div>
<div class="item-after text-color-black"><b>$200</b></div>
</div>
</li>
<li class="item-content">
<div class="item-inner">
<div class="item-title">Item 2</div>
<div class="item-after text-color-black"><b>$180</b></div>
</div>
</li>
<li class="item-content">
<div class="item-inner">
<div class="item-title">Delivery</div>
<div class="item-after text-color-black"><b>$120</b></div>
</div>
</li>
</ul>
</div>
</div>
</div>
<!-- Sheet Push -->
<div class="sheet-modal sheet-modal-push my-sheet-push">
<div class="toolbar">
<div class="toolbar-inner">
<div class="left"></div>
<div class="right">
<a class="link sheet-close">Close</a>
</div>
</div>
</div>
<div class="sheet-modal-inner">
<div class="page-content">
<div class="block">
<p>Lorem ipsum dolor sit amet....</p>
</div>
</div>
</div>
</div>
</body>
var app = new Framework7();
var $$ = Dom7;
// DOM events for my-sheet sheet
$$('.my-sheet').on('sheet:open', function (e) {
console.log('my-sheet open');
});
$$('.my-sheet').on('sheet:opened', function (e) {
console.log('my-sheet opened');
});
// Create dynamic Sheet
var dynamicSheet = app.sheet.create({
content: '<div class="sheet-modal">'+
'<div class="toolbar">'+
'<div class="toolbar-inner">'+
'<div class="left"></div>'+
'<div class="right">'+
'<a class="link sheet-close">Done</a>'+
'</div>'+
'</div>'+
'</div>'+
'<div class="sheet-modal-inner">'+
'<div class="block">'+
'<p>Sheet created dynamically.</p>'+
'<p><a href="#" class="link sheet-close">Close me</a></p>'+
'</div>'+
'</div>'+
'</div>',
// Events
on: {
open: function (sheet) {
console.log('Sheet open');
},
opened: function (sheet) {
console.log('Sheet opened');
},
}
});
// Events also can be assigned on instance later
dynamicSheet.on('close', function (sheet) {
console.log('Sheet close');
});
dynamicSheet.on('closed', function (sheet) {
console.log('Sheet closed');
});
// Open dynamic sheet
$$('.dynamic-sheet').on('click', function () {
// Close inline sheet before
app.sheet.close('.my-sheet');
// Open dynamic sheet
dynamicSheet.open();
});
// Create swipe-to-close Sheet
app.sheet.create({
el: '.my-sheet-swipe-to-close',
swipeToClose: true,
backdrop: true,
});
// Create swipe-to-step Sheet
app.sheet.create({
el: '.my-sheet-swipe-to-step',
swipeToClose: true,
swipeToStep: true,
backdrop: true,
});