main
  .phone
    ul.message-list(aria-label='A list of random messages from a simulated server, styled to resemble a smartphone.' aria-live='polite' aria-relevant='additions')
    
  .text
    h1 408 — Request Timeout
    
    p The client did not produce a request within the time that the server was prepared to wait. The client MAY repeat the request without modifications at any later time.
View Compiled
body
  font-family 'space mono', monospace
  font-size 16px
  color #333
  background-color ghostwhite
   
.phone
  max-width 15em
  margin 3em auto
  background-color currentcolor
  padding 1em 0.5em
  border-radius 1em
  box-shadow 0 10px 20px rgba(0,0,0,0.19), 0 6px 6px rgba(0,0,0,0.23)
  
.message-list
  height 20em
  overflow hidden
  background white
  margin 1em auto
  list-style none
  padding 0.5em
  border-radius 0.1em
  display flex
  flex-direction column
  justify-content flex-end
  
.message
  display flex
  align-items flex-end
  flex-shrink 0
  margin-bottom 1em
  animation fadein 400ms
  
.message__text
  background-color dodgerblue
  padding 0.5em 1em
  color rgba(255, 255, 255 0.9)
  border-radius 1em

.message__avatar
  flex-shrink 0
  width 2em
  height 2em
  text-align center
  margin-right 0.5em
  border-radius 2em
  display flex
  flex-direction column
  justify-content center
  background-color lavender
  
.text
  width 27em
  margin 0 auto
  
.visually-hidden
  clip rect(1px, 1px, 1px, 1px) 
  height 1px 
  overflow hidden 
  position absolute 
  white-space nowrap 
  width 1px 
  
@media (prefers-reduced-motion: reduce)
  * 
    animation none !important
    transition none !important
  
@keyframes fadein
  0%
    opacity 0
    
  50%
    opacity 0
    
  100%
    opacity 1
View Compiled
const messages = [
  'hey',
  'heyy',
  'heyyy',
  "what's up?",
  'you there??',
  "how's it going?",
  'so...',
  'anybody home?',
  'just checking in',
  "what's going on?",
  'you around?',
  'let me know when you get this',
  'did you get my message?',
  'knock knock',
];

const messageList = document.querySelector('.message-list');

function randomMessage() {
  const i = Math.floor(Math.random() * messages.length);
  return messages[i];
}

function buildMessage(message) {
  const li = document.createElement('li');
  li.classList.add('message');
  
  const avatar = document.createElement('div');
  avatar.classList.add('message__avatar');
  avatar.setAttribute('aria-hidden', 'true');
  avatar.appendChild(document.createTextNode('🖥️'));
  
  const messageEl = document.createElement('div');
  messageEl.classList.add('message__text');
  
  const hiddenText = document.createElement('span');
  hiddenText.classList.add('visually-hidden');
  hiddenText.appendChild(document.createTextNode('Message from server: '));
  messageEl.appendChild(hiddenText); 
  messageEl.appendChild(document.createTextNode(message));
  
  li.appendChild(avatar);
  li.appendChild(messageEl);
  
  return li;
}

function scrollToBottom(animate) {
  if (animate) {
    const distance = messageList.scrollHeight - messageList.scrollTop;
    const steps = 10;
    const step = distance / steps;
  
    for (let i = 0; i <= steps; i++) {
      setTimeout(() => {
        messageList.scrollTop = messageList.scrollTop + (i * step);
      }, 50 * i);
    }
  }
  else {
    messageList.scrollTop = messageList.scrollHeight;
  }
}

function showMessage(infinite) {
  const message = randomMessage();
  messageList.appendChild(buildMessage(message));
  scrollToBottom(infinite);
  
  if (infinite) {
    const delay = Math.random() * 2000 + 2000;
    setTimeout(() => showMessage(true), delay);
  }
}

const motionQuery = matchMedia('(prefers-reduced-motion: reduce)');
function handleReduceMotionChanged() {
  const animate = !motionQuery.matches;
  if (animate) {
    showMessage(true);
  }
  else {
    showMessage(false);
    showMessage(false);
    showMessage(false);
    showMessage(false);
    showMessage(false);
    showMessage(false);
    showMessage(false);
  }
}
handleReduceMotionChanged();
motionQuery.addListener(handleReduceMotionChanged);

External CSS

  1. https://cdnjs.com/libraries/10up-sanitize.css
  2. https://fonts.googleapis.com/css?family=Space+Mono:400,700

External JavaScript

This Pen doesn't use any external JavaScript resources.