Font Face
Teva Sans Latin

Drafts & Templates
PBS Templates

Primitives & components context

Primitives & components: Teva Global

Modal

v0.0.0

The Modal augments the Bootstrap Modal. The Modal will be appended to the body element when opened.

Add the class .vi-modal to the dialog wrapper and only use .modal-body.

Never use .modal-header or .modal-footer. The design requires more fine grained control over the layout. To have full control over the layout inside .modal-body the Modal Layout is used.

The Modal is basically a restyled version of the Bootstrap Modal. For al options please visit their website.

<!-- .d-block, .position-static and .show classes to display a static modal example -->
<!-- Modal  -->
<div class="modal fade d-block position-static show vi-modal" role="dialog" tabindex="-1">
  <div class="modal-dialog" role="document">
    <div class="modal-content">
      <div class="modal-body">
        <!-- Modal Layout  -->
        <div class="vi-modal-layout">
          <div class="vi-modal-layout__body">
            <div class="vi-modal-layout__section vi-modal-layout__section--header-close">
              <div class="vi-modal-layout__header vi-typesystem vi-typesystem--collapse-last">
                <h3>8-bit readymade tousled.</h3>
              </div>
            </div>
            <div class="vi-modal-layout__section">
              <!-- Content of modal -->
              <div class="vi-typesystem">
                <p>Echo kogi pinterest flexitarian literally celiac biodiesel distillery. Raw denim vhs iphone flexitarian wolf. Small batch celiac fashion axe sartorial everyday.</p>
              </div>
              <div class="text-center">
                <!-- Button type: solid  -->
                <button data-dismiss="modal" type="button" class="vi-btn-solid vi-btn-solid--lg vi-btn-solid--accent-2 vi-btn">Schlitz lumbersexual</button>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

Live Demo #

Toggle a working modal demo by clicking the button below. It will slide down and fade in from the top of the page.

<!-- Button type: solid  -->
<button data-toggle="modal" data-target="#sg-cc189e" type="button" class="vi-btn-solid vi-btn">Launch text content</button>
<!-- Modal  -->
<div class="modal fade vi-modal" id="sg-cc189e" role="dialog" tabindex="-1">
  <div class="modal-dialog modal-dialog-centered" role="document">
    <div class="modal-content">
      <div class="modal-body">
        <!-- Modal Layout  -->
        <div class="vi-modal-layout">
          <div class="vi-modal-layout__body">
            <div class="vi-modal-layout__section vi-modal-layout__section--header-close">
              <div class="vi-modal-layout__header vi-typesystem vi-typesystem--collapse-last">
                <h3>Gentrify migas scenester.</h3>
              </div>
            </div>
            <div class="vi-modal-layout__section">
              <!-- Content of modal -->
              <div class="vi-typesystem">
                <p>Farm-to-table you probably haven't heard of them cold-pressed pickled sartorial pug. Meditation master portland. Irony vhs you probably haven't heard of them hella next level venmo. Chartreuse cliche try-hard truffaut cardigan blue bottle selvage. Sustainable raw denim muggle magic beard.</p>
              </div>
              <div class="text-center">
                <!-- Button type: solid  -->
                <button data-dismiss="modal" type="button" class="vi-btn-solid vi-btn-solid--lg vi-btn-solid--accent-2 vi-btn">Artisan williamsburg</button>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>
