NOTE: As much as I can I will try to do the bootstrap 4 tutorial and learn BS5. The demos in the root of this directory are BS5; the subdirectory BS4 contains the demos from tutorialrepublic for the stable but soon deprecated BS4
Please install Github Mermaid extension for Firefox/Chrome to display the diagrams in this document.
-
Always include the viewport
meta
tag inside the<head>
section to enable touch zooming and ensure proper rendering on mobile devices; -
In grid layout, content must be placed inside columns
.col
and.col-*
and only columns may be the immediate children or rows.row
. These last ones should be placed inside a.container
(or.container-fluid
(full-width));<div class="container"> <!-- Row with two equal columns --> <div class="row"> <div class="col-md-6">Column left</div> <div class="col-md-6">Column right</div> </div> <!-- Row with two columns divided in 1:2 ratio --> <div class="row"> <div class="col-md-4">Column left</div> <div class="col-md-8">Column right</div> </div> <!-- Row with two columns divided in 1:3 ratio --> <div class="row"> <div class="col-md-3">Column left</div> <div class="col-md-9">Column right</div> </div> </div>
-
the sum of the columns' number from the end of their class is 12 by default (everything beyond 12 will be wrapped); if you set
col
, it will balance automatically the column; you can mix static and automatic columns; you can create a flexible layout that changes the column orientation based on the viewport size:<div class="container"> <!-- large device: 1:2:1 ratio; medium device: 1:2 ratio then 3rd column wrapped on a second row --> <div class="row"> <div class="col-md-4 col-lg-3">Column one</div> <div class="col-md-8 col-lg-6">Column one</div> <div class="col-md-12 col-lg-3">Column one</div> </div> </div>
-
the grid columns are also nestable that means you can put rows and columns inside an existing column (the sum of column numbers should be equal to 12 or less within a single row);
-
alignment of grid: you can use the flexbox alignment utilities:
- vertically:
.align-items-{start,center,end}
in the row or.align-self-{start,center,end}
in an individual column; - horizontally:
.justify-content-{start,center,end}
in the row.
- vertically:
-
reordering of grid columns:
.order-{first,last,1..12}
; -
offseting the grid columns:
.offset{-sm,-md,-lg,-xl}-*
; there's also the margin utility classes{ml,mr}{-sm,-md,-lg,-xl}-auto
in the situations where the width of the offset is not fixed (NOTE:ml
offsets to the right); -
compact columns:
.no-gutters
; -
break columns to a newline: insert a
.w-100
div where you want to break (tryclass="w-100 d-xl-none"
to break except in extra large devices); -
typography:
-
<h1 class="display-{1,2,3,4}">
: largerfont-size
& lighterfont-weight
; -
<p class="lead">
: stand-out paragraph; -
<p class="text-{sm-,md-,lg-,xl-}{left,center,right,justify}">
: text alignment; -
<p class="text-{lowercase,uppercase,capitalize}">
: text transformation; -
<p class="text-{primary,secondary,success,info,warning,danger,muted}">
: emphasis utility classes, muted is faded; -
.blockquote
example:<blockquote class="blockquote"> <p class="mb-0">You're doing it completely wrong!</p> <footer class="blockquote-footer">by <cite>John McCarthy</cite></footer> </blockquote>
-
-
<table class="table{-responsive{-sm,...}} {table-striped,table-dark,table-bordered,table-borderless,table-hover}">
: table w/ classes (you also have some classes forthead
(.thead-light
) &tr
(.table-{primary,...}
); -
.list-unstyled
,.list-inline
,.list-group
: list classes; -
.form-group
/.form-row
(in a form-surrounded div) or.form-inline
as a form class:- you must use
.form-control
for your input, textarea and select; - to create horizontal form layouts, you add the class
.row
on form groups and use the.col-*-*
grid classes to specify the width of your labels & controls; IMPORTANT: apply.col-form-label
on the label elements in this case (check the example); .form-inline
case as a form class: always include a label otherwise screen readers will have trouble with your forms and use.sr-only
labels to hide the labels;- replace
.form-control
by.form-control-plaintext
when an input has areadonly
attribute; - use
.d-block
for label to create vertically stacked checkboxes (don't use it for inline checkboxes); - the attribute
disabled
disables individual form controls; use it in a surrounding fieldset to disable a set of form controls; - column sizing of form elements with a
.form-row
form-surrounded div; <form class="needs-validation" novalidate>
adds form validation styles via CSS:invalid
and:valid
pseudo-classes; you can use an originally hidden message with a<div class="invalid-feedback">
below each input, textarea and select;- custom form controls exist: check
.custom-control{...}
(you must add.custom-control-{input,label}
to ensure the good formating of inputs and labels; there are severals well-written classes likecustom-{switch,checkbox,radio,select,range}
;
- you must use
-
.input-group
: add surrounding divs with the class.input-group-{prepend,append}
according to the position, then create a<span class="input-group-text">
(you can place radio button or checkbox inside; also button dropdown w/o the normally required.dropdown
); -
images & video: add
.img-fluid
to<img>
to create a responsive image; add a surrounding div with.embed-responsive
class to embed videos:<div class="embed-responsive embed-responsive-16by9"> <iframe class="embed-responsive-item" src="<my video link>"></iframe> </div>
-
image alignment with:
- float class:
<img src="<my image>" class="pull-{left,right}">
; - text alignement classes:
<div class="box text-{left,right,center}"><img{...}>
; - auto margin for center alignment:
<div class="box"><img src="<my image>" class="d-block mx-auto">
.
- float class:
-
IMPORTANT:
.card
/.card-{group,deck,columns}
; use.card-{header,footer,body,title,text}
for inner divs' classes (they can be mixed); you can use.card-img-overlay
instead of.card-body
;.card-group
uses thedisplay: flex;
CSS to achieve their uniform sizing;.card-columns
(inside a<div class="row">
in a container) are built with CSS column properties instead of flexbox for easier alignement; you can create horizontal cards using a combination of grid and utility classes:<div class="card"> <div class="row no-gutters"> <div class="col-sm-5"> {...} </div> <div class="col-sm-7"> <div class="card-body"> {...} </div> </div> </div> </div>
-
clickable card: add
.stretched-link
to a link inside the card; -
.media
: use.media-body
(like cards...); media objects can be nested (.media
inside a.media
); you can usealign-self-{center,end}
for your media (default is top); create a media list (.list-unstyled
) by using.media
on the child<li>
elements; -
icons: no icons in BS4 (BS3 had Glyphicons) but you can use the popular & highly compatible Font Awesome icon library (
.fa
in the examples here). IMPORTANT: leave a space after the closing tag of icon element to ensure proper spacing between the icon and the text; -
.nav
: you can add.add-{tabs,pills}
to create a tabbed or pill-based navigation; you can usenav-fill
or.nav-justified
to manage the layout; nav children have.nav-item
and.nav-link
; you need.dropdown
,.dropdown-toggle
,.dropdown-{menu,item}
to add a dropdown menu in a tabbed or pill-based nav:<nav class="nav nav-tabs"> <div class="nav-item dropdown"> <a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown">Messages</a> <div class="dropdown-menu"> <a href="#" class="dropdown-item">Inbox</a> <a href="#" class="dropdown-item">Sent</a> </div> </div> </nav>
-
.navbar
for<nav>
: create a responsive navigation header; it collapses on small viewports and expands when user clicks the toggle button; use a.navbar-toggler
button withdata-toggle=collapse
&data-target="#{my-navbar-collapse}"
attributes then create a<div class="collapse navbar-collapse" id="{my-navbar-collapse}><div class="navbar-nav"></div>{main nav-links}<div class="navbar-nav ml-auto">{special right nav-link, say, login}</div>
;.fixed-{top,bottom}
or.sticky-top
are very useful for a<nav>
(CHECK THIS: place the fixed.navbar
content inside the.container{-fluid}
for proper padding and alignment with the rest of the content and, remember to addpadding: 70{+}px;
to the top or botton of the<body>
to prevent the content to go underneath the navbar); -
.breadcrumb
in<ol>
: also add.breadcrumb-item
in the<li>
children; -
.pagination
in<ul>
: also add.page-item
in the<li>
children (and.page-link
in the inner<a>
s); -
badges: create a badge like this
<span class="badge {badge-pill} badge-{primary....}">
; -
progress bar: use
<div class="progress"><div class="progress-bar" style="min-width: 20px;">
and manage the size with `style="witdth: {x}%" or JS:var i=0; function makeProgress(){ if (i < 100) { i+=1; let inc=i+"%"; $(".progress-bar").css(inc).text(inc); } setTimeout("makeProgress()", 100); } makeProgress();
-
spinners: use
.spinner-{border,grow}
and resize with.spinner-border-{sm,lg...}
:<div class="spinner-border"> <span class="sr-only">Loading...</span> </div>
-
REMINDER: the display classes:
.d-none
: hide;- `.d-{inline,block,inline-block}: force an element to generate a box;
.d-{table,table-row,table-cell}
: force an element to behave like a<table>
,<tr>
or<td>
;.d-{inline-}flex
: force an element to generate a block or inline-level flex container box; s.d-print{...}
instead of.d
: print variant of the display classes.
-
special classes:
.close
: generic close icon for dismissing content like modals and alerts;.overflow-auto
: provide scrollbars to view overflowed content of an element if required;.overflow-hidden
: hide overflowed content of an element;- IMPORTANT:
.stretched-link
: make an element clickable by stretching a nested link; .{in}visible
: make an element (in)visible;.sr-only
: hide an element to all but screen readers;.text-hide
: replace an element's text content with a background image.
Install Github Mermaid extension for Firefox/Chrome to display the diagram:
graph TD
A[body]
A --> B[nav]
B --> C[.container]
C --> Brand[.navbar-brand]
C --> NavToggler[.navbar-toggler]
C --> NavbarCollapse(.navbar-collapse)
NavbarCollapse --> Navbars(.navbar .ms-auto)
A --> D[.container]
D --> H[.header]
D --> R1[.row]
R1 --> C11[.col-4]
R1 --> C12[.col-4]
R1 --> C13[.col-4]
D --> Sep[hr]
Sep --> F[footer]
F --> R2[.row]
R2 --> C21[.col-6]
R2 --> C22[.col-6 .text-end]
C21 --> Copyright[#copyright]
C22 --> Terms[#terms]
C22 --> Privacy[#privacy]
-
use a
.modal
hierarchy of divs:.modal-dialog
then.modal-content
then.modal-{header,body,footer}
(use.modal-title
in a header is a good practice); IMPORTANT: add thedata-dismiss="modal"
attribute to a.close
or a Cancel button; add thedata-toggle="modal" data-target="#MyModal"
attribute to a button to display a specific faded.modal
; -
example of usage of a modal event to change the title:
$(document).ready(function(){ $("#MyModal").on("show.bs.modal", function(event){ var button = $(event.relatedTarget); var titleData = button.data("title"); //the button MUST have a data-title attr $(this).find(".modal-title").text(titleData); }); });
-
example of jQuery
load()
method to load the content of a modal remotely:$(document).ready(function(){ $("#MyModal").on("show.bs.modal", function(event){ $(this).find(".modal-body").load("remote.php"); }); });
-
vertically centered: use
.modal-dialog-centered
in a.modal-dialog
; -
options (boolean or static string in the backdrop case):
data-backdrop="static"
;- `data-focus="false";
- `data-show="false";
- `data-keyboard="false";
-
change options for modals using JS and the
modal(options)
function:$(".launch-modal").click(function(){ $("#myModal").modal({ backdrop: 'static'; keyboard: false; }); });
-
by example in a
.navbar
(instead of a<div>
); it works the same for a.nav
or a<button type="button" class="btn">
(you also can use a container for these buttons<div class="btn-group drop{up,left,right}">
):<nav class="navbar navbar-expand-md> <a href="#" class="navbar-brand">Brand</a> <button type="button" class="navbar-toggler" data-toggle="collapse" data-target="#navbarCollapse"> <span class="navbar-toggler-icon"></span> </button> <div id="navbarCollapse" class="collapse navbar-collapse"> <ul class="nav navbar-nav> <!-- dropdown inside the li.nav-item --> <li class="nav-item dropdown"> <a href="#" class="nav-link dropdown-toggle" data-toggle="dropdown">Messages</a> <div class="dropdown-menu"> <div class="dropdown-header">GMAIL</div> <a href="#" class="dropdown-item">Inbox</a> <a href="#" class="dropdown-item">Drafts</a> <a href="#" class="dropdown-item">Sent</a> <div class="dropdown-divider"></div> <a href="#" class="dropdown-item">Trash</a> <div class="dropdown-divider"></div> <div class="dropdown-header">GMX</div> <a href="#" class="dropdown-item">Inbox</a> <a href="#" class="dropdown-item disabled">Drafts</a> <a href="#" class="dropdown-item">Sent</a> <div class="dropdown-divider"></div> <a href="#" class="dropdown-item">Trash</a> </div> </li> </ul> </div> </nav>
-
.dropdown-menu-right
; -
.dropdown-header
; -
manually generated dropdown (BEWARE: it requires the
data-toggle="dropdown"
attribute):$(document).ready(function(){ $(".dropdown-toggle").dropdown(); });
-
dropdown event:
$(document).ready(function(){ $(".dropdown").on("show.bs.dropdown", function(){ var linkText = $(e.relatedTarget).text(); // get the link text alert("Click on OK button to view the dropdown menu for - " + linkText); }); });
-
use
.nav-{tabs,pills}
in a.nav
and adata-toggle="tab"
in each<a class="nav-link">
; -
create the content in a
.tab-content
as a.tab-pane
:<ul class="nav nav-tabs"> <li class="nav-item"> <a href="#home" class="nav-link active" data-toggle="tab">Home</a> </li> <li class="nav-item"> <a href="#profile" class="nav-link" data-toggle="tab">Profile</a> </li> </ul> <div class="tab-content"> <div class="tab-pane fade show active" id="home"> <h4 class="mt-2">Home tab content</h4> <p>{...}</p> </div> <div class="tab-pane fade" id="profile"> <h4 class="mt-2">Profile tab content</h4> <p>{...}</p> </div> </div>
-
dynamic tabs:
$(document).ready(function(){ $('#myTab a[href="#profile"]').click(function(e){ e.preventDefault(); $(this).tab('show'); }); });
-
events;
$(document).ready(function(){ $('a[data-toggle="tab"]').on('shown.bs.tab', function(e){ e.target {...} // active tab e.relatedTarget {...} // previous tab });
-
an example, first:
<a href="#" data-toggle="tooltip" title="Something">Text</a>
; IMPORTANT: for performance reasons, you must manually initialize the tooltip with:$(document).ready(function(){ $('[data-toggle="tooltip"]').tooltip(); });
-
positioning: use the
data-placement="{top,bottom,right,left}"
attribute or$(".tip-top").tooltip({placement: 'top'})
; -
customize with a template (
.tooltip-inner
is the content div):$("#myTooltips a").tooltip({ template: '<div class="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-head"><h3><span class="glyphicon glyphicon-info-sign"></span> Tool Info</h3></div><div class="tooltip-inner"></div></div>' });
Same as the tooltip but:
data-trigger="focus"
to ensure the other popovers are hidden when the newly focused one is shown;$('[data-toggle="popover"]').popover({trigger: 'hover'});
to trigger the popovers on mouse hover instead of click;- the inner template from the attribute
data-content
is written in the.popover-body
(not a popover-inner class as in the.tooltip-inner
);
- simple warning:
.alert-warning
in a.warning
div; add a mandatorydata-dismiss="alert"
attribute on the.close
button; IMPORTANT:.alert-dismissible
ensures the close button is well positioned;
<button type="button" class="btn btn-primary" data-toggle="button" autocomplete="off">Text</button>
: IMPORTANT:autocomplete="off"
is here for a Firefox potential persistency issue;- button {radio,checkboxes}: add the attribute
data-toggle="buttons"
to a.btn-group
of<input type="{radio,checkbox}">
; $("#myButton").click(function(){$(this).button('toggle');});
transforms a button into an active button;
-
use the
.toast
as a container and.toast-{header,body}
as a content; -
REMINDER: don't forget the
data-dismiss="toast"
for the close button (similar to.modal
or.alert
); -
trigger with a
toast('show')
function; -
IMPORTANT: place them in the top right/middle side:
<div style="position: relative; min-height: 300px;"> <div style="position: absolute; top: 0; right: 0;"> <div class="toast fade show"> {...}
-
the Bootstrap scrollspy plugin requires the use of a
<nav>
component (like.navbar
, tabs or pills) for proper highlighting of active links; -
normal flow:
- the
data-spy="scroll"
attribute is in a<body>
; - the
data-target="#MyNavbar"
attribute (also in<body>
) aims the<nav>
; - the optional
data-offset
attribute specifies the number of pixels to offset from top when calculating the position of scroll.
- the
-
example of event:
$("#myNavbar").on("activate.bs.scrollspy", function(){ var currentItem = $(".nav li.active > a").text(); $("#info").empty().html("Currently you are viewing - " + currentItem); });
IMPORTANT: deprecated since BS4, use the twitter typeahead.
data-{toggle,target}
isdata-bs-{toggle,target}
now;- BEWARE:
.m{l,r}-auto
in LTR is.m{s,e}-auto
now (start-end is better than the static left-right); .text-md-{left,right}
is.text-md-{start,end}
now;- no
.jumbotron
.
Digest by Martial BONIOU, 2021