Replicating Some Of Google Hangouts Chat Design

I've been using Google Hangouts a bunch. It's really pretty great. One on one or group text chat, audio, or video. Text is archived, maintains history, and is searchable. Video / audio is recordable. It works great on desktop and mobile devices and keeps them in sync. It's free. Hard to beat that.

Anyway, on a whim I decided to replicate some of the look of the chat window on desktop. Turns out there is a bunch of interesting stuff that comes up! Radial gradients, pseudo elements and animations, flexbox, and more.

The image above is what we're going to build.

Overall Structure

Everything we see here is related. That calls for a <section> I think. There will probably be others like it, so that calls for a class name.

<section class="module">
<!-- everything -->
</section>

The top is more of a "header" than a "heading" because it's not just text, it has other stuff going on up there. The conversation happens in a very specific order, so I'm thinking <ol> with each group of text/image being a <li>. Within the list item, stuff like images and paragraphs.

I find little charts like this useful. While not comprehensive, it shows the thought process:

In the header there are some icons. In the demo, I use some quick-and-dirty stuff from We Love Icon Fonts. In production I would use a streamlined icon font made from IcoMoon and inserted with this HTML.

The Pulsing Header

When you get a new message, the header kinda glows/pulses. The solid-color bar now has essentially a radial gradient in the center of it that becomes more and less intense. At peak intensity, it's like:

Which you could picture like this:

Creating that gradient isn't quite as easy as you might hope1. You might think it's the most basic syntax of all, from one gray to another:

background: radial-gradient(#666, #999);

But no, that just fills the area with an elliptical gradient (white and black for clarity):

You can force it into a circle, which gets us pretty close:

background: radial-gradient(circle, #666, #999);

But if you really want fine-grained control over how large that gradient in the middle is, you'll want something like:

And even then it doesn't work in Opera 12.15. So... instead we could use the most simple gradient syntax and apply it to a pseudo element on the header. That way we can animate the opacity to get the pulse effect anyway.

Which won't work in everything but it's a lot better than it was. You'd do it with an extra element / image / jQuery if you deemed the effect critical enough.

Basic Chat Box Setup

We already decided the conversation itself is an ordered list. Each person talking is a list item. Each individual message is a <p>, but there can be multiple messages together, so those are all grouped in a <div class="message">. We'll wrap the avatar as well.

The Variable Width Chat Bubbles

An interesting design feature of this chat design is that the chat "bubble" is only as wide as the longest sentence it contains. It's a nice feature as it makes very short messages less visually intense and gives rhythm to the conversation.

If (avatar + messages = full width) every time, floats would work fine. There is a way we could get this working with floats, but it would require extra non-semantic wrappers. Instead, let's make this a super-progressive demo and use flexbox for layout2. This is going to make a couple of other things awesomely easy, which we will get to in a moment.

Flex items, by their nature, are just as wide as they need to be. They also exhibit no natural desire to fill their flex container. If they do, they do, if they don't, they don't. You can even have them wrap if you want, but we don't in this case.

The Switcheroo

I'm sure you noticed the flip-flop design. Messages from others have the avatar on the left, messages by you have the avatar on the right. Again, do-able with floats but kinda janky. Flexbox makes this extremely easy.

In our markup, we put the avatar first, so that will be the default ("other people"). In list items with the class name "self" (our own messages) we'll switch the order of layout.

.self {
justify-content: flex-end;
}

WELL THAT WAS EASY. But wait. It's not just the horizontal alignment that switches, it's the vertical alignment too.

Floats would never be able to help us here. Things would get freaky with some placeholder elements and absolutely positioning and who knows what. With flexbox...

The Message Bubble Triangles

This has been covered a million times, so I'll keep it brief. You can make triangles in CSS with zero-width zero-height elements and borders. The borders on elements will meet each other at an angle. So if one is colored and the other is transparent, it will look like a shape.

Here, we'll color the top and right borders, and leave the bottom and left borders transparent. This makes the type of triangle you see here:

The message bubbles have little box-shadows under them. We didn't cover it, but you can see in the demo. In the "self" messages, the triangle meets the bubble where the shadow is most pronounced, so it looks weird if it's not there. We can apply the shadow to it to fix it.

.self .avatar::after {
box-shadow: 1px 1px 2px rgba(black, 0.2);
}

The Demo

2I went totally un-prefixed and new-school with all the flexbox stuff in this article, Here's some resources on that: CSS-Tricks, Dev.Opera. It's a good time for flexbox right now. IE 10 has a prefixed semi-old version, but IE 11 will be un-prefixed and new. Firefox has supported various versions forever but will be un-prefixed and new in 22 (late June 2013). Safari has old version prefixed in 6 but going unprefixed and new in 7. Chrome has new verison prefixed but is unprefixing in (30?). iOS and Blackberry are prefixing, but at least new syntax. Android at least has old prefixed version.

Is it really necessary to add all those prefixes for the gradient background?

After all, Mozilla and Opera dropped it a while ago, while the older WebKit syntax is buried. These are all self-updating browsers, so we can fairly pretend they’re always updated to the latest version, can’t we?

Great post, as always . There were a couple of things that I really appreciated.

-The mocks were a fantastic way to explain page layout and your thought process behind them, I can actually see myself using that approach in the future, I’d always put notes inside elements before and that doesn’t translate as nicely for containers.

-Absolute positioning on the before element to force the sizing… I don’t know why this surprises me, but the cleanliness of this is so good. I had been using forced shrink-wrapping on parents with children before and then messing with z-indexes to force the layer to the back. That worked, but was nowhere near as clean as I’d like. I probably will move over to this approach.

There is a lot of great stuff throughout the rest, of course, but these were the things that hit home for me today.

First of all, I’m really happy to see that flexbox finally takes its leap into modern applications. I’ve been using it on a regular basis for over a year for a number of projects, and haven’t looked back since. :)

Just a couple of notes on the ordering of item –
In the article it says that in order to switch the elements’ place you use ‘justify-content’. That’s partly true, since you also need to use the ‘order’ property (and in the codepen example you are using it).
The ‘justify’ only does the “pushing” to the other end. The ‘order’ is the “switcheroo” thingy :)

