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
View Compiled
@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%)
View Compiled
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)
View Compiled
This Pen doesn't use any external CSS resources.