Lesson 18 - Bootstrap - Modal dialogs
In the previous lesson, Bootstrap - Pagination, Alerts, and Breadcrumbs, we continued with Bootstrap and introduced several new components. In today's Bootstrap CSS framework tutorial, we'll continue in the same manners. We'll talk about modal dialogs.
Although pop-ups don't really go along with websites, sometimes we don't have
other choice. It's e.g. when we want to make sure if the user really wants to
close a tab because they have unsaved work there. For this purpose we could use
native JavaScript dialogs (confirm()
, prompt()
,
alert()
) but those don't look exactly great and it's not possible
to customize them. Pop-ups are also often used for e.g. opening the full-size
image or a video to prevent unnecessary redirects to other pages. You may know
this as lightbox.
Modal dialogs in Bootstrap
We create modal dialogs via JavaScript, so again, we have to load Bootstrap's JavaScript plugin first.
Example
As the first example let's place a button into the page which, when clicked, will cause a modal dialog to open.
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#dialog"> Open modal </button> <div class="modal fade" id="dialog" tabindex="-1" role="dialog" aria-labelledby="dialog-label" aria-hidden="true"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="dialog-label">Title</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> Text </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> </div> </div> </div> </div>
In practice, we're going to open modals rather in JavaScript, unlike the vast
majority of components. In the example above the dialog is opened via the
<button>
element and the data-toggle="modal"
data attribute. Using the data-target
attribute we'll specify a
selector to the modal which should be opened by the button. The result in the
browser:
To create modals we first place a semi-transparent gray layer over the page
as a <div>
element with the .modal
class. To
achieve an animation effect we assign the .fade
class as well; if
we didn't want to play the animation for some reason, we just wouldn't assign
this class. To eliminate the possibility of selecting the layer by
tab, we also assign the tabindex="-1"
attribute. And
finally, to support screen readers, we also add attributes
role="dialog"
, aria-labelledby="dialog-label"
, and
aria-hidden="true"
. We then place the modal itself as another
<div>
with the .modal-dialog
class. We'll divide
it into divs with classes .modal-header
, .modal-body
,
and .modal-footer
. It's worth noticing the cross icon placed in the
header for closing the modal.
We can put any HTML content, including forms, inside modals. However be careful; don't use modals for advertisement which pops up immediately after the page is opened, Google penalizes such websites.
When a pop-up is displayed, the .modal-open
class is applied to
the <body>
element, removing the scrollbars. We can then
scroll through the pop-up content if it doesn't fit in the page instead of
scrolling through the page itself. Bootstrap modals can be closed by clicking
outside of them. We can display only a single modal at a time. Since modals are
rendered with fixed position, we should place the contents of the modal above
the page's content to prevent covering the contents of the modal by some part of
the page content. The autofocus
attribute won't work in modal
dialogs. If we placed a form inside a modal and wanted to use this attribute,
we'd have to use JavaScript:
$('#dialog').on('shown.bs.modal', function () { $('#form-name').trigger('focus'); });
As mentioned before, we can place basically anything inside modals, including popovers and a grid, see further in this course.
Prefilled content
We can prefill modal dialogs or even change their contents slightly, depending on the event which caused them to open. Like this, we can use a single modal for multiple similar purposes.
In the example below we fill an input with text depending on which button has been clicked:
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#dialog" data-type="feature">Request a new feature</button> <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#dialog" data-type="bug">Report a bug</button> <div class="modal fade" id="dialog" tabindex="-1" role="dialog" aria-labelledby="dialog-label" aria-hidden="true"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="dialog-label">System development</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> <form> <div class="form-group"> <label for="request-type" class="col-form-label">Request type</label> <input type="text" class="form-control" id="request-type"> </div> <div class="form-group"> <label for="request-text" class="col-form-label">Text</label> <textarea class="form-control" id="request-text"></textarea> </div> </form> </div> <div class="modal-footer"> <button type="button" class="btn btn-primary">Send</button> <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> </div> </div> </div> </div>
We'll use JavaScript to prefill the modal:
$('#dialog').on('show.bs.modal', function (event) { var button = $(event.relatedTarget); // Get the button which opened the modal var recipient = button.data('type'); // Load information from its data attribute $(this).find('.modal-body input').val(recipient); // Assign the value to the input });
In JavaScript we could, of course, edit any part of the modal, load something
via AJAX and such. The key is to handle the show.bs.modal
event.
The result in the browser:
Modal height
Modals are centered according to their height which is calculated when
rendered. If we edited a model's content dynamically somehow, it's possible to
reposition it by calling
$('#dialog').data('bs.modal').handleUpdate();
or
$('#dialog').modal('handleUpdate');
.
Sizes
Even modals can be rendered in several sizes by assigning a class to the
<div>
element with the .modal-dialog
class,
meaning the second nested <div>
.
.modal-lg
- A large modal- No class for the standard size
.modal-sm
- A small modal
JavaScript
As said before, JavaScript will be your good friend when working with modals. Except for displaying modals by buttons with data attributes, we can also display a modal from JavaScript like this:
$('#dialog').modal();
Properties
We can change the behavior of modals using data attributes with the
data-
prefix or the following JavaScript properties. We can pass an
object with these properties to the modal()
method above as
parameter.
backdrop
- Thetrue
value causes covering the page with a semi-transparent gray background. Thestatic
value additionally forbids the modal to be closed by clicking on this background. Thefalse
value won't display this layer at all.keyboard
- Depending on the values oftrue
orfalse
, the modal will (or won't) close after pressing the esc key.focus
- Focuses the dialog when opened,true
by default.show
- Specifies whether the dialog should show once initialized,true
by default.
Methods
All the methods are called asynchronously and pass the control flow before the animation (transition) finishes. If a method is called on a modal which transition is in progress, this method call will be ignored.
We can call the modal()
method with the following
parameters:
settings
- An object with the properties set as described above. We pass it e.g. like this:$('#dialog').modal({ keyboard: false })
."toggle"
- Shows/closes the modal and passes the control flow before actually displaying/hiding it."show"
- Shows the modal and passes the control flow before actually displaying it."hide"
- Closes the modal and passes the control flow before actually hiding it."handleUpdate"
- Repositions the modal based on its height. We call it when its the height changed."dispose"
- Disposes the modal.
Events
show.bs.modal
- Is called when the modal is opened but before it actually opens because an animation can still be in progress. If the modal is opened using a button, we can find this element in therelatedTarget
property of this event.shown.bs.modal
- Is called when the modal is shown, once the animation finishes. If the modal is opened using a button, we can find this element in therelatedTarget
property of this event.hide.bs.modal
- Is called when the modal is closed but before it actually disappears.hidden.bs.modal
- Is called when the closed dialog isn't visible anymore.
Handling the event can look like this:
$('#dialog').on('hidden.bs.modal', function (e) { // some reaction on the event... })
In the next lesson, Bootstrap - Popovers, we'll focus on the Popover components.