我一直在使用 Google Hangouts。 真的很棒。 一对一或群组文本聊天、音频或视频。 文本存档,维护历史记录,并且可搜索。 视频/音频可录制。 它在台式机和移动设备上运行良好,并保持同步。 它是免费的。 很难超越它。
无论如何,我一时兴起决定复制桌面聊天窗口的部分外观。 事实证明,出现了很多有趣的东西! 径向渐变、伪元素和动画、Flexbox 等等。

上面的图片是我们即将构建的内容。
整体结构
我们在这里看到的一切都是相关的。 我想这需要一个 <section>
。 可能还会像它这样的其他部分,因此需要一个类名。
<section class="module">
<!-- everything -->
</section>
顶部更像是“标题”而不是“标题”,因为它不仅仅是文本,它还有其他东西在上面。 谈话按非常具体的顺序进行,所以我认为 <ol>
,每个文本/图像组都是一个 <li>
。 在列表项中,诸如图像和段落之类的内容。
我发现像这样的图表很有用。 虽然不全面,但它显示了思维过程。
<section class="module">
<header class="top-bar">
<h1>Hangouts</h1>
<!-- likely some spans and stuff -->
</header>
<ol class="conversation">
<li>
<img class="avatar" />
<div class="message">
<p>Talkie talk talk.</p>
</div>
<li>
</ol>
</section>
标题中有一些图标。 在演示中,我使用了一些来自 We Love Icon Fonts 的快速且肮脏的东西。 在生产中,我将使用一个来自 IcoMoon 并使用 此 HTML 插入的简化图标字体。
脉冲标题
当您收到新消息时,标题会有点发光/脉冲。 现在,实色条实际上在其中心有一个径向渐变,该渐变变得越来越强或越来越弱。 在峰值强度下,它就像