<!-- Button type: solid  -->
<button data-toggle="modal" data-target="#sg-9b8ee6" type="button" class="vi-btn-solid vi-btn">Launch video content</button>
<!-- Modal  -->
<div class="modal fade vi-modal" id="sg-9b8ee6" role="dialog" tabindex="-1">
  <div class="modal-dialog modal-dialog-centered modal-lg" role="document">
    <div class="modal-content">
      <div class="modal-body">
        <!-- Modal Layout (mods: --compact) -->
        <div class="vi-modal-layout vi-modal-layout--compact">
          <div class="vi-modal-layout__body">
            <div class="vi-modal-layout__section vi-modal-layout__section--header-close">
              <div class="vi-modal-layout__header vi-typesystem vi-typesystem--collapse-last">
                <p>Retro pbr&amp;b fixie.</p>
              </div>
              <div class="vi-modal-layout__close">
                <!-- Button type: close  -->
                <button aria-label="Message dialog - click to close or navigate to the message content" data-dismiss="modal" type="button" class="vi-btn-close vi-btn-close--accent-1 vi-btn"><span class="vi-btn-close__label vi-btn__label">Close</span></button>
              </div>
            </div>
          </div>
        </div>
        <!-- Modal Layout (mods: --visual) -->
        <div class="vi-modal-layout vi-modal-layout--visual">
          <div class="vi-modal-layout__body">
            <div class="vi-modal-layout__section vi-modal-layout__section--video">
              <iframe allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen="" frameborder="0" src="https://www.youtube.com/embed/672TY8K2PKk"></iframe>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>
<!-- Button type: solid  -->
<button data-toggle="modal" data-target="#sg-97a1e6" type="button" class="vi-btn-solid vi-btn">Launch modal with scrollpane</button>
<!-- Modal  -->
<div class="modal fade vi-modal" id="sg-97a1e6" role="dialog" tabindex="-1">
  <div class="modal-dialog modal-dialog-centered" role="document">
    <div class="modal-content">
      <div class="modal-body">
        <!-- Modal Layout  -->
        <div class="vi-modal-layout">
          <div class="vi-modal-layout__body">
            <div class="vi-modal-layout__section vi-modal-layout__section--header-close">
              <div class="vi-modal-layout__header vi-typesystem vi-typesystem--collapse-last">
                <h3>Cliche chambray hashtag.</h3>
              </div>
            </div>
            <div class="vi-modal-layout__section">
              <!-- Content of modal -->
              <div class="mb-20" style="height: calc(var(--vh) * 25)">
                <!-- Scrollpane  -->
                <div class="vi-scrollpane">
                  <div class="vi-scrollpane__bar">
                    ...
                    ...
                    ...
                    ...
                    ...
                  </div>
                </div>
              </div>
              <div class="text-center">
                <!-- Button type: solid  -->
                <button data-dismiss="modal" id="sg-97a1e6focus-test" type="button" class="vi-btn-solid vi-btn-solid--lg vi-btn-solid--accent-2 vi-btn">Park gluten-free</button>
              </div>
            </div>
          </div>
        </div>
        <script>
          // Window on key t down, focus element with id 'focus-test'
          window.addEventListener('keydown', function(event) {
            if (event.key === 't') {
              document.getElementById('sg-97a1e6focus-test').focus();
            }
          });
        </script>
      </div>
    </div>
  </div>
</div>
<!-- Button type: solid  -->
<button data-toggle="modal" data-target="#sg-87a5a0" type="button" class="vi-btn-solid vi-btn">Launch modal without data dismiss on the button</button>
<!-- Modal  -->
<div class="modal fade vi-modal" id="sg-87a5a0" role="dialog" tabindex="-1">
  <div class="modal-dialog modal-dialog-centered" role="document">
    <div class="modal-content">
      <div class="modal-body">
        <!-- Modal Layout  -->
        <div class="vi-modal-layout">
          <div class="vi-modal-layout__body">
            <div class="vi-modal-layout__section vi-modal-layout__section--header-close">
              <div class="vi-modal-layout__header vi-typesystem vi-typesystem--collapse-last">
                <h3>Health roof fixie.</h3>
              </div>
            </div>
            <div class="vi-modal-layout__section">
              <!-- Content of modal -->
              <div class="mb-20" style="height: calc(var(--vh) * 25)">
                <!-- Scrollpane  -->
                <div class="vi-scrollpane">
                  <div class="vi-scrollpane__bar">
                    ...
                    ...
                    ...
                    ...
                    ...
                  </div>
                </div>
              </div>
              <div class="text-center">
                <!-- Button type: solid  -->
                <button id="sg-87a5a0focus-test" type="button" class="vi-btn-solid vi-btn-solid--lg vi-btn-solid--accent-2 vi-btn">Cold-pressed occupy</button>
              </div>
            </div>
          </div>
        </div>
        <script>
          // Window on key t down, focus element with id 'focus-test'
          window.addEventListener('keydown', function(event) {
            if (event.key === 't') {
              document.getElementById('sg-87a5a0focus-test').focus();
            }
          });
        </script>
      </div>
    </div>
  </div>
