TanXinNiao / blog

贪心鸟的博客
0 stars 0 forks source link

CSS权威指南(第4版)第八章 内边距、边框、轮廓和外边距 #18

Open TanXinNiao opened 3 years ago

TanXinNiao commented 3 years ago

你可能已经知道,文档中的每个元素都会生成一个矩形框,我们称之为元素框(element box) o这个框体描述元素在文档布局中所占的空间。因此,元素框之间是有影响的, 涉及位置和尺寸。假如文档中的第一个元素高1英寸,那么下一个元素框至少从文档顶 部1英寸处开始。如果第一个元素的高度变了,变成了 2英寸,那么后续各个元素框都 将向下移动1英寸,因此第二个元素框至少从文档顶部2英寸处开始。

默认情况下,渲染出来的文档中,各矩形框的排布方式在视觉上不会出现重叠。而且, 某些情况下,元素框会尽量占用较少的空间,但是依然留有足够的间隔,能清楚地分清 一部分内容属于哪个元素。

如果元素框是手动定位的,可能出现重叠,此外,在正常流动的元素上应用负的外边距, 也会出现视觉上的重叠。

TanXinNiao commented 3 years ago

基本元素框

内边距的百分数值

元素的内边距可以用百分数值设定。百分数值相对父元素内容区的宽度计算,因此, 如果出于什么原因,父元素的宽度变了,内边距也会变。

p {padding: 10%; background-color: silver;}
<div style®"width: 600px;">
<P>
This paragraph is contained within a DIV that has a width of 600 pixels, so its padding will be 10% of the width of the paragraph's parent element. Given the declared width of 600 pixels, the padding will be 60 pixels on all sides.
</p>
</div>
<div style®"width: 300px;">
<P>
This paragraph is contained within a DIV with a width of 300 pixels, so its padding will still be 10% of the width of the paragraph's parent. There will, therefore, be half as much padding on this paragraph as that on the first paragraph.
</p>
</div>

着父元素宽度的变化,不仅两侧的内边距变了, 上下内边距也变了。这正是CSS定义的行为。回顾这个属性的定义,你应该还记得,百 分数值是相对父元素的宽度计算的。这一点不仅针对左右内边距,也针对上下内边距。 因此,对下述样式和标记来说,段落的上内边距为50像素。

div p (padding-top: 10%;}
<div style="width: 500px;">
<P>
This is a paragraph, and its top margin is 10% the width of its parent element.
</p>
</div>

如果你觉得这种处理方式有点奇怪,可以这样理解:正常流动模式下的多数元素,其高 度恰好够容纳后代元素的内容及其内边距(这也是本章假定的行为)。如果元素的上下 内边距相对父元素的高度计算,为了容纳上下内边距,父元素的高度要增加,而高度变 化后,上下内边距的值又要随之变化,如此一直下去,进入无限循环。但是元素的上下 内边距又不能忽略,因此规范制定人员决定相对父元素内容区的髙度计算上下内边距的 百分数值,原因很简单,父元素的宽度不随后代元素的宽度影响。

TanXinNiao commented 3 years ago

行内元素的内边距

规范允许这么做,但是应用到行内非置换元素上的内边距对行高没有任何影响。因为没 有背景的内边距是透明的,所以上述声明其实没有视觉效果。还是那句话,因为行内非 置换元素的内边距对元素的行高没有影响。

但是要小心,如果行内非置换元素有背景色和内边距,其背景会向元素上下延伸。

行高没有变,但是因为背景色延伸到内边距区域了,所以背景与前面的行出现了重叠。 这样的结果是符合预期的。

上述行为针对行内非置换元素的上下两边,左右两边又是另外一种情况。来看一行中一 小段行内非置换元素的情况。如果为这样的元素设定左内边距或右内边距,确实能看到 效果

置换元素的内边距

不管置换元素是块级还是行内的,内边距都出现在内容四周,而且背景色会填充到内边 距区域

行内非置换元素的内边距对文本行的高度没有影响。置换元素截然相反,规 则完全变了。行内置换元素的内边距对行高有很大的影响。

TanXinNiao commented 3 years ago

图像边框

border-image-slice border-image-slice属性在图像上放置4条裁剪线,这4条线围聚得到的部分用作绘制 边框的图像。这个属性最多接受4个值,(按顺序)定义距上右下左4边的偏移。是的, 顺序依然是TRBLO少于4个值时,也应用前面讲过的值复制规则。因此,只提供一个值时, 为四边设定相等的偏移。

下面以一个3行3列共9个圆(各圆的颜色不同)构成的图为例,裁剪后用作边框的图像。

border: 25px solid;
border-image-source: url(i/circles.png);
border-image-slice: 33.33%;

注意,各边上的图像有拉伸,这是默认的行为,不过十分合理。 裁剪线正好位于 相邻的圆之间,这是因为图中各个圆的尺寸是一样的,所以1/3的偏移量正好使裁剪线 落在两个圆之间。位于四个角的圆出现在边框的四个角上,而各边上的圆经过拉伸后填 满整条边。

