CSS 备忘录

盒模型(Box Model)

盒模型的主要区域:内容盒子(Content Box)、内边距盒子(Padding Box)、边框盒子(Border Box)、外边距盒子(Margin Box)。

Box-Model

Content Box:这是内容所在的区域。此内容可以控制其父级的大小,因此通常是最可变大小的区域。

Padding Box:内边距盒子围绕内容盒子,是由 padding 属性创建的空间。如果我们的盒子设置了溢出规则,比如 overflow:auto 或者 overflow:scroll,滚动条也会占用这个空间。

Border Box:边框盒子围绕着内边距盒子,其空间被 border 值占用。边框是盒子的边界。

Margin Box:最后一个区域,即外边距盒子,是盒子周围的空间,由盒子上的 margin 规则定义。轮廓 outline 和盒子阴影 box-shadow 等属性也占据了这个空间,因为它们被绘制在顶部,所以它们不会影响我们盒子的大小。你可以在盒子上有一个 200pxoutline-width,并且包括边框在内的所有内容都将是完全相同的大小。

内容和大小

盒子根据其 display 值、设置的尺寸和其中的内容具有不同的行为。

你可以通过使用外部大小来控制盒模型内容大小:width:50px;

或者,也可以继续让浏览器根据内容大小为您做出决定,使用内部大小:width: min-width; 浏览器默认行为;

当我们显式的设置宽度 width 时,由于 CSS 使用默认的 box-sizing: content-box宽度只会作用于内容盒子。我们也可以使用 border-box 让盒子大小为:Border Box + Padding Box + Content Box。

JS 获取盒模型大小

Content Box

JS 无法直接获取内容盒子的大小,但是可以通过 Padding Box 的大小 - Padding 得到,代码如下:

1
2
3
4
5
6
7
function getContentWidth (element) {
const styles = getComputedStyle(element)

return element.clientWidth
- parseFloat(styles.paddingLeft)
- parseFloat(styles.paddingRight)
}

Padding Box

内边距盒子可以通过元素的 clientWidth 只读属性获取,Element.clientWidth 可以用来获取非内联元素的内边距盒子宽度,以像素计。该属性包括内边距 padding,但不包括边框 border、外边距 margin 和垂直滚动条(如果有的话)。

如果元素超出了指定大小并设置了溢出规则,此时如果要获取元素的实际内边距盒子,可以通过 Element.scrollWidth 只读属性来度量包括由于溢出而在屏幕上不可见的内容的宽度。宽度的测量方式与 clientWidth 相同,如果没有溢出,则 clientWidth 和 scrollWidth 相同。

Border Box

要获取包括边框在内的宽度,可以使用元素的 offsetWidth 只读属性。HTMLElement.offsetWidth 包括任何边框、内边距和垂直滚动条(如果有的话)。它不包括伪元素的宽度,例如 ::before::after

也可以使用元素的 getBoundingClientRect() 属性,绝大多数情况下两者是相等的。除了在有 变换 - transform 的情况下,offsetWidth 和 offsetHeight 返回元素的布局宽度和高度,而 getBoundingClientRect() 返回渲染的宽度和高度。

例如,如果元素有 width: 100px; 和 transform: scale(0.5); getBoundingClientRect() 将返回 50 作为宽度,而 offsetWidth 将返回 100。


它们的关系如下图:

js-doc-width

选择器(CSS Selector)

要将 CSS 应用于元素,需要先选择元素。CSS 为我们提供了许多不同的方法来执行此操作。这些选择器可以多个任意组合形成一个 CSS 规则。这些选择器包括:

