Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

JavaScript

Babel is required to process package imports. If you need a different preprocessor remove all packages first.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Behavior

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                h1.status 408
.chat
  .header.chat__header
    .header__title New Request
    .header__members
      .header__member
      .header__member.header__member--server
  .message.message--browser
    .message__content Hey Server 👋
  .message.message--server
    .message__content Hey Browser 👋
  .message.message--browser
    .message__content Got a quick one for ya 😅
  .message.message--server
    .message__content Sure 👍
  .message.message--server
    .message__content Fire away 🔫
  .message.message--browser
    .message__content Jus' a sec 🕥
  .message.message--server
    .message__content OK 👌
  .message.message--server
    .message__content ???
  .message.message--server
    .message__content You still there??
  .message.message--server
    .message__content Ughh 😞
  .message.message--left
    .message__content Server left the chat 💅
  .message.message--typing.message--browser
    .message__content
      div
      div
      div

              
            
!

CSS

              
                @import url('https://fonts.googleapis.com/css?family=Lato')

*
  box-sizing border-box

$primary = #e0bbe4
$secondary = #fec8d8
body
  font-family 'Lato', sans-serif
  margin 0
  padding 0
  min-height 100vh
  display flex
  align-items center
  justify-content center
  flex-direction column
  background lighten($secondary, 60%)

h1
  margin 0


.status
  font-size 100px
  left 50%
  top 50%
  color lighten($secondary, 30%)
  text-shadow 0 0 5px $secondary
  margin-bottom 2rem

  @media(min-width 768px)
    font-size 200px
    transform translate(-50%, -50%) rotate(-90deg) translate(0, -140px) translate(0, -50%)
    position absolute


.chat
  border-radius 15px
  box-shadow 0 0 20px $primary
  background #fff
  width 280px
  height 250px
  display flex
  justify-content flex-end
  flex-direction column
  overflow hidden
  position relative
  padding 0 15px

  @media(min-width 768px)
    width 280px
    height 400px

  &__header
    position absolute
    top 0
    left 0


.header
  align-items center
  border-radius 15px 15px 0 0
  background darken($primary, 25%)
  color #fff
  display flex
  height 60px
  padding 20px
  width 100%
  text-transform uppercase
  z-index 2
  transform translate(0, 0)

  &__members
    display flex
    align-items center
    padding-left 15px

  &__member
    height 30px
    width 30px
    border-radius 100%
    background linear-gradient(25deg, grey, white)
    background-image url(https://source.unsplash.com/JelL3CneNDY/50x50)
    background-size cover
    margin-right 4px

    &--server
      background-image url(https://source.unsplash.com/uWaRsN-CqY0/50x50)


.message
  display none
  flex 0 0 auto
  margin-bottom 5px

  &--browser
    justify-content flex-start

    .message__content
      background #eee

  &--server
    justify-content flex-end

    .message__content
      background $primary
      color #fff
      justify-content flex-end
      text-align right


  &__content
    border-radius 15px
    min-height 50px
    align-items center
    display inline-flex
    background white
    padding 10px

  &--left
    justify-content center

    .message__content
      background #ffffff
      color #ccc

  &--typing .message__content
    div
      animation wave .5s ease infinite
      border-radius 100%
      height 8px
      width 8px
      background darken(#eee, 25%)
      margin 2px

      for $d in (1..3)
        &:nth-of-type({$d})
          animation-delay $d * .1s


    @keyframes wave
      50%
        transform translate(0, -150%)


              
            
!

JS

              
                const FourOhEight = new TimelineMax({ repeatDelay: 3 })
const typing = document.querySelector('.message--typing')
const left = document.querySelector('.message--left')
const avatar = document.querySelector('.header__member--server')
const messages = document.querySelectorAll(
  '.message:not(.message--typing):not(.message--left)'
)
const msgDuration = 0.25
const random = (max, min) => Math.floor(Math.random() * (max - min + 1)) + min
const generateChatTL = messages => {
  const chatTL = new TimelineMax()
  let stagger = 0
  for (let m = 0; m < messages.length; m++) {
    const message = messages[m]
    const differentRecipient =
      message.classList.contains('message--server') &&
      messages[m - 1] &&
      !messages[m - 1].classList.contains('message--server')
    if (
      m !== 0 &&
      m !== messages.length - 2 &&
      (m === 5 || m === 6 || m === 7 || Math.random() > 0.5)
    ) {
      const deliberation =
        m === 5 || m === 6 || m === 7 ? Math.random() * 3 : Math.random()
      chatTL.set(typing, { display: 'flex' })
      chatTL.add(
        TweenMax.to(typing, deliberation, { display: 'none' }),
        stagger
      )
      stagger += deliberation
    }
    chatTL.set(message, { scale: 0 })
    chatTL.add(
      TweenMax.to(message, msgDuration, {
        scale: 1,
        onStart: () => (message.style.display = 'flex'),
      }),
      stagger
    )
    let step = differentRecipient ? random(3, 1) : Math.random()
    if (m === messages.length - 4 || m === messages.length - 2)
      step = random(4, 2)
    stagger += m === 0 ? 2 : step
  }
  return chatTL
}

FourOhEight.set([...messages, left], { display: 'none', scale: 0 })
  .add(generateChatTL(messages))
  .set(left, { scale: 0 })
  .add(
    TweenMax.to(left, msgDuration, {
      delay: 2,
      scale: 1,
      onStart: () => (left.style.display = 'flex'),
    })
  )
  .add(
    TweenMax.to(avatar, msgDuration, {
      scale: 0,
    })
  )
  .repeat(-1)

              
            
!
999px

Console