output used to construct a "toast" component

Published:

Read additional information about output and this demo.

Note this demo makes no accommodations for mouse hover or keyboard focus within the popup message into account for delaying the automatic dismissal. Such functionality should be included in a more robust form of this demo.

Activate the button, get a "toast"

Activating the "press me" button will inject content into an output element. CSS and JavaScript are then used to visually reveal and dismiss the message.

The dismiss button of the "toast" is not a child of the output element, but rather a sibling to it. This is so that it is not part of the live announcement of the element. Activating the dismiss button will return focus to the invoking element, so keyboard focus does not become 'lost'.

Test 1 markup
<button onclick="toasty('By the power of readily available HTML, CSS and JS, I am a popup message!', 5000)">Press Me</button>
<div class="toast">
  <output></output>
  <!-- note button is not within output as this
    should NOT be part of the live announcement. -->
  <button onclick="quickDismiss()" aria-label="Dismiss">X</button>
</div>
<style>
  .toast {
    background: #61728b;
    border: 1px solid;
    border-radius: 2px;
    bottom: .5em;
    color: #fff;
    left: 0;
    margin: auto;
    max-width: 34em;
    opacity: 0;
    padding: .75em 2em .75em .75em;
    position: fixed;
    transform: translateY(0);
    transition:
      transform .2s ease-in-out,
      opacity .2s ease-in-out;
    right: 0;
  }

  .toast p {
    margin: 0;
  }

  .toast.popped {
    opacity: 1;
    transform: translateY(-4em);
  }

  .toast button {
    border: 0;
    border-left: 1px solid #fff;
    color: #fff;
    background: none;
    position: absolute;
    right: 0;
    top: 0;
    bottom: 0;
    margin: auto;
    z-index: 5;
  }
  .toast button:hover,
  .toast button:focus {
    background: #000;
  }
</style>
<script>
  // quick n' simple proof of concept JS
  var toastWrapper = document.querySelector('.toast');
  var toast = toastWrapper.querySelector('output');
  var timer;
  var init;

  var toasty = function ( string, duration ) {
    if ( typeof timer === 'number' ) {
      clear();
    }
    init = event.target;
    toast.innerHTML = '<p>' + string + '</p>';
    toastWrapper.classList.add('popped');
    timer = setTimeout(autoDismiss, duration);
  };

  var clear = function () {
    window.clearTimeout(timer);
  }

  var quickDismiss = function ( ) {
    init.focus();
    autoDismiss();
  };

  var autoDismiss = function () {
    toastWrapper.classList.remove('popped');

    timer = setTimeout(function () {
      toast.innerHTML = ' ';
      timer = undefined;
    }, 1000);
  }
</script>