Skip to content

Instantly share code, notes, and snippets.

@martialboniou
Last active March 1, 2021 22:44
Show Gist options
  • Save martialboniou/202913a4466a634f3fc5798458c2b082 to your computer and use it in GitHub Desktop.
Save martialboniou/202913a4466a634f3fc5798458c2b082 to your computer and use it in GitHub Desktop.
Bootstrap 4/5 tutorial

BOOTSTRAP DIGEST

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.

Bootstrap basics

  • 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.
  • 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 (try class="w-100 d-xl-none" to break except in extra large devices);

  • typography:

    • <h1 class="display-{1,2,3,4}">: larger font-size & lighter font-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 for thead (.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 a readonly 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 like custom-{switch,checkbox,radio,select,range};
  • .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">.
  • 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 the display: 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 use align-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 use nav-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 with data-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 add padding: 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.

Example of page with grids

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]
Loading

Bootstrap advanced

Modals

  • 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 the data-dismiss="modal" attribute to a .close or a Cancel button; add the data-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;
        });
    });

Dropdown menus

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

Tabs

  • use .nav-{tabs,pills} in a .navand a data-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
    });

Tooltips

  • 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>'
    });

Popovers

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

Alerts

  • simple warning: .alert-warning in a .warning div; add a mandatory data-dismiss="alert" attribute on the .close button; IMPORTANT: .alert-dismissible ensures the close button is well positioned;

Buttons

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

Toast

  • 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">
        {...}

Scrollspy

  • 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.
  • example of event:

    $("#myNavbar").on("activate.bs.scrollspy", function(){
        var currentItem = $(".nav li.active > a").text();
        $("#info").empty().html("Currently you are viewing - " + currentItem);
    });

Typeahead

IMPORTANT: deprecated since BS4, use the twitter typeahead.

Bootstrap 5 changes

  • data-{toggle,target} is data-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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment