首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >《CSS揭秘》读书总结:背景与边框

《CSS揭秘》读书总结:背景与边框

作者头像
逆葵
发布2019-04-25 11:16:04
1.7K0
发布2019-04-25 11:16:04
举报
文章被收录于专栏:FECodingFECoding

前言: 本系列是阅读《CSS揭秘》所作的总结,用以提高知识吸收程度。同时该书本身便是以解决 47 个 CSS 技巧而进行组织的,总结归纳后方便日后查找。

1. 半透明边框

难题

在 CSS 中使用半透明颜色,可以使用 rgba() 和 hsla()。

HSL代表色相,饱和度和亮度 - 使用色彩圆柱坐标表示。 HSL颜色值指定:HSL(色调,饱和度,明度)。 色相是在色轮上的程度(从0到360)-0(或360)是红色的,120是绿色的,240是蓝色的。饱和度是一个百分比值;0%意味着灰色和100%的阴影,是全彩。亮度也是一个百分点;0%是黑色的,100%是白色的。

HSLA的颜色值是一个带有alpha通道的HSL颜色值的延伸 - 指定对象的透明度。 指定HSLA颜色值:HSLA(色调,饱和度,亮度,α),α是Alpha参数定义的不透明度。 Alpha参数是一个介于0.0(完全透明)和1.0(完全不透明)之间的参数。

尽管半透明颜色很受欢迎,但人们对其使用更多集中于背景上。

假设我们想给一个容器设置一层白色背景和一道半透明白色边框,body 的背景会从它的半透明边框透上来。我们最开始的尝试可能是这样的:

border: 10px solid hsla(0,0%,100%,.5); 
background : white;

结果如下,边框不见了:

解决方案

默认状态下,背景会延伸到边框的区域下层,结合下面绿色背景虚线边框的图比较好理解:

这就可以解释我们遇到的难题:body 的背景并没有从内部 content 的半透明的白色半透明边框处透上来,而是在半透明白色边框处透出了这个容器自己的纯白实色背景,这实际上得到的效果跟纯白实色的边框看起来完全一样。

如果要解决这个问题,可以使用 CSS 3 中的 background-clip 属性来进行调整。该属性初始值为 border-box,意味着背景会被元素的 border box(边框的外沿框)裁切掉,如果设置为 padding-box,这样浏览器就会用内边距的外沿来把背景裁切掉。

我们修改代码如下:

border: 10px solid hsla(0,0%,100%,.5); 
background : white; 
background-clip : padding-box;

效果如下:

2.多重边框

难题

多重边框的实现很长时间内都需要各种丑陋的 hack,比如使用多个元素来模拟多重边框。在 CSS 代码层面对多重边框进行灵活的调整看起来非常困难。

解决方案

  1. box-shadow 方案 box-shadow 可以接受 6 个参数,如下表所示:

当我们将 spread 属性设为正值,h-shadow、v-shadow 和 blur 均设置为 0,得到的“投影”就像一道实线边框: background : yellowgreen; box-shadow : 0 0 0 10px #655; 效果如下:

使用 border 也可以实现同样的效果,但 box-shadow 的优势在于:它支持逗号分隔语法,这意味着其可以创建任意数量的投影,所以也就可以创建任意数量的边框。这里在上面的基础上添加一道边框: background: yellowgreen; box-shadow: 0 0 0 10px #655, 0 0 0 15px deeppink; 效果如下:

有一处需要注意,box-shadow 是层层叠加的,因此需要按此规律调整 spread 值。比如,上面第一层边框的 spread 值为 10 px,则宽度为 10 px;如果第二层边框的宽度需要设置为 5px,则第二个 box-shadow 的spread 值需要设置为 (10 + 5)即 15 px。 注:

  • 投影的行为跟边框不完全一致,因为它不会影响布局,而且也不会受到 box-sizing 属性的影响。如有需要,可以通过内边距或外边距(这取决于投影是内嵌还是外扩的)来额外模拟出边框所需要占据的空间。
  • 使用 box-shadow 创建的边框,其不会响应鼠标事件, 比如悬停或点击。如果需要使其响应鼠标事件,则可以添加 inset 关键字,使得 box-shadow 创建的边框出现在内圈,然后留出额外的内边距来填补这些空隙。

  1. outline 方案 此方案适用于只创建两层边框的情况。第一层边框使用 border 属性创建,第二层边框使用 outline 属性创建。该方案非常灵活。先看一下 outline 属性可以接受的参数:

对于上面用 box-shadow 实现的两层边框,用 outline 实现的方式如下: background : yellowgreen; border : 10px solid #655; outline : 5px solid deeppink; outline 可以和 outline-offset 配合使用,后者用来控制 outline 和元素边缘之间的距离,该属性可以接受负值,对一层 dashed (虚线)outline 使用负的 outline-offset 后,可以得到简单的缝边效果:

注:

  • outline 只适用于双层边框
  • outline 边框不一定会贴合 border-radius 属性产生的圆角。这种行为被 CSS 工作组认为是一个 bug,因此未来可能会改为贴合 border- radius 圆角。

3. 灵活的背景定位