A little hack – In the fiddle you use ‘order:1’ and ‘order:2’. You can just use ‘order:-1’ on the paragraph. That’s not actually different from what you did, just a nice trick for saving a line of code (I’m so lazy).

You can also use ‘flex-direction:row-reverse’. Using the ‘row-reverse’ property also saves us the use of ‘justify-content’ (since after reversing the box, it’s flex-start is the right-end). So the lazy developer that I am I would use that instead :)

A great example of what the web can do now that just wasn’t possible (or couldn’t be done well/semantically at least) just a couple of years ago. It’s a pity it’s still -too- bleeding edge (and thanks to a lack of IE9 support, we could be a yet another full Windows-version-cycle away from flexbox taking its rightful place as layout-king).

But, maybe with the rise of web technologies in mobile (I’m looking at you, especially, FirefoxOS), this is a good sign of what we can do in that field for presenting on par with native with less holding us back.

The page layout and your thought process behind them, I can actually see myself using that approach in the future. You can also use ‘flex-direction:row-reverse’. Using the ‘row-reverse’ property also saves us the use of ‘justify-content.ECommerce Design Calgary

Always amazing posts Chris! The layout is (almos) perfect. You just missed the rounded corner on the top left of the “other” messages, which left a pixel broken before the arrow. That’s easy to fix with that on line 74:

This is a great example of how to use Flexbox, could you put together a CodePen to demonstrate the correct cross-browser syntax? It’s very confusing when you add that layer, and I think this would be helpful.

👋

CSS-Tricks* is created, written by, and maintained by Chris Coyier and a team of swell people. The tech stack for this site is fairly boring. That's a good thing! I've used WordPress since day one all the way up to v17, a decision I'm very happy with. I also leverage Jetpack for extra functionality and Local for local development.