CSS 编码技巧
在软件开发中,保持代码的 DRY 和可维护性是最大的挑战之一。
-
DRY:Don't Repeat Yourself 不要重复你自己
-
可维护性:尽量减少改动时要编辑的地方
举一个例子:
html1<button>Yes!</button>
css1button { 2 padding: 6px 16px; 3 border: 1px solid #446d88; 4 background: #58a linear-gradient(#77a0bb, #58a); 5 border-radius: 4px; 6 box-shadow: 0 1px 5px gray; 7 color: white; 8 text-shadow: 0-1px 1px #335166; 9 font-size: 20px; 10 line-height: 30px; 11}

这是一个 button 按钮,假设我想要修改它的字体大小,得到一个更大的按钮,我可以直接设置 font-size,但是仅仅设置了 font-size 显然不够,比如下面我将其设置为font-size:30px;

这样行高和字号的比例就不正确了。
依赖关系表达
当某些值相互依赖的时候,我们应该把他们的相互关系用代码表达出来
这里的 line-height 和 font-size 是具有相互关系的,比例大概是 1.5 比 1。
所以我们可以这样写
css1font-size: 30px; 2line-height: 1.5;
line-height 设置成数字或者百分比的时候,会自动根据该元素的字体大小进行计算。
设置 line-height 的推荐写法是设置成数字,不会在继承时产生不确定的结果。 ——MDN
尽量不写绝对值
绝对值写起来非常容易,但是如果要修改时,有可能会非常麻烦。比如在这个按钮上,我们有可能会遇到修改 padding、border-radius 的需求,如果全部用 px 这种绝对值单位书写,那需要修改的地方就非常多。
在 css 中,我们可以用 vw、vh、rem、em、百分比等单位替代绝对值。
css1button { 2 padding: 0.3em 0.8em; /* 父盒子的 font-size 是16px */ 3 border: 1px solid #446d88; 4 background: #58a linear-gradient(#77a0bb, #58a); 5 border-radius: 0.2em; 6 box-shadow: 0 0.05em 0.25em gray; 7 color: white; 8 text-shadow: 0-0.05em 0.05em #335166; 9 font-size: 125%; 10 line-height: 1.5; 11}
现在我们如果想要把按钮放大,那它的所有效果也都跟着放大了。
代码易维护 vs 代码量少
有时候,代码量少和代码易维护不可兼得。假设我们需要给元素添加一道 10px 的边框,但是左边不加边框
css1border-width: 10px 10px 10px 0;
这样代码只需要一行就可以搞定,但是如果以后需要改成 20px 宽呢?就需要修改 3 个地方。
此时只要分开申明,就可以只修改一个地方,而且可读性更高。
css1border-width: 10px; 2border-left-width: 0;
currentColor
currentColor 是 css 中第一个变量,它表示当前的标签所继承的文字颜色
举个例子:
css1button { 2 padding: 0.3em 0.8em; 3 border: 1px solid currentColor; /* 看这里 */ 4 color: white; /* 看这里 */ 5 background: #58a linear-gradient(#77a0bb, #58a); 6 border-radius: 0.2em; 7 box-shadow: 0 0.05em 0.25em gray; 8 text-shadow: 0-0.05em 0.05em #335166; 9 font-size: 125%; 10 line-height: 1.5; 11}
此时字体的颜色是白色的,边框的颜色会跟着字体的颜色变成白色

如果修改成黑色,那么边框就会变成黑色。
css1color: black;

currentColor 是很多属性的初始值(比如 border-color),它会自动根据文本颜色来获取到颜色。
inherit 继承
尽管 inherit 很常见,但是我们还是很容易遗忘它。inherit 可以用在任何 css 属性上,它会绑定到父元素的对应值。
举个例子:当我的 a 标签希望颜色跟页面的其他部分(父元素等)相同时,可以考虑使用 inheirt的特性
css1a { 2 color: inherit; 3}
对于伪元素来说,inherit会取生成该伪元素的宿主元素。
同时,这个 inherit 关键字对于背景颜色和边框等同样有效。
html1<div>这是一个框</div>
css1div { 2 position: relative; 3 max-width: 200px; 4 border: 1px solid black; 5} 6div::before { 7 content: ''; 8 display: block; 9 width: 0; 10 height: 0; 11 border: 10px solid transparent; 12 border-bottom-color: inherit; /* 看这里 */ 13 border-top: none; 14 position: absolute; 15 top: -40%; 16 left: 0.5em; 17}

把媒体查询当做最后的优化手段
响应式网页设计非常重要,但不应过多采用媒体查询,每个媒体查询都会增加成本,这种成本会随着代码的提升,在后期维护时突显出来。
媒体查询不能以一种连续的方式来修复问题,它能做的只是修补某个特定分辨率下的特定问题。
不妨考虑在媒体查询中使用 em 等非绝对单位来取代像素单位。这能让文本缩放在必要时触发布局的变化。
响应式网页设计的建议
下面是响应式网页设计的一些建议,它能够帮助我们避免不必要的媒体查询
-
使用百分比长度来取代固定长度,或者使用与视口相关的单位(vw、vh、vmin、vmax)等解析视口宽度或高度的百分比
-
当需要在较大分辨率下得到固定宽度时,使用
max-width而不是 width,它能适应较小的分辨率。 -
为替换元素(img、video、iframe 等)设置一个
max-width,值为 100% -
背景图片需要完整地平铺一个容器,不管容器的尺寸如何变化,使用
background-size:cover可以做到 -
当图片或者其他元素以行列式进行布局时,让视口的宽度来决定列的数量,可以用弹性盒子布局(
FlexbOX) -
在使用多列文本时,指定 column-width(列宽)而不是指定 column-count(列数),这样它可以在较小的屏幕上自动显示为单列布局。
总得来说,我们的思路是尽可能实现弹性可伸缩的布局,并且在媒体查询的各个区间内指定响应的样式。
当网页的设计足够灵活时,让它变成响应式只需要用到一些简短的媒体查询。
想让网页在一堆不同的设备上合理展示,只需要在最终产品上添加一点 CSS 媒体查询就可以了。这件事情之所以这么简单,关键在于我们的布局原本就是弹性可伸缩的。因此,优化网页在小屏幕上的表现,其实只意味着把一些外边距收拢到最小程度,然后把因为屏幕太窄而无法显示成双列的侧栏调整为单列布局而已。——在 Iterations 中实践响应式设计
合理使用简写
下列两行 css 代码并不是等价的
css1background: red; 2background-color: red;
前面是简写,它可以确保我们得到红色的背景颜色。
后者是展开式单个属性,它并不能帮助我们清空其他相关的所有属性,有可能会干扰我们得到想要的效果。
合理使用简写,是一种良好的防卫性编码方式。当然,如果我们明确需要覆盖某个属性的展开式属性并保留其他样式,那就需要用展开式属性来书写代码。
展开式属性和简写属性的配合使用也非常有用,比如以下代码
css1background: url(tr.png) no-repeat top right / 2em /2em, url(tr.png) no-repeat top left / 2em /2em, 2 url(tr.png) no-repeat bottom right / 2em /2em;
background-size 和 background-repeat 的值被重复了三遍,尽管每层背景的这两个值确实是相同的。
CSS 扩散规则表明:如果只为某个属性提供一个值,那它就会扩散并应用到列表中的每一项。
因此,我们可以抽离出重复的内容
css1background: url(tr.png) top right, url(tr.png) top left, url(tr.png) bottom right; 2background-size: 2em 2em; 3background-repeat: no-repeat;
现在,我们只需要改一个地方就可以控制 background-size 和 background-repeat 了