让页面无懈可击!关于 CSS,你该做好这 20 件事

当前CSS开发的现状不容乐观,扫了一圈,发现各种问题。前端开发更多关注点还是在JavaScript上,技术性相对更强。

关注公众号 前端开发博客,领27本电子书

回复加群,自助秒进前端群

但从前端技术的根本价值出发,实现高可用性的产品用户界面,是用户体验的第一道关,这就跟CSS开发的专业性紧密相关了。轻易改变一下窗囗大小,放大一下字体,页面就被拉垮,这样的产品品质高吗?

本文将涉及一些响应式开发内容,TOB产品同样需要响应式开发。以云安全中心为例,用户屏幕分辩率占比中1920x1080和2560x1440加起来达到52%。平时开发的15寸的本物理分辩率是1440x900只占9%。说明我们的企业用户大多用PC或用外接显示器。请注意:屏幕物理分辨率≠浏览器窗囗大小(如下图)。平时用外接显示器会有各种用法,横着用,坚着用,分屏显示窗囗等等(如封面)。因此,不能简单的依据屏幕分辨率进行设计和开发。我认为体现CSS开发专业性看的就是防御式CSS开发。

5a9f2d2b42b26ccebe98fa09cbe1530e.png25ba18eb5c04043c868b95b742544a99.png

(数据来自css-tricks)

“防御性编程(Defensive programming)是防御式设计的一种具体体现,它是为了保证,对程序的不可预见的使用,不会造成程序功能上的损坏。它可以被看作是为了减少或消除墨菲定律效力的想法。”(引自wiki) 

现在前端开发还是契约式的,也就是还原设计稿,这是远远不够的。设计稿往往只体现出UI的理想态。防御式CSS开发一部分是为了实现响应式设计,同时还包括适配动态内容,在各种情景下保持UI的完美性和健壮性。

1. 采用扁平化的HTML结构,用CSS控制布局

1-1. 避免用“布局组件”

这样会把模块限死在HTML结构中,不利于灵活的适配。

164d6e6f53e13b6d351d4900acb650e5.png
image.png

HTML的结构设计是基本前提,避免“表格思维”,避免多余的行 / 列元素(过度包装元素)。

如,这样设计:

<div class="overview-content">
  <div class="sky-card overview-card">...</div>
  <div class="sky-card overview-card security-defense-card">...</div>
  <div class="sky-card overview-card">...</div>
  <div class="sky-card overview-card">...</div>
</div>

1-2. 不要用JavaScript控制布局

线上问题:

b3064f36b177079ef4ede9702fda4ce9.gif

用CSS实现同样的效果:

f76fa3487fd648fef752da1a5becfa43.gif

2. 避免用float / position: absolute / display: table等方式布局

所有布局和对齐需求,无一例外用 Flexbox / Grids 实现。

3. 避免定高/定宽,用min-width/min-height替代

固定宽/高最容易出现的问题是内容溢出。没必要通过定宽高对齐,可以利用Flexbox的位伸/收缩特性。可以定义最小宽/高。

4. 避免侵入性(损人利自己)的写法

  • 避免影响全局样式,如:* { ... }:root {...}div { ....}等。

  • 避免影响通用组件样式,如:.next-card {...},如果要定制单加一个class名。

  • 不要直接修改全局CSS变量,把自己的CSS变量定义在模块的范围内。

  • 不要写z-index:999。一般1~9,防止被遮挡10~99,绝对够用了。

  • 不要在标签上定义style属性。不要在JS代码中做样式微调,这样今后无法统一升级CSS样式。

  • 只有完全不可修改的样式才能用!important,利用选择器优先级调整样式。

5. 避免CSS代码的误改 / 漏改

  • 将选择器拆开写,如.card-a, .card-b { ... },写时方便,改时难,修改时容易影响其它元素,不如分开写(除非像css reset这种特别确定的情况)。

  • 将样式集中在一起,容易改错。保持CSS代码和文件在相应的层级上,同一模块的放一起。避免混入通用样式中,为了避免改错,允许适当冗余。

  • 用@media时,会集中覆写一批元素的样式,更新样式时非常容易遗漏。所以必须拆开写,和对应模块的样式放在一起。不要集中放在文件底部,或是集中放在某一个文件里。

  • 及时清除“死代码”。

  • 定义样式要写全,微调样式要写具体,如:

.mod {
  margin: 0;
}