</div>

Scrolling long content #

When modals become too long for the user’s viewport or device, they scroll independent of the page itself. Try the demo below to see what we mean.

<!-- Button type: solid  -->
<button data-toggle="modal" data-target="#sg-e126b0" type="button" class="vi-btn-solid vi-btn">Launch demo modal</button>
<!-- Modal  -->
<div class="modal fade vi-modal" id="sg-e126b0" role="dialog" tabindex="-1">
  <div class="modal-dialog modal-dialog-centered" role="document">
    <div class="modal-content">
      <div class="modal-body">
        <!-- Modal Layout  -->
        <div class="vi-modal-layout">
          <div class="vi-modal-layout__body">
            <div class="vi-modal-layout__section vi-modal-layout__section--header-close">
              <div class="vi-modal-layout__header vi-typesystem vi-typesystem--collapse-last">
                <h3>Diy fixie typewriter.</h3>
              </div>
              <div class="vi-modal-layout__close">
                <!-- Button type: close  -->
                <button aria-label="Message dialog - click to close or navigate to the message content" data-dismiss="modal" type="button" class="vi-btn-close vi-btn-close--accent-1 vi-btn"><span class="vi-btn-close__label vi-btn__label">Close</span></button>
              </div>
            </div>
            <div class="vi-modal-layout__section">
              <!-- Content of modal -->
              <div class="vi-typesystem">
                <p>Vice poutine gluten-free. Godard cardigan you probably haven't heard of them. Ethical cornhole tattooed 8-bit irony brooklyn.</p>
                <p>Artisan vice whatever bespoke trust fund vinegar everyday. Celiac literally wayfarers gastropub quinoa thundercats shabby chic. Iphone stumptown leggings diy drinking organic echo. Gentrify thundercats pour-over ennui beard leggings shabby chic kale chips.</p>
                <p>Goth farm-to-table seitan vhs pbr&amp;b kinfolk hammock scenester. Mumblecore loko cronut chillwave. Swag keffiyeh iphone synth mixtape.</p>
                <p>Post-ironic echo flannel authentic green juice tilde messenger bag. Celiac next level small batch truffaut artisan cardigan. Portland cold-pressed put a bird on it viral. Tumblr echo umami knausgaard scenester.</p>
                <p>Venmo occupy ennui skateboard chambray scenester xoxo. Post-ironic pop-up knausgaard cronut butcher meditation chartreuse. Loko vice carry deep v swag ramps. 3 wolf moon schlitz pop-up.</p>
                <p>Direct trade selvage hammock. Xoxo disrupt kogi. Hashtag aesthetic photo booth. Art party wayfarers ugh church-key 3 wolf moon.</p>
                <p>Taxidermy 8-bit tattooed actually viral pabst 90's. Normcore pork belly bushwick brooklyn heirloom austin five dollar toast. Blog twee farm-to-table chartreuse tattooed austin. Microdosing synth cleanse mumblecore humblebrag diy street lo-fi. Echo letterpress blog leggings venmo artisan sriracha iphone.</p>
                <p>Next level carry plaid. Helvetica church-key fingerstache small batch tumblr photo booth microdosing. Small batch ugh sriracha tacos echo scenester austin flexitarian. Portland try-hard squid. Fanny pack organic phlogiston +1 lomo chia.</p>
                <p>Twee marfa hella. Portland bespoke seitan farm-to-table humblebrag. Leggings retro 3 wolf moon. Deep v brooklyn pbr&amp;b portland gastropub waistcoat bushwick.</p>
                <p>8-bit health waistcoat cleanse irony food truck occupy. Quinoa leggings try-hard xoxo fanny pack everyday flannel mlkshk. Fixie slow-carb skateboard sriracha. Crucifix ugh disrupt narwhal before they sold out pinterest.</p>
                <p>Lo-fi freegan twee 90's. Yolo stumptown humblebrag franzen roof tousled austin put a bird on it. Franzen pinterest williamsburg +1 bitters.</p>
                <p>Drinking keytar master kickstarter messenger bag cray mumblecore kogi. Lomo mlkshk salvia jean shorts artisan readymade. Salvia mlkshk yr art party portland neutra farm-to-table. Freegan actually brooklyn intelligentsia phlogiston.</p>
                <p>Brooklyn cray flannel try-hard gluten-free brunch retro. Mixtape listicle paleo salvia fingerstache chartreuse. Hashtag sustainable swag retro diy. Helvetica kogi normcore. Tousled chillwave vhs street scenester.</p>
                <p>Blue bottle godard mixtape craft beer. Kickstarter heirloom cronut sriracha iphone beard bushwick. Fanny pack tote bag forage deep v viral franzen pop-up.</p>
                <p>Intelligentsia neutra tumblr cornhole mlkshk umami photo booth. Phlogiston craft beer waistcoat street. Mumblecore street stumptown you probably haven't heard of them gastropub food truck ethical 8-bit. Cornhole wolf diy. Post-ironic mlkshk scenester try-hard flexitarian pork belly.</p>
                <p>Pickled quinoa skateboard stumptown sustainable vice distillery meggings. Narwhal williamsburg distillery keytar leggings twee park mixtape. Echo crucifix gastropub slow-carb small batch tousled selfies kogi. Squid tumblr art party gastropub fixie small batch blue bottle intelligentsia. Yr freegan kitsch food truck viral authentic photo booth.</p>
                <p>Sartorial quinoa lumbersexual. Hashtag gastropub deep v hammock. Helvetica trust fund kinfolk hammock gluten-free selvage retro.</p>
              </div>
              <div class="text-center">
                <!-- Button type: solid  -->
                <button data-dismiss="modal" type="button" class="vi-btn-solid vi-btn-solid--lg vi-btn-solid--accent-2 vi-btn">Poutine seitan</button>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>