基本选择器

  • 通用选择器Universal selector

    选择所有元素。(可选)可以将其限制为特定的名称空间或所有名称空间。
    语法:* ns|* *|*
    例子:* 将匹配文档的所有元素。

  • 元素选择器Type selector

    按照给定的节点名称,选择所有匹配的元素。
    语法:elementname
    例子:input 匹配任何 `` 元素。

  • 类选择器Class selector

    按照给定的 class 属性的值,选择所有匹配的元素。
    语法.classname
    例子.index 匹配任何 class 属性中含有 “index” 类的元素。

  • ID 选择器ID selector

    按照 id 属性选择一个与之匹配的元素。需要注意的是,一个文档中,每个 ID 属性都应当是唯一的。
    语法:#idname
    例子:#toc 匹配 ID 为 “toc” 的元素。

  • 属性选择器Attribute selector

    按照给定的属性,选择所有匹配的元素。
    语法:[attr] [attr=value] [attr~=value] [attr|=value] [attr^=value] [attr$=value] [attr*=value]
    例子:[autoplay] 选择所有具有 autoplay 属性的元素(不论这个属性的值是什么)。

分组选择器(Grouping selectors)

  • 选择器列表Selector list

    , 是将不同的选择器组合在一起的方法,它选择所有能被列表中的任意一个选择器选中的节点。
    语法A, B
    示例div, span 会同时匹配 元素和

    元素。

组合器(Combinators)

  • 后代组合器Descendant combinator

    (空格)组合器选择前一个元素的所有后代节点。
    语法:A B
    例子:div span 递归匹配所有位于任意

    元素之内的 元素。

  • 直接子代组合器Child combinator

    > 组合器选择前一个元素的直接子代的节点。
    语法A > B
    例子ul > li 匹配直接嵌套在

      元素内的所有
    • 元素。

    • 一般兄弟组合器General sibling combinator

      ~ 组合器选择兄弟元素,也就是说,后一个节点在前一个节点后面的任意位置,并且共享同一个父节点。
      语法A ~ B
      例子p ~ span 匹配同一父元素下,

      元素后的所有 元素。

    • 紧邻兄弟组合器Adjacent sibling combinator

      + 组合器选择相邻元素,即后一个元素紧跟在前一个之后,并且共享同一个父节点。
      语法:A + B
      例子:h2 + p 会匹配所有紧邻在 元素后的

      元素。

    • 列组合器Column combinator

      || 组合器选择属于某个表格行的节点。
      语法: A || B
      例子: col || td 会匹配所有 作用域内的 元素。

    伪选择器(Pseudo)

    • 伪类

      : 伪选择器支持按照未被包含在文档树中的状态信息来选择元素。
      例子:a:visited 匹配所有曾被访问过的 元素。

    • 伪元素

      :: 伪选择器用于表示无法用 HTML 语义表达的实体。
      例子:p::first-line 匹配所有

      元素的第一行。

    使用技巧

    • 使用紧邻兄弟组合器为堆叠元素之间添加间隙。> * + *

    See the Pen Learn CSS - Next sibling selector by Zeral (@Zeral-Zhang) on CodePen.

    仅当元素是 .top 的子元素的下一个兄弟元素时,才使用紧邻兄弟组合器添加间隙,并使用伪元素为间隙添加背景色。

    也可以使用 column-gaprow-gap 为 Multi-column(多列布局)、Flexible Box(弹性盒子)以及 Grid layouts(网格布局)中的列或行之间添加间隙。

    • 使用 Emmet 类 CSS 选择器语法快速书写结构化代码块

    例如使用下面的缩写:

    1
    #page>div.logo+ul#navigation>li*5>a{Item $}

    将转换为:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <div id="page">
    <div class="logo"></div>
    <ul id="navigation">
    <li><a href="">Item 1</a></li>
    <li><a href="">Item 2</a></li>
    <li><a href="">Item 3</a></li>
    <li><a href="">Item 4</a></li>
    <li><a href="">Item 5</a></li>
    </ul>
    </div>

    大多数编辑器都支持 Emmet 缩写 Tab 键快速展开代码块,它的语法不限于 HTML,详情查看官方文档:Emmet Documentation