笔记--《CSS揭秘》第1章

318 阅读11分钟

CSS编码技巧

尽量减少代码重复

css同样需要保持DRY(Don't Repeat Yourself)和可维护性,而代码可维护性的最大要素是尽量减少改动时要编辑的地方

如:给一个按钮添加效果

padding: 6px 16px;
border: 1px solid #446d88;
background: #58a linear-gradient(#77a0bb, #58a);
border-radius: 4px;
box-shadow: 0 1px 5px gray;
color: white;
text-shadow: 0 -1px 1px #335166;
font-size: 20px;
line-height: 30px;

image.png

要达到放大按钮的效果,最直观就是字体尺寸部分了,改变字号的同时调整行高。当某些值相互依赖时,应该把它们的相互关系用代码表达出来。

font-size: 125%; /* 假设父级的字号是 16px */
line-height: 1.5; /* 行号是字号的1.5倍 */

如果要放大按钮的效果,同时需要改动的地方不少,因为涉及整体的放大,不只是字号跟行高。但是如果我们把字号定为绝对长度值(如:20px),每当要修改的时候就特别麻烦。例如:如果我们把父级的字号加大,那就得改每一次使用绝对值作为字体尺寸的样式了。可以改用百分比或者em单位。

padding: .3em .8em;
border: 1px solid #446d88;
background: #58a linear-gradient(#77a0bb, #58a);
border-radius: .2em;
box-shadow: 0 .05em .25em gray;
color: white;
text-shadow: 0 -.05em .05em #335166;
font-size: 125%;
line-height: 1.5;

注意:需要重新审视到底哪些效果应该跟着按钮一起放大,而哪些效果是保持不变的

看回上面的例子,需要做放大的部分padding、border-radius、text-shadow、box-shadow,把这些的长度值都改成em值,就可以依赖字号进行缩放,达到在一处控制按钮的所有尺寸效果。

  • 在CSS中,相关性是一个很重要的特性,但是得想清楚到底哪些东西是真正相关的。

image.png

在做效果的时候,按钮不止变大变小,颜色也是一个要考虑的地方。假设要创建不同颜色的按钮,就可能需要覆盖四条声明(border-color、background、box-shadow 和 text-shadow)。

要根据按钮的亮面和暗面相对于主色调变亮和变暗的程度来分别推导出其他颜色各自的亮色和暗色版本。此外,若我们想把按钮放在一个非白色的背景之上呢?显然使用灰色(gray)作投影只适用于纯白背景的情况。如果只直接改背景颜色效果如下:

image.png

image.png

可以看出,每次修改背景都要改三个地方的色值,而且还要去计算颜色的色值。但是如果做以下的优化,只需要改变背景颜色即可:

.btn {
      padding: .3em .8em;
      background: #58a linear-gradient(hsla(0,0%,100%,.2),transparent);
      border-radius: .2em;
      box-shadow: 0 .05em .25em rgba(0,0,0,.5);
      text-shadow: 0 -.05em .05em rgba(0,0,0,.5);
      color: white;
      font-size: 125%;
      line-height: 1.5;
    }
    .ok {
      background-color: #6b0;
      /*background: #6b0 linear-gradient(#77a0bb, #6b0)*/
   }

小提示:推荐使用 HSLA 而不是RGBA 来产生半透明的白色,因为它的字符长度更短,敲起来也更快。这归功于它的重复度更低。(HSLA以后展开研究一下

不同背景下的效果:

1631441711(1).png image.png image.png

这样设计出来的按钮是不是灵活很多~~~

代码易维护 vs. 代码量少

有时候,代码易维护和代码量少不可兼得。如:

  • 代码量少,但是不好维护,以后要改动边框的宽度,需要同时改三个地方
border-width:10px 10px 10px 0;
  • 只需改一个地方
border-width: 10px;
border-left-width: 0;

currentColor

是CSS3新增的一个颜色关键字,它是从SVG那里借鉴来的。这个关键字没有绑定一个固定的颜色值,而是根据color的值来确定,如果没有定义就根据父级的color值。这个属性可以用在所有能够接受color值的地方。

如:

image.png

image.png image.png

image.png

image.png

实际上,这个特性让它成为了CSS中有史以来的第一个变量。它会在没有给属性定义颜色时,自动地从文本颜色那里得到颜色。

继承

inherit可以用在任何CSS属性中,而且它总是绑定到父元素的计算值(对伪元素来说,则会取生成该伪元素的宿主元素) 如:设定表单元素的字体与页面其他部分相同

input,select,button{ font:inherit; }

把超链接的颜色设定为页面中其他文本相同

a{color:inherit;}

从父元素那里获取背景色和边框样式

.callout { position: relative; }
.callout::before {
content: "";
position: absolute;
top: -.4em; left: 1em;
padding: .35em;
background: inherit;
border: inherit;
border-right: 0;
border-bottom: 0;
transform: rotate(45deg);
}
  • 由以上例子可以看出,继承不止用在字体,还可以用在背景、边框等属性上

相信你的眼睛,而不是数字

我们的眼睛在看到一个完美垂直居中的物体时,会感觉它并不居中。实际上,我们应该把这个物体从几何学的中心点再稍微向上挪一点,才能取得理想的视觉效果。

image.png

圆形的字形(比如 0)与矩形字形相比,需要稍微放大一些,因为我们倾向于把圆形感知得比其实际尺寸更小一些。

image.png

字母的形状在两端都比较整齐,而顶部和底部则往往参差不齐,从而导致你的眼睛把这些参差不齐的空缺部分感知为多出来的内边距。

image.png image.png

关于响应式网页设计

比较常见的实践是用多种分辨率来测试一个网站,然后添加越来越多的媒体查询(Media Query)规则来修补网站在这些分辨率下出现的问题。然而每个媒体查询都会增加成本,添加的媒体查询越多,你的CSS代码就会变大越来越经不起折腾。

这并不是说媒体查询是一种不良的实践。只要用对了,它就是利器,但是只应该把它作为最后的手段。 其工作原理基于某几个特定的阶梯(亦称“断点”)。

媒体查询的断点不应该由具体的设备来决定,而应该根据设计自身来决定。。这不仅是因为我们的网站需要面向的设备太多了(尤其是考虑到未来的设备时),还因为一个网站在桌面端可能会以任意尺寸的窗口来显示。

以下建议,可以帮助避免不必要的媒体查询:

  • 使用百分比长度来取代固定长度,或使用与视口相关的单位(vw、vh、vmin和vmax)
  • 当需要在较大分辨率下得到固定宽度时,使用max-width而不是width
  • 不要忘记为替换元素(如:img、object、video、iframe等)设置一个max-width,值为100%
  • 假如背景图片需要完整地铺满一个容器,不管容器的尺寸如何变化,background-size: cover 这个属性都可以做到。但是,我们也要时刻牢记——带宽并不是无限的,因此在移动网页中通过 CSS 把一张大图缩小显示往往是不太明智的。
  • 当图片(或其他元素)以行列式进行布局时,让视口的宽度来决定列的数量。弹性盒布局(即 Flexbox)或者 display: inline-block加上常规的文本折行行为,都可以实现这一点。
  • 在 使 用 多 列 文 本 时, 指 定 column-width( 列 宽 ) 而 不 是 指 定column-count(列数),这样它就可以在较小的屏幕上自动显示为单列布局。

总的来说,实现弹性可伸缩的布局,并在媒体查询的各个断点区间内指定相应的尺寸

当你发现需要一大堆媒体查询才能适应大大小小的屏幕,那么重新审视你的代码结构了。

合理使用简写

以下两行CSS代码并不是等价的:

background: rebeccapurple;
background-color: rebeccapurple;

前者是简写,它可以确保你得到rebeccapurple 纯色背景;

image.png

但如果你用的是展开式的单个属性(background-color),那这个元素的背景最终有可能会显示为一个粉色的渐变图案、一张猫的图片或其他任何东西,因为同时可能会有一条 background-image 声明在起作用。

image.png image.png

rebeccapurple是CSS4新增的属性 image.png

但是如果把所以的展开属性都设置一遍,工作量增加,还有可能漏掉几个,又或者在未来增加了新的展开式属性,那么你的代码就无法完全覆盖它们了。

合理使用简写是一种良好的防卫性编码方式,可以抵御未来的风险。当然,如果我们要明确地去覆盖某个具体的展开式属性并保留其他相关样式,那就需要用展开式属性。

展开式属性与简写属性的配合使用也是非常有用的,可以让代码更加DRY。

image.png

image.png

CSS 的“列表扩散规则”:如果只为某个属性提供一个值,那它就会扩散并应用到列表中的每一项。

background多个url是什么效果呢?像ps一样有多层图层,但是要背景透明才能看出来,也得注意图层的优先级。

image.png image.png

image.png

我应该使用预处理器吗

CSS预处理器:StylusSassLESS。它们为 CSS的编写提供提供了一些便利,比如变量、mixin、函数、规则嵌套、颜色处理等。如果使用得当,它们在大型项目中可以让代码更加灵活,而 CSS 自身在这方面确实有很大局限。

但是预处理器也不是完美无缺的,也会存在一些问题:

  • CSS 的文件体积和复杂度可能会失控。
  • 调试难度会增加,因为你在开发工具中看到的 CSS 代码并不是你写的源代码。不过这个问题已经大大好转了,因为已经有越来越多的调试工具开始支持 SourceMap。SourceMap 是一种非常酷的新技术,正是为了解决这个痛点而生的,它会告诉浏览器哪些编译生成的CSS 代码对应哪些预处理器 CSS 代码,精确到行号。
  • 预处理器在开发过程中引入了一定程度的延时。
  • 每次抽象都必然会带来更高的学习成本,每当有新人加入到我们的代码库中,这个问题都会重演。他要么已经对我选择的这门预处理器“方言”很熟悉,要么得从头学。这意味着我们要么强制协作者接受我们的选择,要么花费额外的时间来培训,而这两者都不是我们想要的。
  • 另外,别忘了还有抽象泄漏法则:“所有重大的抽象机制在某种程度上都存在泄漏的情况。”预处理器是由人类写出来的,就像所有由人类写出来的大型程序一样,它们有它们自己的 bug。这些 bug 可能会潜伏很久,因为我们很少会怀疑预处理器的某个 bug 才是我们CSS 出错的幕后元凶。 除了上面列出的这些问题,预处理器还可能导致这种风险:网站开发者可能会不自觉地“依赖”和“滥用”。现在很多预处理器的特性逐渐开始融入原生CSS中了,也许在未来那些受欢迎的预处理器特性,CSS都可以支持了。这些原生特性通常比预处理器提供的版本要强大得多,因为它们是动态的(原生 CSS 特性也可以通过脚本来操) 例子
  • 预处理器完全不知道如何完成 100% - 50px 这样的计算,因为在页面真正被渲染之前,百分比值是无法解析的。但是,原生CSS 的 calc() 在计算这样的表达式时没有任何压力。
  • 预处理器不能做到的变量玩法
ul { --accent-color: purple; }

ol { --accent-color: rebeccapurple; }

li { background: var(--accent-color); }

建议:在每个项目开始时使用纯 CSS,只有当代码开始变得无法保持 DRY 时,才切换到预处理器的方案。为了避免可能发生的“依赖”或“滥用”,在引入预处理器的问题上需要冷静决策,不应该在每个项目一开始时就不动脑筋顺着惯性来。