难题

要求针对容器某个角对背景图片做偏移定位,如右下角。在 CSS 2.1 中,只能指定距离左上角的偏移量,或者靠齐到其他三个角。但是如果希望图片和容器的边角之间能留出一定的空隙,此时便比较难解决。

解决方案

  1. 传统方法
    • 对于固定尺寸的容器,可以基于它自身的尺寸以及我们期望它距离右下角的偏移量,计 算出背景图片距离左上角的偏移量,然后再把计算结果设置给 background- position 。
    • 对于尺寸不固定的容器,上述方案无效。
  2. background-position 的扩展语法方案 background-position 在 CSS 3 中得到扩展,其允许我们指定背景图片距离任意角的偏移量,只要我们在偏移量前指定关键字,比如: background : url(code-pirate.svg) no-repeat #58a; background-position : right 20px bottom 10px; 以上代码表示让背景图片跟右边缘保持 20 px 的偏移量,同时跟底边保持 10px 的偏移量。 对于不支持 background-position 扩展的浏览器,应该为其提供回退方案,在 background 中指定老式的 right bottom 简写值: background : url(code-pirate.svg) no-repeat bottom right #58a; background-position : right 20px bottom 10px;
  3. background-origin 方案 对于 background-position: top left 这样的代码,这里的 top left 是相对于元素的 padding box 的左上角。现在我们使用 CSS 3 新增的 background-origin 属性可以指定矩形框是 content-box、padding-box 还是 border-box。比如: padding: 10px; background: url("code-pirate.svg") no-repeat #58a bottom right; /* 或 100% 100% */ background-origin: content-box ; 当设置 background-origin 为 content-box 时,background-position 属性中使用的边角关键字将会以内容区的边缘作为基准(也就是说,此时背景图片距离边角的偏移量就跟内边距保持一致了)。
  4. calc() 方案 直接上代码: background : url("code-pirate.svg") no-repeat; background-position : calc(100% - 20px) calc(100% - 10px); 以上代码的效果也是让背景图片跟右边缘保持 20 px 的偏移量,同时跟底边保持 10px 的偏移量。 注:在 calc() 函数内部的 - 和 + 运算符的两侧各加 一个空白符,否则会产生解析错误。此举是为了向前兼容: 未来,在 calc() 内部可能会允许使用关键字, 而这些关键字可能会包含连字符(即减号)。

4. 边框内圆角

难题

有时我们需要一个容器,只在内侧有圆角,而边框或描边的四个角在外 部仍然保持直角的形状,如下图所示:

使用两个元素可以实现上述效果,并且很简单:

<div class="something-meaningful"> 
	<div> I have a nice subtle inner rounding, don't I look pretty? </div>