/* 其它地方需要微调时 */
.biz-card .mod {
  margin-bottom: 16px;
}

6. 避免CSS样式冲突

  • 限定作用范围。如,.my-module .xxx { ... }

  • 业务代码中的样式要加前缀,或借鉴BEM命名方式。如:.overview-card-title { ... }。用CSS Module也可以。

  • 注意选择器的精确性。级层过长过于复杂的CSS选择器会影响性能,但要注意:有时需要精确选择某些元素,如仅选择一级子元素,.overview-card-content > .item { ... }

7. 防止内容不对齐

受字体、行高等因素影响(如图),用Flexbox实现对齐最可靠:

  • height / line-height 不可靠。

  • display:inline-block / vertical-align:middle 不可靠。

b7d3b29ea2bfd63f50dc10a6293a8a5b.pnge5079c2954ae06b66d23363abf092e95.png

用Flexbox实现对齐

0e56c7bfc2375440ad0f78b6f09e58d4.png60ad88112e92a2c9f27f2e5dad07be09.png

8. 防止内容溢出

包括文字/图表等内容在宽度变化时或是英文版下容易出现溢出(如图)。

0c14ca227606766e53048acd343142c9.png
image.png
  • 图表要支持自动 resize。

  • 图片要限制大小范围,如:max-width、max-height min(100px, 100%)、max(100px, 100%)

注意:min() / max() 兼容性:chrome 79+ / safari 11 / firefox 75

d9b1f6004438d2fb6b028085878190b1.png
image.png
  • 不能固定宽/高。(见规则3)

  • 不要在容器元素定义overflow:hidden

9. 防止内容过度拥挤

为了防止内容过长时紧帖到后面的内容,水平排列元素之间要设置间距,一般是8px。

06aaea790c817ea471fbb471a2e6bf0c.png
image.png

如果用flexbox要加上gap。考虑到gap的兼容性:chrome 84,稳定起见用margin。

a8527d9d597988648f76c32cb78bbcf8.png
image.png
.item {
  margin: 0 8px 0 0;
}
.item:last-child {
  margin-right: 0;
}

10. 防止内容被遮挡

定义负值时(负margin / top / left),小心内容被遮挡,避免这么定义。定义margin统一朝一个方向,向下和向右定义,再重置一下:last-child。position: relative 平时很常用,发生遮挡时会造成链接无法点击(如图)。

432013229a9ece66221654ee0a830769.gif

11. 防止可点击区域过小

小于32x32像素的可点击元素,通过下面的方式扩大可点击区域:

7e2a2c847a21332ef808e3ca62347172.gif
.btn-text {
  position: relative;
}
/* 比 padding 副作用小 */
.btn-text::before {
  content: '';
  position: absolute;
  top: -6px;
  left: -8px;
  right: -8px;
  bottom: -6px;
}

12. 防止内容显示不全 / 被截断

  • 在定义overflow:hidden时,就要考虑内容是否有被截断的可能。一般不要加在容器元素上。

  • 防止长文字被生生截断(如图),加省略号。

ce2a3b19a59c9bbb0dbfa4ae930c8551.png
线上问题
overflow: hidden; 
text-overflow: ellipsis; 
white-space: nowrap;

不想折行,溢出加省略号,这都没问题。但忽略了对inline元素无效,所以要再加一条display: block

13. 防止该折行不折行 / 不该折行的折行

首先必须理解UI,有3种情况:哪些需要折行,哪些不能折行,哪些不能从中间断行。

  1. 大部分情况需要折行,不能为了保持UI美观而损失内容的完整性。

一般用overflow-wrap,尽量不要用word-wrap(不符CSS标准):overflow-wrap: break-word配合overflow-wrap,可再加上hyphens: auto(目前兼容性不够)

限定多行:-webkit-line-clamp: 3

  1. 不能折行,如标题 / 列头 / 按钮等。开发中要理解内容,哪些元素不应该折行。

f22962f59f719702343c7a7320c3758d.png
image.png
overflow: hidden; 
text-overflow: ellipsis; 
white-space: nowrap;

表格列数过多(>5列)时,会要求锁列,此时,th 定义 white-space: nowrap 强制不折行

  1. 不能从中间断行的情况(如图)

2687f043b870724aac195647df8ed74c.png
image.png

14. 防止滚动链问题

