共计 2994 个字符,预计需要花费 8 分钟才能阅读完成。
原文在 https://www.chenhuijing.com/blog/box-alignment-and-overflow/#%F0%9F%8F%80
作者是 chenhuijing
最近,我正在研究一些聊天界面,并且一般的布局对于大多数聊天应用程序来说都是典型的。会有一个输入与窗口底部吻合,输入消息会显示在聊天窗口的任一侧,具体取决于谁说了什么。
通常,您自己的消息将显示在右侧,而收到的消息将显示在左侧。当然,还有一些接口(Slack)可以将左侧的所有消息对齐,但是我经常使用的接口(Whatsapp,WeChat,Twitter)使用上述的左右样式。
使用 Flexbox 和 Box Alignment 属性构建这样的接口并非易事。但是在为消息区域使用框对齐属性时,确实在界面中创建了一个错误。TL:DR,此修复程序涉及使用自动页边距代替justify-content
。感兴趣吗?继续阅读。
CSS- 聊天界面
首先,我将快速概述基本聊天界面 CSS 的外观。因此,布局应如下所示:
您将需要一个用于整个聊天窗口的容器,并在底部将其分为标题,消息区域和输入区域。在消息区域内,单个消息将是它们自己的元素,左右排列。
<aside id="chatWindow">
<div class="header">
<h1>Live support</h1>
<button class="btn-close" id="closeChat">
<svg viewBox="0 0 47.971 47.971"><path fill="white" d="M28.228 23.986L47.092 5.122a2.998 2.998 0 000-4.242 2.998 2.998 0 00-4.242 0L23.986 19.744 5.121.88a2.998 2.998 0 00-4.242 0 2.998 2.998 0 000 4.242l18.865 18.864L.879 42.85a2.998 2.998 0 104.242 4.241l18.865-18.864L42.85 47.091c.586.586 1.354.879 2.121.879s1.535-.293 2.121-.879a2.998 2.998 0 000-4.242L28.228 23.986z"/></svg>
</button>
</div>
<div id="message-area" class="messages">
</div>
<div class="controls">
<form id="textentry">
<input id="textbox" type="text">
<input id="submit" type="submit" value="Send">
</form>
</div>
</aside>
对于此特定示例,我将一个 <aside>
元素用作聊天窗口主体,并在其上应用了一个 display: flex
。整个聊天窗口的布局几乎都将由Flexbox
提供支持。
aside {
display: flex;
flex-direction: column;
height: 100vh;
}
.header {
display: flex; /* Because I have a close button I want aligned with the title text */
align-items: center;
/* Visual styles not included here but they exist */
}
.messages {
flex: 1; /* Allows the message area to expand with viewport height */
display: flex;
flex-direction: column;
overflow-y: scroll;
}
.controls {/* Visual styles, not much layout */}
消息区域上flex: 1
,而它的父(<aside>
)flex 方向是纵向的,者意味着,消息区的高度会随着父元素增加填充额外的空间,或反之亦然。
将单个正整数用作 flex
flex 项目上的值将使用 flex 关键字值之一。此关键字解析为flex-grow
正整数值,flex-shrink
1 的值或者flex-basis
0 的值。
至于消息区域内的聊天气泡,每个角色都有自己的类,例如 agent
和input
。对于应该在左侧的聊天气泡,您实际上不需要执行任何操作,而对于应该在右侧的聊天气泡,请添加一个align-self: flex-end
。
数据丢失问题
随着更多消息的交换,所有消息的总高度将超过消息区域的高度,因此我们希望消息区域可滚动。
最初,为了使聊天消息从消息区域的底部开始,我在消息区域上设置了一个justify-content: flex-end
。这足够好用。首先:
.messages {
flex: 1; /* Allows the message area to expand with viewport height */
display: flex;
flex-direction: column;
overflow-y: scroll;
justify-content: flex-end;
}
不幸的是,一旦我们收到的消息超出消息区域可以容纳的数量,就会遭受数据丢失的问题。我们无法滚动到最早的消息。
如果您查看框对齐的规范,则需要注意以下几点:
当对齐对象大于对齐容器时,它将溢出。如果在这种情况下使用某些对齐方式,则可能会导致数据丢失:例如,如果侧边栏的内容居中,则当它们溢出时,它们可能会将部分框发送到视口的开始边缘之外,而无法滚动到。
而且,如果您查看 flexbox 规范,还需要注意以下几点:
溢出框会忽略其自动页边距,并在最终方向上溢出。
现在,如果使用的overflow alignment
关键字 safe,浏览器将执行的操作是将对齐方式更改回不会导致数据丢失的方式。您可以在 Firefox 中尝试一下以自己查看。
.messages {
flex: 1; /* Allows the message area to expand with viewport height */
display: flex;
flex-direction: column;
overflow-y: scroll;
justify-content: safe flex-end;
}
但是,这样就无法实现使消息从消息区域的底部开始的初衷。浏览器已强制对齐以 flex-start
防止数据丢失,因此我们回到正题。
auto-margins
修复法
我想出的解决方案是,不是 justify-content: flex-end
在消息区域的第一个子节点上设置margin-top: auto
,而是将消息与消息区域的底部对齐。
如果您这次浏览 Flexbox 规范,则可以找到以下内容:
在通过 justify-content 和 align-self 对齐之前,任何正的自由空间都会分配给该维度中的自动边距。
无论消息区域中有多少消息气泡,第一个消息气泡上的顶部自动边距都会将所有消息向下推到消息区域的底部。并且当有很多消息时,您仍然可以滚动消息区域。
https://www.chenhuijing.com/a…
如果有人感兴趣,我已经移植了一个演示,展示了此 CodePen 中两种实现之间的区别:https ://codepen.io/huijing/pen/zYYoZZP。
搬运一篇文章,机翻。
没有公众号需要你关注。