</div>
.something-meaningful { background : #655; padding : .8em; }

.something-meaningful > div { background : tan; border-radius : .8em; padding : 1em; }

但是如果要求用一个元素实现呢?

解决方案

background : tan; 
border-radius : .8em; 
padding: 1em; 
box-shadow : 0 0 0 .6em #655; 
outline : .6em solid #655;

其效果和上面两个元素实现的效果一样。究其原因,正如多重边框一节对 outline 属性介绍时提到的,其并不会贴合 border-radius 属性产生的圆角,但是 box-shadow 会。二者叠加到一起,box-shadow 会刚好填补描边和容器圆角之间的空隙。以下两张图分别是单独使用 outline 和 box-shadow 属性的效果:

我们为 box-shadow 属性指定的扩张值并不一定等于描边的宽度,我们只需要指定一个足够填补“空隙”的扩张值就可以了。这个值具体是多少?看下图:

当圆角半径为 r 时,从圆角的圆心到描边顶角的长度就是 r√2,这意味着投影的扩张半径 spread 值不能小于 r√2 - r = (√2 - 1)r。同时,该值还需要比描边的宽度值小。

5. 条纹背景

难题

目前在网页中实现条纹图案的方式非常繁琐,并且效果往往不够理想。

解决方案

  1. 水平条纹 使用 linear-gradient 属性可以创建基本的垂直渐变,比如: <!--下图一--> background : linear-gradient(#fb3, #58a); <!--下图二--> background : linear-gradient(#fb3 20%, #58a 80%); <!--下图三--> background : linear-gradient(#fb3 40%, #58a 60%); 对应效果:

可以发现,当拉近两个色标时,渐变区域越来越窄。不难想象,如果把两个色标重合在一起,得到的就是两条水平条纹。以下是理论依据: “如果多个色标具有相同的位置,它们会产生一个无限小的过渡区域, 过渡的起止色分别是第一个和最后一个指定值。从效果上看,颜色会在那 个位置突然变化,而不是一个平滑的渐变过程。” ——CSS 图像(第三版)(http://w3.org/TR/css3-images) background : linear-gradient(#fb3 50%, #58a 50%); 对应效果:

在此基础上,我们可以进行一些再加工: <!--可以通过background-size来调整尺寸--> <!--背景默认重复平铺,所以整个容器被两条条纹填满--> <!--如下图一--> background : linear-gradient(#fb3 50%, #58a 50%); background-size : 100% 30px; <!--还可以用相同的方法来创建不等宽的条纹,只需调整色标的位置值即可--> <!--如下图二--> background : linear-gradient(#fb3 30%, #58a 30%); background-size : 100% 30px;

针对上面的代码,还可以有改进方案,理论依据如下: “如果某个色标的位置值比整个列表中在它之前的色标的位置值都要 小,则该色标的位置值会被设置为它前面所有色标位置值的最大值。” ——CSS 图像(第三版)(http://w3.org/TR/css3-images) 所以,如果我们把第二个色标的位置值设置为 0,那它的位置就总是会被浏览器调整为前一个色标的位置值。我们可以把原先这样的代码 background : linear-gradient(#fb3 30%, #58a 30%); 改写成这样: background : linear-gradient(#fb3 30%, #58a 0); 如果要创建超过两条颜色的条纹,也很容易。以下是生成三条条纹的代码: background : linear-gradient(#fb3 33.3%, #58a 0, #58a 66.6%, yellowgreen 0); background-size : 100% 45px; ​

  1. 垂直条纹 垂直条纹相比水平条纹,在 linear-gradient 的开头加一个额外参数来标记其渐变方向即可(在水平条纹中我们没有加这个参数,因为其默认值就是 to bottom,也就是水平条纹的效果): background : linear-gradient(to right, /* 或 90deg */ #fb3 50%, #58a 0); background-size : 30px 100%; 还需要把 background-size 的值颠倒。
  2. 斜向条纹 如果按照常规思维,要实现斜向条纹,改变 linear-gradient 的方向和 background-size 的值,貌似就可以搞定。如果要实现一个 45° 的条纹图案,代码这样写: background: linear-gradient(45deg,#fb3 50%, #58a 0); background-size : 30px 30px; 得到的效果却是:

失败的原因是我们仅仅把每个背景单元作了渐变旋转,而没有站在背景整体的角度来看问题。来看预想的斜向背景的单个背景单元:

可以看到,在一个背景单元里,实际上有四条条纹,这样就可以实现条纹无缝衔接: background : linear-gradient(45deg, #fb3 25%, #58a 0, #58a 50%, #fb3 0, #fb3 75%, #58a 0); background-size : 30px 30px; 关于条纹变成斜向后为何会看起来变瘦了,实际上是因为背景尺寸设置为 30px 时,产生的条纹宽度将是15/√2 ≈ 10.606 像素。如果需要和原先水平或垂直条纹一样的宽度,在其基础上乘以 √2 即可。

  1. 更好的斜向条纹 上面的方案在我们想调整斜向角度时会非常不灵活。这里提供一个更好的方案。首先需要了解的是 linear-gradient() 和 radial-gradient() 各还有一个循环式的加强版:repeating-linear-gradient() 和 repeating-radial-gradient()。其工作方式和前两者类似,只有一点不同:色标是无限循环重复的,直到填满整个背景。比如以下代码: background : repeating-linear-gradient(45deg, #fb3, #58a 30px); 其实相当于: background: linear-gradient(45deg, #fb3, #58a 30px, #fb3 30px, #58a 60px, #fb3 60px, #58a 90px, #fb3 90px, #58a 120px, #fb3 120px, #58a 150px, ...); 效果图如下:

第一个好处就是减少了重复,改动颜色时只需要修改两处。另外一点就是现在是在渐变的色标中指定长度,而不是原来的 background-size。因为这些长度是直接在渐变轴上进行度量的,直接代表了条 纹自身的宽度。所以再也不用进行各种数学计算了。 当需要改变角度为 60° 时,只需要这样: background : repeating-linear-gradient(60deg, #fb3, #fb3 15px, #58a 0, #58a 30px);

  1. 灵活的同色系条纹

当条纹图案由差异不大的颜色组成时,按照上面提供的方法,我们可能需要这样写 CSS: background : repeating-linear-gradient(30deg, #79b, #79b 15px, #58a 0, #58a 30px); 如图:

实际上,在应对这种情况时,我们可以把最深的颜色指定为背景色,同时把半透明白色的条纹叠加在背景色之上来得到浅色条纹: background : #58a; background-image : repeating-linear-gradient(30deg, hsla(0,0%,100%,.1), hsla(0,0%,100%,.1) 15px, transparent 0, transparent 30px);

6. 复杂的背景图案

7. 伪随机背景

8. 连续的图像边框

请支持正版,购买书籍自行查看。

好吧,其实是我觉得这三章内容 focus 的点太小了,感觉了解一下即可。

好吧,其实是我懒得截图整理了,加上确实 focus 的点太小了,所以就偷个懒啦。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 半透明边框
    • 难题
      • 解决方案
      • 2.多重边框
        • 难题
          • 解决方案
          • 3. 灵活的背景定位
            • 难题
              • 解决方案
              • 4. 边框内圆角
                • 难题
                  • 解决方案
                  • 5. 条纹背景
                    • 难题
                      • 解决方案
                      • 6. 复杂的背景图案
                      • 7. 伪随机背景
                      • 8. 连续的图像边框
                      相关产品与服务
                      容器服务
                      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档