那么,为什么本节开头那个示例中的图像只出现在边框的四个角上,而没有出现在四条 边上呢?因为border-image・slice属性就是这么定义的。规范是这么说的: 如果左右两边的[border-image-slice]宽度之和大于或等于图像的宽度,上下两边 和中间部分是空的……上下两边类似。

也就是说,如果裁剪线重合或错过了,图像便只出现在角上,而边上则为空。这一点使 用border-image-slice: 50%最好解释。此时,一个图像被分成四等份,分别用于四角, 没有留下任何部分供四边使用。然而,如果值大于50%,尽管图像不再被分成四等份, 依然得到相同的结果。因此,声明为border-image・slice: 100%时(默认值),整个图 像都出现在四角上,而各边则留空。

假如你想让图像的尺寸不同于border-width定义的宽度, 使用 border-image-width 属性设定。 取值 [ |〈percentage〉| |auto ]

为了弄清这个属性的作用,我们从长度值入手。下述声明设定lem宽的边框: border-image-width: lem; 这个声明把裁剪线放在距边框区域四边均为1em的地方

因此,上下边框的高度为lem,左右边框的宽度为lem,四个角的宽度和高度均为 lem0在这种情况下,由border-image-slice确定的边框图像将根据border-image- repeat (稍后介绍)规定的方式填充限定的边框区域。

注意,各裁剪区域的尺寸与border-width无关。,即便把border-width的 值设为零,通过border-image-width也能让边框图像显示出来。利用这一点可以把实线 边框作为后备式样,以防边框图像无法加载,但是又不让实线跟图像的高度/宽度一样宽。 例如:

border: 2px solid;
border-image-source: url(stars.gif);
border-image-width: 12px;
border-image-slice: 33.3333%;

border-image-width的基本作用与border-image-slice十分相似,只不过前者裁剪的 是边框框自身。

TanXinNiao commented 3 years ago

外推边框

好的,现在我们知道如何裁剪大图并设定边框图像的宽度了,那么应该如何保证大图 不与内容重叠呢?我们可以添加大量内边距,可是一旦图像加载失败,或者浏览器不
支持图像边框,就会留出多余的空白。为了处理这种情况,规范引入了 border-image- outset 属性。

不管使用长度还是数字,border-image-outset都把边框图像向边框框外侧推,类似 裁剪线的偏移方式,只不过这里是向外偏移。与border-image-width 一样,border- image-outset 的数字值也是border-width (不是border-image-width)所定义宽度的 倍数。

下面举个例子说明这个属性的用途。假设你想使用图像做边框,但是在图像不可用时回 落到细实线边框。最初你可能会这样编写:

border: 2px solid;
padding: 0.5em;
border-image-slice: 10; border-image-width: 1;

我们定义了 0.5 em的内边距,在浏览器默认的配置下,计算结果为8像素。加上2像素 宽的边框,从内容区边界到边框外边界的距离为10像素。因此,如果能正常渲染边框 图像,图像不仅会填满边框区域,还会填充到与内容毗邻的内边距区域。 我们可以增加内边距的大小,但是倘若图像无法显示呢,在内容和细实线边框之间将出 现大量空白。为了避免出现这种情况,我们可以把边框图像向外推

border: 2px solid;
padding: 0.5em;
border-image-slice: 10;
border-image-width: 1; border-image-outset: 8px;
TanXinNiao commented 3 years ago

轮廓

CSS定义了一种特殊的装饰方式,名为轮廓(outline)。实际使用中,轮廓一般直接绘 制在边框外侧,但情况并不总是这么简单(稍后就将看到)。根据规范.轮廓与边框的 区别体现在三个方面:

  1. 轮廓不占空间。
  2. 轮廓可以不是矩形。
  3. 用户代理通常在元素处于:focus状态时渲染轮廓。 不过,我还要再加一点:
  4. 轮廓更极端,无法单独为一边设置独特的轮廓。

轮廓式样

outline-style 取值 auto | none | solid | dotted | dashed | double | groove | ridge | inset | outset

与边框最大的两点不同是,轮廓没有hidden式样(边框有),但是多了个aut。式样。 这个式样给用户代理留出了足够的自由权,可以实现丰富的轮廓外观。CSS规范是这样 说的: 用户代理在处理auto值时可以自定义轮廓的式样,可以结合所在平台的用户界面, 也可以比CSS所能描述的更加华丽,例如带圆角的外发光轮廓。

除了这两点之外,轮廓的其他式样都与边框一样 此外还有一个不太明显的区别:border-style是简写属性,而outline-style不是。 你不能使用outlineTtyle为各边设定不同的式样,因为轮廓不支持这么做。CSS没有 outline-top-style属性。其他轮廓属性也是如此,但outline除外。

轮廓与边框的区别

轮廓与边框之间的第一个重要区别是,轮廓对布局完全没有影响。任何影响都没有。轮 廓只是视觉上的效果。