近来在完善本站的评论及回复功能,考虑在评论的时候,可以让大家选择一个皮肤,让评论区域显得不那么单调,具体效果可以参考百度贴吧和QQ的聊天界面。本文给出了一种采用CSS Sprites的实现方式,气泡可以做到宽度和高度的自适应扩展。

本例中用到的气泡图案来自QQ,此处仅用于交流学习

需求描述

基本要求就是希望可以实现一个类似QQ聊天气泡的效果,做到宽度和高度的自适应扩展。此外,最好可以实现方便的皮肤选择,使得气泡可以应用多种样式,以使界面更丰富多彩。

本文实现样例展示

气泡自适应的宽度和高度

多种皮肤效果展示

实现思路

对于自适应的宽度和高度,普通的行内元素即可实现。为了实现丰富的气泡,不得不使用背景图片,我们首先来观察一个气泡,可以发现一个气泡基本上可以分为9个部分,如下图所示:

为了方便描述,我们对这些区域进行编号为0-8,其中浅蓝色部分(1/3/5/9)为相对固定不变的区域,浅黄色部分(2/4/6/8)为自动扩展的部分(其高度或者宽度需要扩展),浅红色区域(区域0)为显示文本的区域。实际上,这与Android APP开发中常用的9-patch图片的原理是类似的。

为了实现自适应的气泡,我们首先需要对这9个区域进行正确的定位。通过CSS的相对和绝对定位可以达到这个目的。简单来说,区域0的宽度和高度自动扩展,包裹0-8这所有9个区域的元素(假设为wrapper)的宽度和高度也自动扩展,同时wrapper的position设为relative,并把1-8元素的position设为absolute。这样即可以做到宽度和高度的自适应,以及各区域的正确定位。

实现了各区域的定位后,对各区域进行设定背景即可。其中1/3/5/7使用图片作背景,2/4/6/8既可以使用图片,也可以仅使用CSS设定背景和边框颜色(根据实现的难易程度来选择具体实现方式)。为了减少对服务器的图片请求次数,考虑使用CSS Sprites技术。而对于多种皮肤的实现,在不同class下应用不同的样式,调整背景图即可。

关键代码

DOM结构

首先,给出代码结构如下(仅供参考),此处使用className:left和right来区分聊天气泡的位置(界面左侧还是右侧),使用一个className来确定使用的皮肤(以下代码中是bubble-bear),替换该值可选用其他的皮肤。

  1. <ul class="chat-list">
  2. <li class="chat-item left">
  3. <img src="img/avatar-1.jpg" class="chat-avatar"/>
  4. <div class="bubble-item bubble-bear">
  5. <span class="chat-content">我是萌萌的左边小熊</span>
  6. <span class="cell cell-1"></span>
  7. <span class="cell cell-2"></span>
  8. <span class="cell cell-3"></span>
  9. <span class="cell cell-4"></span>
  10. <span class="cell cell-5"></span>
  11. <span class="cell cell-6"></span>
  12. <span class="cell cell-7"></span>
  13. <span class="cell cell-8"></span>
  14. </div>
  15. </li>
  16. <!-- more -->
  17. </ul>

CSS

  1. /* 气泡的position设为relative,方便其子元素的定位 */
  2. .bubble-item {
  3. position: relative;
  4. }
  5. /* 子元素的position设为absolute,方便其定位到父元素 */
  6. .cell {
  7. position: absolute;
  8. }
  9. /* 设定背景图(CSS Sprites) */
  10. .bubble-bear .cell-1,
  11. .bubble-bear .cell-3,
  12. .bubble-bear .cell-5,
  13. .bubble-bear .cell-7 {
  14. background: url(../img/bubbles.png) no-repeat;
  15. }
  16. /* 内容区域,防止被其他区域遮挡 */
  17. .chat-content {
  18. position: relative;
  19. z-index: 10;
  20. }
  21. /**
  22. * 以下是小熊左侧的实现代码
  23. */
  24. /* 区域0(内容区域)的边距及背景颜色等 */
  25. .left .bubble-bear .chat-content {
  26. margin: 17px 32px 15px 18px;
  27. display: inline-block;
  28. background-color: #fff8ef;
  29. }
  30. /* 区域1(左上角)的定位、大小设置、背景图位置设置 */
  31. .left .bubble-bear .cell-1 {
  32. left: 0;
  33. top: 6px;
  34. width: 20px;
  35. height: 20px;
  36. background-position: -3px -10px;
  37. }
  38. /* 区域2(上边)的定位、大小设置、背景及边框颜色 */
  39. .left .bubble-bear .cell-2 {
  40. left: 20px;
  41. top: 11px;
  42. right: 20px;
  43. height: 16px;
  44. background-color: #fff8ef;
  45. border-top: 1px solid #835426;
  46. }
  47. /* 区域3(右上角)的定位、大小设置、背景图位置设置 */
  48. .left .bubble-bear .cell-3 {
  49. right: 0;
  50. top: 0;
  51. width: 60px;
  52. height: 28px;
  53. background-position: -58px -4px;
  54. }
  55. /* 区域4(右边)的定位、大小设置、背景及边框颜色 */
  56. .left .bubble-bear .cell-4 {
  57. top: 28px;
  58. right: 6px;
  59. bottom: 10px;
  60. width: 60px;
  61. background-color: #fff8ef;
  62. border-right: 1px solid #835426;
  63. }
  64. /* 区域5(右下角)的定位、大小设置、背景图位置设置 */
  65. .left .bubble-bear .cell-5 {
  66. right: 0;
  67. bottom: 0;
  68. width: 60px;
  69. height: 16px;
  70. background-position: -58px -50px;
  71. }
  72. /* 区域6(下边)的定位、大小设置、背景及边框颜色 */
  73. .left .bubble-bear .cell-6 {
  74. right: 60px;
  75. bottom: 6px;
  76. left: 20px;
  77. height: 10px;
  78. background-color: #fff8ef;
  79. border-bottom: 1px solid #835426;
  80. }
  81. /* 区域7(左下角)的定位、大小设置、背景图位置设置 */
  82. .left .bubble-bear .cell-7 {
  83. left: 0;
  84. bottom: 0;
  85. width: 20px;
  86. height: 20px;
  87. background-position: -3px -46px;
  88. }
  89. /* 区域8(左边)的定位、大小设置、背景及边框颜色 */
  90. .left .bubble-bear .cell-8 {
  91. top: 25px;
  92. bottom: 20px;
  93. left: 4px;
  94. width: 20px;
  95. background-color: #fff8ef;
  96. border-left: 1px solid #835426;
  97. }

另一侧(即右侧)的样式与左侧类似,此处不再详举。其他皮肤的实现方式也与此相同,只是需要根据背景图来调整CSS里各属性的值(主要为定位相关的值top/right/bottom/left,大小相关的值width/height,背景及边框颜色,background-position等)。

完整代码

完整代码见 Github。您还可以在本网站的评论区域找到此种实现方案的具体应用。