系列文章
说在前面
本篇是张鑫旭老师的 CSS基础测试4 的阅后笔记。(感谢 XboxYan 的解答,堪称模板。另外还有几位同学的解答也各有亮点:yaeSakuras,maomao1996)
题目
先来看看题目。
完成下图所示的布局效果,只要兼容移动端即可,效果如下:
需求:
- 视觉还原
- 代码友好
- 体验良好
思路
还是老规矩,先实现最基础的,再谈优化。
这个界面乍一看有几个关键点:
- 气泡小尾巴
- 布局
气泡小尾巴
那么先来看看这个气泡小尾巴的实现。
在我上期的 css 小测 - 02 中提到过通过 border 来绘制三角形的原理,这里同样使用 border 来完成小尾巴的绘制。
首先把正方形画出来:
.border{
border: 20px solid $borderColor;
}
效果如下:
从题目的图中可以看到,小气泡是具有弧度的,那么这里很明显可以使用 border-radius 来调节。
首先我们为这个元素添加大小,然后去掉其中两个相邻边的 border。
.border{
background: deeppink;
height: 20px;
width: 20px;
border-width: 0px 0px 20px 20px;
}
效果如下:
现在我们让左上角具有一定的弧度:
.border{
background: deeppink;
height: 20px;
width: 20px;
border-width: 0px 0px 20px 20px;
border-top-left-radius: 60px;
}
效果如下:
仔细观察的话,小尾巴的雏形已经出现了,我们只需要让其他部分消失即可。这里需要消除的是元素本身的背景色和底部的边框。
.border{
background: #fff;
height: 20px;
width: 20px;
border-width: 0px 0px 20px 20px;
border-top-left-radius: 60px;
border-bottom-color: transparent;
}
最终效果如下:
这个小尾巴,在实现好气泡之后,让它把一部分藏在气泡之下即可。
布局
关于布局在我的 css 小测 - 01 中也有提到过。
这里我们先构建 HTML,有以下几点值得注意:
- 注意命名空间
- 如果遇到不同性质的命名空间,可以通常有两种解决方案:
- 使用 class,在命名上加以区分,比如 msg-item__left
- 使用属性选择器
- 尽量使用具有语义的标签
注意以上几点,HTML 就没什么好说的了:
<ul class="chat-list">
<li class="chat-item">
<img
class="chat-avator"
alt="head"
src="https://tva4.sinaimg.cn/crop.0.0.750.750.180/75f2b996jw8f6zkdm7qp7j20ku0kudgr.jpg"
/>
<div class="chat-container">
<h3 class="chat-user">
<span class="chat-name">提按生</span>
<span class="chat-time">9月30日 21:47</span>
</h3>
<p class="chat-content">
什么秘密,我觉得你现在跟我说什么都没有意义。
</p>
</div>
</li>
<li class="chat-item" date-chat-self>
<img
class="chat-avator"
alt="head"
src="https://tvax3.sinaimg.cn/crop.135.0.810.810.180/006LO43wly8frjay2sypvj30u00mita5.jpg"
/>
<div class="chat-container">
<h3 class="chat-user">
<span class="chat-name">X优秀Y</span>
<span class="chat-time">刚刚</span>
</h3>
<p class="chat-content">
围观戏精现场
</p>
</div>
</li>
</ul>
那么接下来写 css。首先,reset css 的时候,padding 并没有设置的必要,因为 html 和 body 并没有 padding,其他需要花时间细调的就先不赘述了。
html,
body {
margin: 0;
height: 100%;
}
.chat-list {
height: 100%;
margin: 0;
padding: 0;
overflow: auto;
list-style: none;
}
.chat-item {
display: flex;
padding: 0.4375rem;
margin-bottom: 0.9375rem;
}
.chat-item::after {
content: '';
display: inline-block;
width: 2.75rem;
}
.chat-avator {
width: 2.75rem;
height: 2.75rem;
border-radius: 50%;
object-fit: cover;
}
.chat-container {
flex: 1;
text-align: start;
padding: 0 0.625rem;
overflow: hidden;
}
.chat-user {
margin: 0;
font-weight: normal;
font-size: 0.8125rem;
color: #949ead;
}
.chat-user span {
display: inline-block;
}
.chat-time {
padding: 0 0.5rem;
}
.chat-content {
position: relative;
display: inline-flex;
background: #f2f5f9;
border-color: #f2f5f9;
font-size: 0.875rem;
line-height: 1.5;
color: #2c3038;
padding: .6rem 1rem;
text-align: left;
margin: 0.3125rem 0 0;
border-radius: 0.375rem;
}
.chat-content::before {
content: '';
position: absolute;
width: 1.4rem;
height: 1.2rem;
top: 0;
margin-inline-start: -3rem;
border-top-right-radius: 40% 50%;
border-top-left-radius: 40% 50%;
border-left: 0.6rem solid;
border-right: 0.6rem solid;
border-color: inherit;
}
.chat-item[data-chat-self] .chat-content {
background: #00afff;
border-color: #00afff;
color: #fff;
}
效果如下:
接下来只需要让自己发送的消息靠右并且颠倒文字顺序即可,可以通过 flex-direction 来实现,不过最好的方式是通过 direction: rtl 来改变文档流:
.chat-item[data-chat-self] {
direction: rtl;
}
效果如下:
到这里基本就完成了整个页面的布局,想要继续优化的话,可以从自适应屏幕宽度入手,之前可以通过 js 动态计算根元素的 font-size 大小,现在使用 media 就可以实现这个效果了:
html{
font-size: 16px;
}
@media screen and (min-width: 375px) {
html {
/* iPhone6 的 375px 尺寸作为 16px 基准,414px 正好 18px 大小 */
font-size: calc(100% + 2 * (100vw - 375px) / 39);
font-size: calc(16px + 2 * (100vw - 375px) / 39);
}
}
@media screen and (min-width: 414px) {
html {
/* 414px ~ 1000px 每 100 像素宽字体增加 1px(18px ~ 22px) */
font-size: calc(112.5% + 4 * (100vw - 414px) / 586);
font-size: calc(18px + 4 * (100vw - 414px) / 586);
}
}
@media screen and (min-width: 600px) {
html {
/* 600px ~ 1000px 每 100 像素宽字体增加 1px(20px ~ 24px) */
font-size: calc(125% + 4 * (100vw - 600px) / 400);
font-size: calc(20px + 4 * (100vw - 600px) / 400);
}
}
@media screen and (min-width: 1000px) {
html {
/* 1000px 往后是每 100 像素增加 0.5px */
font-size: calc(137.5% + 6 * (100vw - 1000px) / 1000);
font-size: calc(22px + 6 * (100vw - 1000px) / 1000);
}
}
效果如下:
可以看到,随着屏幕尺寸的减小,整体内容都在不断的变小。
结束语
这一次的小测主要考察我们的综合素质,所以并没有太多的细节可讲,这里贴一下张老师总结出来的几个关键点:
- 基准字号使用 16px,不用其它像素值。也不用使用 100px
media查询和vw技巧实现html基础尺寸动态化(无需JS)- 要有统一的类名命名空间,类似
chat- - 遇到不同性质的命名,通常两种方式
- 类名,但是命名上明显区分,例如
chat-item__left - 使用属性选择器
- 类名,但是命名上明显区分,例如
- 避免没必要的嵌套,百害无一益
- 小尾巴的实现。边框+圆角,
box-shadow+圆角,径向渐变 - 左右对称布局的实现:
direction: rtl配合 CSS 逻辑属性 - 不推荐使用 dl 标签,可以给每个列表增加
tabindex=0
最后 在线 Demo 在这里