浮层的场景下需要避免滚动链问题:子元素可滚动,如果父元素也有滚动区域,在子元素上滚动时,触顶/触底后,会影响父元素滚动。关掉浮层后,用户会发现页面滚到了其它位置。

优化前优化后
919045afc6f937bb93c7975b15ceb275.gif

163631fc1c96a0e417ef05ee6e083eef.gif


overscroll-behavior: contain;
overflow-y: auto;
overflow-x: hidden;

注意:避免出现同时出现水平/垂直滚动条 兼容性:chrome 63+ / firefox 59+ / safari和edge不支持

15. 防止图片变形

图片被置于特定比例的容器中时,固定宽/高和约束最大宽/高,都可能会导致图片变形。

f3e21d9a8b18cf34249b0d31e37ed0fa.png
image.png
.head img {
  width: 100%;
  height: 100%;
}
5f8ff457ec2fbb3dbce573ffcf325301.png
image.png
.head img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

在Flexbox容器内,图片高度会被自动拉伸。因为不定义align-items,默认是stretch。

2d18650a9ff8ef560f0d6be5a393b187.png
image.png
324cc8cda2402369f34ac3d3821bc11d.png
image.png

16. 防止图片加载失败

需要考虑图片加载慢或加载失败的情景。在图片的容器上加边或加底色。

e7d5f60c4610c0228b3e7414ff96e7c7.png04f08ee2c8c1cf97c051f2d3673c0175.png

.head {
  background: #eee;
  box-shadow: inset 0 0 0 1px #aaa;
}

17. 防止CSS变量未引入

在标准化开发中,我们提倡使用全局的CSS变量。业务代码中,利用CSS变量也可以方便的进行全局的控制。在使用CSS变量时要加上缺省值。

font-size: var(--tab-item-text-size-s, 12px);

18. 防止CSS兼容性问题

  • 不要加浏览器厂商前缀,让CSS预编译自动处理,像-webkit-、-moz-。

  • 不要用仅特定浏览器厂商支持的属性。

19. Flexbox常见防御性写法

Flexbox的默认表现比较多,不能简单的定义display:flex,或是flex:1。

  1. Flexbox容器元素通常要做如下定义:要支持多行(默认是单行),交叉轴上垂直居中(默认是stretch),主轴上采用space-between,将自由空间分配到相邻元素之间。

display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
  1. Flexbox的盒子元素,不要固定宽/高,更不要指定百分比的值。Flexbox会自动拉伸/收缩盒子元素,能够精确到浮点数,指定具体值会破坏原本的“弹性”。

  2. Flexbox的盒子元素要定义间距。

案例分析:

1f7ea098a7bb6203075bf1e518deb99e.gif

优化后:

a516b3ca62e50120aa8da13409f151df.gif

参考代码,总结用法:

.new-overview-v2-center-box .left .top {
  /* position: relative; */
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  /* height: 100%; */
}

.new-overview-v2-center-box .left .top .item {
  /* width: 25%; */
  flex: 1;
  min-width: max-content;
  margin: 0 8px 8px 0;
}

20. Grid常见防御性写法

  • 不固定网格的宽度,用minmax(最小值,1fr)。

  • 定义间距grid-gap: 8px。

  • 不固定列数, 利用auto-fit / auto-fill自动适配(如图)。

6244e4d72f8822db06a7432a3de989a1.gif
.wrapper {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
  grid-gap: 8px;
}

.item {
  border: 2px solid #aaa;
  box-sizing: border-box;
  min-height: 128px;
}

最后

我是小前端,欢迎大家围观我的朋友圈,搞搞技术,吹吹牛逼。我的微信:kujian89,秒添加,回复加群,可以进入 500人前端群。

f61454e530bb081f3c09db4fbdf0c789.png

4c158e570b5ff1d34f6e3d5ab14aff7f.png

关注公众号:前端开发博客

  1. 回复「小抄」,领取Vue、JavaScript 和 WebComponent 小抄 PDF

  2. 回复「Vue脑图」获取 Vue 相关脑图

  3. 回复「思维图」获取 JavaScript 相关思维图

  4. 回复「简历」获取简历制作建议

  5. 回复「简历模板」获取精选的简历模板

  6. 回复「加群」进入500人前端精英群

  7. 回复「电子书」下载我整理的大量前端资源,含面试、Vue实战项目、CSS和JavaScript电子书等。

  8. 回复「知识点」下载高清JavaScript知识点图谱

 👍🏻 点赞 + 在看 支持小编

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值