I am Joseph Barrett

Pure CSS3 Animated Chat Icon

Today I’d like to share with you the code that I had set up for my chat icon for my social navigation. My ideas were to bring a little more context to the icons on hover and I wanted to come up with an animated version for each one. After coming up with the chat icon, I had used some images to create it and figured that there could be an way to do it without using any images for fun. You can view the demo here - CSS3 Chat Icon Demo

The HTML

First we build our foundation of the chat bubble:

	
<div class="chat">
	<span class="line"></span>
	<span class="line"></span>
	<span class="line"></span>
	<span class="dot"></span>
	<span class="dot"></span>
	<span class="dot"></span>
</div>

This is all the HTML that is needed to do the bubble. I’ve purposely left them as empty spans as they aren’t necessary to any of the page markup and have no semantic meaning to a user/bot/alien.

The CSS

Now that we have our markup, let’s make it look like an actual conversation. We’ll start out with the bubble shape:

	
.chat {
	position: relative;
	height: 30px; 
	width: 43px; 
	
	-moz-border-radius: 26px / 18px;
	-webkit-border-radius: 26px 18px;
	border-radius: 26px / 18px;
	
	//Background gradient created with the help of http://www.colorzilla.com/gradient-editor/
	background: #f2c718; /* Old browsers */
	background: -moz-linear-gradient(left, #f2c718 0%, #e7980e 100%); /* FF3.6+ */
	background: -webkit-gradient(linear, left top, right top, color-stop(0%,#f2c718), color-stop(100%,#e7980e)); /* Chrome,Safari4+ */
	background: -webkit-linear-gradient(left, #f2c718 0%,#e7980e 100%); /* Chrome10+,Safari5.1+ */
	background: linear-gradient(left, #f2c718 0%,#e7980e 100%); /* W3C */
}

.chat:before {
	content: "";
	display: block;
	width: 0;
	height: 0;
	
	//Shaping the triangle with borders
	border-left: 8px solid transparent;
	border-right: 8px solid transparent;
	border-top: 8px solid #eeb614;
	
	position: absolute;
	left: 0; 
	bottom: -3px;
	
	//Turning a right triangle into an isosceles triangle with scaleX() since it was too wide
	-webkit-transform: rotate(30deg) scaleX(.4);
	-moz-transform: rotate(30deg) scaleX(.5);
}

In order to take our oval shape, the first number is the horizontal radii (26px) and controls all 4 corners. The second is the vertical radii (18px). Depending on the height and width of your chat bubble, your radii will follow - For the oval, a radius of just over half the width has seemed to work best.

Instead of creating more markup within the document itself, we’re rendering our chat bubble tail with the psuedo-element :before (triangles thanks to CSS Tricks). Positioning and rotating the triangle into place while also scaling the x-axis to squeeze it together finishes off the look of the chat bubble.

Now we’ll set up the lines and circles that make up the dialog. A simple 1px white line and the 4px circles to accommodate them and positioned into place:


.line {
	width: 20px; 
	height: 1px;
	 
	position: absolute; 
	top: 9px; 
	left: 13px;
	
	background: #fff;
	-webkit-box-shadow: 0px 1px 0px #e58e39; 
	-moz-box-shadow: 0px 1px 0px #e58e39; 
	box-shadow: 0px 1px 0px #e58e39; 
}
.line:nth-of-type(1n) {top: 9px; left: 13px;}
.line:nth-of-type(2n) {top: 14px; left: 8px;}
.line:nth-of-type(3n) {top: 19px; left: 13px;}
.dot {
	width: 4px; 
	height: 4px; 
	-webkit-border-radius: 4px; 
	-moz-border-radius: 4px; 
	background: #4b503f; 
	
	position: absolute;
	top: 7px; 
	left: 8px;
}
.dot:nth-of-type(1n) {top: 7px; left: 8px;}
.dot:nth-of-type(2n) {top: 12px; left: 29px; background: #fffd18;}
.dot:nth-of-type(3n) {top: 18px; left: 8px; background: #4b503f;}

You should now be seeing the final chat bubble all created out of CSS3. This is what non-webkit browsers should be viewing with the exception of <IE8 which will see a magnificent box. It gets the job done, but doesn’t create the same impact as what some simple animation can do to it. The first thing we’ll attack is animating the dots and controlling their delay within the animation keyframes:


.dot:nth-of-type(1n) {
	-webkit-animation-name: dot1;
    -webkit-animation-timing-function: ease-in-out;
    -webkit-animation-iteration-count: infinite;
    -webkit-animation-duration: 1.4s;
}
@-webkit-keyframes dot1 {
    0%,95% { opacity: 1; }
    100% { opacity: 0; }
}
.dot:nth-of-type(2n) {
	-webkit-animation-name: dot2;
    -webkit-animation-timing-function: ease-in-out;
    -webkit-animation-iteration-count: infinite;
    -webkit-animation-duration: 1.4s;
}
@-webkit-keyframes dot2 {
    0%,31% { opacity: 0; }
    33%,100% { opacity: 1; }
}
.dot:nth-of-type(3n) {
	-webkit-animation-name: dot3;
    -webkit-animation-timing-function: ease-in-out;
    -webkit-animation-iteration-count: infinite;
    -webkit-animation-duration: 1.4s;
}
@-webkit-keyframes dot3 {
    0%,65% { opacity: 0; }
    67%,100% { opacity: 1; }
}

As you can see I have 3 separate animated keyframes for each dot, essentially broken down into viewing thirds - dot1 is showing all the time, dot2 is hidden the first third, and dot3 is hidden the first two-thirds of the animation-duration. The reason I chose the route of 3 separate keyframe sets and forgo an animation-delay with 1 keyframe set, is that I wanted this to be on an infinite loop and only the first iteration of the keyframe set is delayed when using the property. Also, the animation-duration is your end time of the loop, so if you want to slow it down a bit, all you need to do is lengthen the time.

When it comes to the line animations, I set it all up the same except for we’re animating the width property instead of the opacity:


.line:nth-of-type(1n) {
	-webkit-animation-name: line1;
    -webkit-animation-timing-function: ease-in-out;
    -webkit-animation-iteration-count: infinite;
    -webkit-animation-duration: 1.4s;
}
@-webkit-keyframes line1 {
    0% { width: 0; }
    33%,100% { width: 20px; }
}
.line:nth-of-type(2n) {
	-webkit-animation-name: line2;
    -webkit-animation-timing-function: ease-in-out;
    -webkit-animation-iteration-count: infinite;
    -webkit-animation-duration: 1.4s;
}
@-webkit-keyframes line2 {
    0%,33% { width: 0px; }
    67%,100% { width: 20px; }
}
.line:nth-of-type(3n) {
	-webkit-animation-name: line3;
    -webkit-animation-timing-function: ease-in-out;
    -webkit-animation-iteration-count: infinite;
    -webkit-animation-duration: 1.4s;
}
@-webkit-keyframes line3 {
    0%,67% { width: 0px; }
    100% { width: 20px; }
}

This completes the chat bubble animation. The final product. The only thing left would be to implement it how you want to, I put it on a simple :hover event:


.bubble {
	-webkit-transition: all ease-in-out 400ms; 
	-webkit-transform: scale(0); 
	-webkit-transform-origin: bottom left;
	
	-moz-transition: all ease-in-out 400ms; 
	-moz-transform: scale(0); 
	-moz-transform-origin: bottom left;
}
a:hover .bubble {
	-webkit-transform: scale(1);
	-moz-transform: scale(1);
}

The possibilities are endless, I just hope this can spark an idea in your head of what you can do with creating your own shapes and animating them within the browser.

If you had any questions or comments feel free to hit me up on Twitter.

Follow me on Twitter, Dribbble and Tumblr

5.08
2011