您可以像这样想象它
创建渐变并不像您希望的那样容易1。 您可能会认为它是最基本的语法,从一种灰色到另一种灰色
background: radial-gradient(#666, #999);
但事实并非如此,它只是用椭圆渐变填充区域(为清晰起见,为白色和黑色)

您可以将其强制为圆形,这使我们非常接近
background: radial-gradient(circle, #666, #999);

但是,如果您真的希望对中间渐变的大小进行精细控制,您将需要类似的东西
background: radial-gradient(center center, circle closest-side, #999999, #666666 800%);
在这里,您可以调整该 800% 以获得您想要的效果。 在撰写本文时,该语法仍然带有前缀。 具有所有前缀,它就像
background: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 800, color-stop(0%, #999999), color-stop(800%, #666666));
background: -webkit-radial-gradient(center center, circle closest-side, #999999, #666666 800%);
background: -moz-radial-gradient(center center, circle closest-side, #999999, #666666 800%);
background: -o-radial-gradient(center center, circle closest-side, #999999, #666666 800%);
background: radial-gradient(center center, circle closest-side, #999999, #666666 800%);
即使这样,它也不适用于 Opera 12.15。 因此……我们可以使用最简单的渐变语法并将其应用于标题上的伪元素。 这样,我们可以通过动画调整不透明度来获得脉冲效果。
.top-bar {
background: #666;
position: relative;
overflow: hidden;
}
.top-bar::before {
content: "";
position: absolute;
top: -100%;
left: 0;
right: 0;
bottom: -100%;
opacity: 0.25;
background: radial-gradient(white, black);
}
绝对定位将使它位于具有默认静态定位的标题中的任何内容之上。 但我们可以解决这个问题。
.top-bar > * {
position: relative;
}
然后对其进行动画处理
.top-bar::before {
animation: pulse 1s ease alternate infinite;
}
@keyframes pulse {
from { opacity: 0; }
to { opacity: 0.5; }
}
这在所有内容中都无法正常工作,但它比以前好得多。 如果您认为效果足够重要,您将使用额外的元素/图像/jQuery 来完成它。
基本聊天框设置
我们已经决定谈话本身是有序列表。 每个说话的人都是一个列表项。 每条单独的消息都是一个 <p>
,但可以将多条消息放在一起,因此它们都分组在一个 <div class="message">
中。 我们也将包装头像。
<li>
<div class="avatar">
<img src="//s3-us-west-2.amazonaws.com/s.cdpn.io/5/profile/profile-80_9.jpg" />
</div>
<div class="messages">
<p>yeah, they do early flights cause they connect with big airports. they wanna get u to your connection</p>
<time datetime="2009-11-13T20:00">Timothy • 51 min</time>
</div>
</li>
请注意那里的 <time>
元素。 时间元素的实际内容可以是任何有意义的东西。 但 datetime
属性采用特定格式。 查看更多。
我们还需要一种方法来区分我们的消息和其他人的消息。 一个类就行了……
<li class="self">
<!-- ... -->
</li>
<li class="other">
<!-- ... -->
</li>
可变宽度的聊天气泡
这种聊天设计的有趣设计特征是聊天“气泡”仅与其中包含的最长句子一样宽。 这是一个很好的功能,因为它使非常短的消息在视觉上不那么强烈,并为谈话增添节奏。
如果(头像 + 消息 = 全宽)每次都一样,浮动就可以了。 我们有一种方法可以使浮动起作用,但这需要额外的非语义包装器。 相反,让我们创建一个超前的演示并使用 Flexbox 进行布局2。 这将使其他一些事情变得非常容易,我们将在稍后介绍。
Flex 项本质上仅与它们需要的一样宽。 它们也不自然地渴望填满它们的 Flex 容器。 如果它们确实如此,那就这样,如果它们不这样做,那就不要这样做。 您甚至可以根据需要让它们换行,但在本例中我们不会这样做。
因此,我们的 CSS 变成
.discussion li {
display: flex;
}
.avatar {
width: 40px;
}
.avatar img {
width: 100%;
display: block;
}
非常容易。
切换
我敢肯定您已经注意到了翻转设计。 来自其他人的消息的头像在左侧,您自己的消息的头像在右侧。 同样,可以使用浮动来实现,但有点笨拙。 Flexbox 使这变得极其容易。
在我们的标记中,我们将头像放在首位,因此这将是默认值(“其他人”)。 在具有类名“self”(我们自己的消息)的列表项中,我们将更改布局顺序。
.self {
justify-content: flex-end;
}
好吧,这太容易了。 但是等等。 不仅仅是水平对齐方式切换,垂直对齐方式也切换。
浮动永远无法帮助我们。 事情会变得很奇怪,有一些占位符元素和绝对定位,以及谁知道是什么。 使用 Flexbox……
.self {
/* switch horizontal layout */
justify-content: flex-end;
/* switch vertical layout */
align-items: flex-end;
}
擦擦手。
聊天气泡三角形
这已经被讨论过很多次了,所以我简短地说一下。 您可以使用 CSS 创建三角形,方法是使用零宽度零高度元素和边框。 元素上的边框将在一个角度相遇。 因此,如果一个元素有颜色而另一个元素是透明的,它看起来像一个形状。
在这里,我们将为顶部和右侧边框着色,并将底部和左侧边框保持透明。 这将创建您在这里看到的三角形类型
.other .avatar::after {
content: "";
position: absolute;
top: 0;
right: 0;
width: 0;
height: 0;
border: 5px solid white;
border-left-color: transparent;
border-bottom-color: transparent;
}
然后只需更改其位置以及为“self”消息着色的边框
.self .avatar::after {
content: "";
position: absolute;
bottom: 0;
left: 0;
width: 0;
height: 0;
border: 5px solid white;
border-right-color: transparent;
border-top-color: transparent;
}
聊天气泡在下面有一点方框阴影。 我们没有介绍它,但您可以在演示中看到。 在“self”消息中,三角形在阴影最明显的点与气泡相遇,因此如果没有它,看起来很奇怪。 我们可以将阴影应用于它来修复它。
.self .avatar::after {
box-shadow: 1px 1px 2px rgba(black, 0.2);
}
演示
Check out this Pen!
1 以下是关于径向渐变的更多资源:Impressive Webs、Web Directions
2 我在本文中完全去除了 Flexbox 的所有前缀,并使用了最新方法。 以下是关于它的资源:CSS-Tricks、Dev.Opera。 现在是 Flexbox 的好时机。 IE 10 有一个带前缀的半旧版本,但 IE 11 将没有前缀且是新的。 Firefox 一直支持各种版本,但在 22(2013 年 6 月下旬)将没有前缀且是新的。 Safari 在 6 中有一个带有前缀的旧版本,但在 7 中将没有前缀且是新的。 Chrome 有一个带有前缀的新版本,但 正在去除前缀(30?)。 iOS 和 Blackberry 正在添加前缀,但至少是新的语法。 Android 至少有一个旧的带前缀的版本。
Chris 的好帖子(一如既往)!!!
谢谢 Chris,这很好。
我喜欢越来越多的人在复制 Google 推出的漂亮设计。谢谢 Chris,很棒的 HTML5 和 CSS3 教程。
纯粹的赞!:D
这很棒,Chris :) 谢谢关于 flex-box 的提示 :) :)
真的有必要为渐变背景添加所有这些前缀吗?
毕竟,Mozilla 和 Opera 在一段时间前就放弃了它,而较旧的 WebKit 语法被掩埋了。这些都是自动更新的浏览器,所以我们不妨假装它们始终更新到最新版本,对吧?
我参考 Lea Verou 的文章 来解释为什么不使用它。我经常也会遵循它,具体取决于我正在处理的网站的统计数据。
喜欢你做这些。非常有见地,也很有教育意义。特别是这个,学到了很多关于渐变和 flex 的知识 :)
好文章,一如既往。有一些事情我真的很感激。
- 模拟图是解释页面布局和你的思路的绝佳方式,我实际上可以想象自己在未来使用这种方法,我一直会在元素内部添加笔记,但这对于容器来说并不能很好地转化。
- 对 before 元素的绝对定位来强制尺寸......我不知道为什么这会让我惊讶,但这的简洁性太好了。之前我一直使用强制缩放到父级元素,然后使用 z-index 来强制层到后面。这很有效,但并不像我希望的那样简洁。我可能会转向这种方法。
当然,其余部分还有很多很棒的东西,但这些是我今天最感触的部分。
这个脉冲标题很漂亮;对这一点的把握非常好。Flexbox 的使用也很棒,尤其是在头像的底部/右侧对齐方面。
关于最后两块代码,你有很多重复的东西。你可能想把所有这些东西放到
.avatar:after
中,然后简单地更改.self .avatar:after
的边框。使用客户端语言进行这类事情的想法很酷。:)
仅仅出于好奇:这是 Google Hangouts for iPhone 吗?还是你用的是什么 Android 设备?还是这是特定视图?(你在进行语音聊天吗?)
聊天是一样的,但顶部的栏和其它东西在我的 Nexus 4 上大不相同。空白聊天的截图:http://cl.ly/image/0S1i2r2d0Q2Q
我认为他在说 Hangouts for desktop
Hangouts for desktop?就像在 Gmail 中?我可能还在使用旧版本……我的看起来一点都不像那样,哈哈。
好的,我错了……我访问了文章顶部的链接,发现有一个“桌面应用程序”(这是一个特殊的 Chrome 扩展)。这很酷!也许终于可以替换 Adium 了……?
首先,我很高兴看到 flexbox 终于在现代应用中崭露头角。我一年多来一直定期在多个项目中使用它,而且再也没有回头过。:)
关于项目排序的几点说明——
文章中说,为了交换元素的位置,你需要使用‘justify-content’。这部分正确,因为你还需要使用‘order’ 属性(在 codepen 示例中你使用了它)。
‘justify’ 只是将元素“推”到另一端。‘order’ 才是“交换”的工具。:)
一个小技巧——在小提琴中,你使用了‘order:1’ 和 ‘order:2’。你只需要在段落中使用‘order:-1’。这实际上与你所做的没有区别,只是一个小技巧,可以节省一行代码(我太懒了)。
你也可以使用‘flex-direction:row-reverse’。使用‘row-reverse’ 属性也可以让我们不用使用‘justify-content’(因为反转盒子后,它的 flex-start 就是右边)。所以像我这样懒惰的开发者会使用它。:)
好文章 :)
Google 的确有一些很棒的设计。
Chris,谢谢你的文章。
我看到你使用了
:after
和::after
。是有原因吗?还是只是拼写错误?:after
是旧的语法,而::after
是新的语法。新的语法是为了区分伪类(比如:hover
)和伪元素(::after
是一个伪元素)。IE8 不支持新的语法,因此最好在一段时间内继续使用旧的语法。
真的很棒的文章。 真不可思议,如此简单的东西竟然是经过深思熟虑和创造力的产物!
很奇怪,我在 Firefox 21 中没有看到正确的结果。我去了 about:config 并注意到
layout.css.flexbox.enabled
被设置为false
(默认/非粗体设置)。更改它解决了这个问题,但我有点惊讶于我需要这样做,我希望下一个版本默认情况下进行更改……
顺便说一句,好文章 :)
将实验性功能放在标志后面是浏览器中的标准做法。下一个版本的 Firefox 将默认情况下启用 Flexbox。
顺便说一句,距离下一个版本的 Firefox 发布不到一周了 :-D
这是一个很好的例子,说明了 web 现在可以做的事情,而就在几年前,这些事情是不可能的(或者至少不能很好地/语义化地完成)。很遗憾它仍然过于前沿(而且由于缺乏对 IE9 的支持,我们可能还要等一个完整的 Windows 版本周期才能让 flexbox 成为布局之王)。
但是,也许随着 web 技术在移动设备中的兴起(我特别关注你,FirefoxOS),这是一个很好的迹象,表明我们在该领域可以做些什么,从而以与原生应用程序相媲美的水平进行展示,而不会受到太多阻碍。
页面布局和你的思路,我实际上可以想象自己在未来使用这种方法。你也可以使用‘flex-direction:row-reverse’。使用‘row-reverse’ 属性也可以让我们不用使用‘justify-content.ECommerce Design Calgary
很好地使用了 flex-box。但我认为它可以不用 flex-box 来实现。这是我的 小提琴,它使用相同的 html 和绝对定位和浮动相结合。
Chris 的文章总是很棒!布局(几乎)完美。你只是错过了“其他”消息左上角的圆角,在箭头前留下了一个像素的断裂。用第 74 行的代码很容易修复。
谢谢你的好文章!
很有建设性,而且概念很强。
谢谢分享。
这是一个使用 Flexbox 的绝佳例子,你能提供一个 CodePen 来演示正确的跨浏览器语法吗?当你添加这一层时,它非常令人困惑,我认为这将非常有用。
好文章。你在屏幕截图上使用什么程序来做标记?我喜欢突出显示截图的字体、颜色等等。
孩子们,这就是你如何走到顶峰。找到一件很难的事情,然后试着用你除了智慧之外什么都没有的东西去构建它。
这里最大的教训不是关于这篇文章的实际内容,而是展示了保持眼睛睁开并使用纪律挑战自己的过程。
敬礼!
一些不错的代码示例,Chris!感谢分享。你给了我一些想法,可以用于我正在进行的另一个项目。
干杯
Laurence
这是我的不满
在 CSCC 第 108 行的某些阴影中存在一些奇怪之处
我试图使用一个匿名函数来修复它
CodePen,但我似乎无法完全修复它。
此外,感谢你所有优秀的文章以及 shop talk show dot com
非常感谢,我总是从你的代码示例中学习很多。
谢谢!
在 Chrome 28 beta(和 30 canary,我还没有尝试过 Chrome 27)中,第一张图片不知何故变得小很多(大约 19 像素)。你也看到这种情况了吗?
我也遇到了这个问题。你可以做的不是设置
width: 40px;
而是min-width: 40px;
max-width: 40px;
这将解决问题!
不错的帖子!你有关于 Google plus vcard 风格的可逆帖子的帖子吗?当你在帖子的背面时,你可以找到带有相同标签的相关帖子?
嗨,克里斯,
很棒的帖子/文章。我很遗憾现在才看到它。我绝不是 CSS 专家,但无论如何,我无法让我的“Hangouts”模块看起来像你的。
即使我复制粘贴你的 CodePen HTML 和 CSS 代码。
有什么想法吗?|