css学习笔记 margin和padding的百分比

一个运用了padding:100%的css效果

偶然间看到一段代码,可以用padding:100%实现一个高度永远等于宽度的块框。

1
<div class="constant-width-to-height-ratio"></div>

1
2
3
4
5
6
7
8
9
.constant-width-to-height-ratio {
background: #333;
width: 50%;
}
.constant-width-to-height-ratio::after {
content: '';
display: block;
padding-top: 100%;
}


可是为什么明明是作用在垂直方向上的padding-top会和宽度扯上关系呢

padding和margin的百分比

在W3C文档文档中我们可以看到以下解释

Note that in a horizontal flow, percentages on ‘margin-top’ and ‘margin-bottom’ are relative to the width of the containing block, not the height (and in vertical flow, ‘margin-left’ and ‘margin-right’ are relative to the height, not the width).

Note that percentages on ‘padding-top’ and ‘padding-bottom’ are relative to the width of the containing block, not the height (at least in a horizontal flow; in a vertical flow they are relative to the height).

也就是说margin-top/bottom和padding-top/bottom的百分比所参照的对象的都是其父元素的width,因而也就可以解释上面为什么可以用padding-top:100%实现该块的高度永远等于宽度。
换而言之,设置任意比例的padding-top也就可以任意设置块的宽高比。

思考:如果不使用伪元素呢

在上述例子中,通过伪元素去设置padding-top,使其实际高度相当于容器的宽度。
如果不使用伪元素的话,我们可以直接在给该元素同时设置width和padding-top,可是容器的内容实际高度会为0,是因为有了跟内容宽度一致的padding,因此整体视觉效果上像是被撑开了。

那什么是伪元素呢?

伪元素

首先我们先分清伪元素和伪类

伪元素是双冒号::,伪类是单冒号:

  • 常见伪类
    • :hover,:link,:active,:target,:not(),:focus。
  • 常见伪元素
    • ::first-letter,::first-line,::before,::after,::selection
      一个元素每次只能对一个伪元素操作(必须处于选择器语句的最后),但可以添加多个伪类(link,visited,hover,active顺序不能混)

::before和::after

::before和::after下特有的content,用于在css渲染中向元素逻辑上的头部或尾部添加内容。这些添加不会出现在DOM中,不会改变文档内容,不可复制,仅仅是在css渲染层加入,但其作用效果和直接在该dom上加内容的效果是一样的,设置的属性也同作用于css中的盒模型。

结合counter计数器

在::before和::after中我们经常会把content和css的计数器结合使用

  • counter-reset:[ ? ]+ | none | inherit
    • 默认值为none。
    • 第一个参数用来定义计数器的名称,但不可以是CSS关键字例如none;
    • 第二个参数用来定义计数器开始计数的起始值,默认为0(则计数从1开始)。
    • 该属性的主要功能是标识计数器作用域,而且此值必须作用于选择器上,并且不可缺少。
  • counter-increment:[ ? ]+ | none | inherit
    • 默认值为none。
    • 第一个参数表示要调用的计数器的名称,就是在counter-reset里定义的那些;
    • 第二个参数指定计数起始值。其值允许是0或者负整数值,如果未指定任何值,则该值为1(前提是counter-reset未显式设置计数的起始值)。其值递增是按倍数值递增,如果设置了值为2,后面元素递增值为4、6、8,依此类推。为负值时表示递减
  • counter()
    • 用来调用定义的计数器,接受两个参数,中间用 , 分隔。
    • 第一个参数就是之前定义的计数器名称
    • 第二个参数用来定义计数的样式,同列表的list-style。(包括:disc,circle,square,decimal,decimal-leading-zero,lower-roman,upper-roman,lower-greek, lower-latin,upper-latin,armenian,georgian, lower-alpha, upper-alpha,none, inherit)
      1
      2
      3
      4
      5
      6
      7
      8
      9
      .chooses{
      counter-reset: choosenNum;
      }
      .chooses input:checked{
      counter-increment: choosenNum;
      }
      .choose span:before{
      content: counter(choosenNum);
      }

上述例子实现了选中n个checkbox,则会在span内容后面显示“n”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.class{
counter-reset: part;
}
.class h1{
counter-reset: subpart;
counter-increment: part;
}
.class h2{
counter-increment: subpart;
}
.class h1:before{
content: "章节" counter(part)" ";
}
.class h2:before{
content: counter(part) "." counter(subpart) "节 ";
}

上述例子实现了章节序号,即

1
2
3
4
5
6
章节1 xxx
1.1节 xxx
1.2节 xxx
章节2 xxx
2.1节 xxx
……