Stylesheets #

The following stylesheets are required to display this component.


JavaScript #

The following javascripts are required to display this component.


Usage documentation #

Usage documentation can be found here.


Changelog #

Changelog

  • 09 Oct 2025 - fix(modal): Focus next focusable element when no data-dismiss attr is present
  • 09 Oct 2025 - docs(modal): Add focus button test on scrolling long content example.

Fix

  • 25 Jan 2022 - Fix regression remove console.log output.
  • 30 Nov 2022 - Fix regression caused by page-layout iOS overscroll prevention.
  • 30 Sept 2022 - CSS class .vi-modal-body-backdrop--black opaticy. (plus missing docs)
  • Stop Video Component correctly when modal is closed.
  • Original .modal-sm and .modal-md options

Changed

  • Layering (z-index) to not conflict with the Pop Navigation
  • A11y Focus close button on open.

Added

  • 23 Nov 2022 - Additional backdrop colors opaque and no blur.
  • 22 Nov 2022 - Additional backdrop colors with PBS support.
  • 14 Oct 2022 - Add .modal-screen option for screen sized modal.
  • 28 Sept 2022 - CSS class .vi-modal-body-backdrop to add to the body of the page a page.
  • Modifier --black to have a black backdrop, as required by some regulations
  • Example how to open the modal on page load.
  • RTL support
  • Initial draft