理解CSS(上) | 青训营笔记

97 阅读13分钟

一、基础知识

Casading规则、选择器、继承、值和单位、盒模型

1. 层叠、优先级

image.png

层叠三大规则

image.png

image.png

选择器类别

  • 通配符选择器:*

  • 元素选择器:根据HTML元素类型选择元素。例如,p选择所有的<p>元素。

  • 类选择器:根据元素的类属性选择元素。例如,.my-class选择具有类my-class的所有元素。

  • ID选择器:根据元素的ID属性选择特定元素。例如,#my-element选择ID为my-element的元素。

  • 属性选择器:根据元素的属性和属性值选择元素。例如,[data-attribute]选择具有data-attribute属性的所有元素,[data-attribute="value"]选择具有data-attribute属性且其值为value的所有元素。[attr|=val]选择具有attr属性且值为val或以val-开头的元素。[attr^=val]选择具有attr属性且值以val开头的元素。[attr$=val]选择具有attr属性且值以val结尾的元素。[attr*=val]选择具有attr属性且值包含val的元素。[attr1][attr2]选择具有attr1和attr2属性的元素。

  • 伪类选择器:根据元素的状态或文档结构选择元素。例如,:hover选择鼠标悬停在其上的元素,:first-child选择作为其父元素的第一个子元素的元素。

  • 伪元素选择器:选择元素的某个部分,例如内容的前后。例如,::before选择元素内容之前的一个虚拟元素,::after选择元素内容之后的一个虚拟元素。

  • 组合选择器:通过组合多个选择器来选择符合所有条件的元素。

    • 后代选择器(空格):例如,div p选择所有作为<div>元素后代的<p>元素。
    • 子元素选择器(>):例如,div > p选择所有作为<div>元素直接子元素的<p>元素。
    • 相邻兄弟选择器(+):例如,div + p选择紧跟在<div>元素后面的<p>元素。
    • 一般兄弟选择器(~):例如,div ~ p选择在<div>元素后面的所有<p>兄弟元素。
  • 多个选择器:使用逗号分隔的多个选择器可以同时选择符合任一选择器条件的元素。例如,div, p选择所有的<div><p>元素。

image.png

选择器优先级

image.png

源码位置

image.png

由层叠概念引申出的css代码good practice(好习惯)

  1. 选择器尽量少用id(不利于复用。优先级较高,不利于后续覆盖)
  2. 尽量不要用!important(级别是最高的,后面想扩展的灵活性会被压缩)
  3. 自己的样式加载在引用库样式的后面(保证我们自己的样式优先生效)

2. 继承

CSS 中的继承是一种机制,通过它,子元素可以从其父元素接收样式属性值。这使得我们可以在一个地方设置通用样式,然后让其他元素自动继承这些样式,从而减少代码的重复和提高可维护性。

并非所有的 CSS 属性都是可继承的。一些常见的可继承属性包括:colorfonttext-align等。这些属性在父元素上设置后,子元素会自动继承这些样式,除非子元素上明确设置了不同的值。

image.png

3. CSS的值和单位

文字类:比如像initial这种关键字,颜色、位置等等 数值类:比如z-index:1这种数值,或者带有单位的数值、百分比等 函数生成:比如calc(),min(),max()等

长度:

绝对长度:px,pt,cm,in.…

相对长度:em,rem,ex,rex..w,vh,vmin,vmax.… 角度:deg,grad,turn,rad 时间:s,ms 分辨率:dpi,dpcm,dppx

image.png

4. 盒模型

浏览器根据视觉格式化模型(visual formatting model),将所有元素表示为盒子模型,css通过盒模型做layout。

视觉格式化模型:视觉格式化模型 - CSS:层叠样式表 | MDN (mozilla.org)

  • 控制盒子类型 display:block、inline、inline-block、flex、..

  • 控制盒子大小&计算方式 width,height... box-sizing:content-box border-box

  • 控制盒中内容流 overflow:auto、scroll、hidden、.

  • 控制定位 position:static、relative、absolute、fixed、sticky

  • 是否可见 visibility:visible、hidden、..

image.png

根据盒模型举例

image.png

实现三角形 (bnorder)

/* 创建一个空的 div 元素,将其作为三角形 */
<div class="triangle"></div>
​
/* 为三角形添加样式 */
<style>
  .triangle {
    /* 将 div 的宽度和高度设置为 0,这样它本身不会占据空间 */
    width: 0;
    height: 0;
​
    /* 使用 border 来制作三角形 */
    /* 三角形的底边宽度,此处设为 100px */
    border-left: 50px solid transparent;
    border-right: 50px solid transparent;
​
    /* 三角形的高度,此处设为 100px */
    border-bottom: 100px solid red;
​
    /* 如果想创建其他方向的三角形,可以尝试更改 border 的设置 */
  }
</style>

实现固定比例矩形(aspect-ratio/padding百分比)

<div class="rectangle"></div>
<style>
.rectangle {
  /* 设置矩形的宽度 */
  width: 200px;
​
  /* 使用 aspect-ratio 属性设置矩形的宽高比为 4:3 */
  aspect-ratio: 4 / 3;
​
  /* 设置矩形的背景颜色和边框 */
  background-color: lightblue;
  border: 2px solid black;
}
</style>
<div class="rectangle"></div>
<style>
.rectangle {
  /* 设置矩形的宽度 */
  width: 100%;
  height: 0;
  padding: 0;
  /* padding-bottom是父元素宽度75% */
  padding-bottom: 75%;
}
</style>

实现水平居中

<div class="container">
  <div class="centered"></div>
</div>

/* 设置 body 和 html 的高度为 100%,这样才能让外层容器占据整个屏幕 */
html, body {
  height: 100%;
  margin: 0;
}
​
.container {
  /* 将容器的宽度设置为 100%,以使其占据整个屏幕宽度 */
  width: 100%;
​
  /* 使用 flex 布局将子元素水平居中 */
  display: flex;
  justify-content: center;
}
​
.centered {
  /* 设置要居中的元素的样式,例如背景色、内边距等 */
  background-color: lightblue;
  padding: 20px;
  border: 2px solid black;
}
常用的居中方式

行内元素水平居中

  1. text-align: center;

块级元素水平居中

  1. display: flex; justify-content: center;
  2. margin: auto;

行内元素垂直居中

  1. line-height: height (行高=父高)
  2. display: inline-block; vertical-align: middle;

块级元素垂直居中

  1. display: flex; align-items: center;
  2. display: table-cell; vertical-align: middle;
  3. 绝对定位

实现渐变边框

<div class="awesome-border">
</div>

.awesome-border {
    width: 150px;
    height: 100px;
    border: 8px solid transparent;
    border-radius: 12px;
    background-clip: padding-box, border-box;
    background-origin: padding-box, border-box;
    background-image: linear-gradient(to right, #fff, #fff),linear-gradient(135deg, #e941ab, #a557ef);
}

下面采用为元素来实现

  • 渐变边框的实现:通过创建一个伪元素并设置其背景为渐变,我们可以实现一个渐变边框的效果。伪元素将覆盖在其父元素(.gradient-border)上,但位于父元素的内容之下。
  • 边框宽度控制:设置伪元素的 padding,我们可以控制渐变边框的宽度。伪元素的 padding 就是渐变边框的宽度。
  • 与父元素内容分离:伪元素独立于其父元素的内容,因此我们可以在不影响父元素内容的情况下实现渐变边框效果。这使得父元素的内容可以维持其原始样式(例如,背景颜色、边框和圆角),而伪元素专门负责实现渐变边框效果。

伪元素在这里中主要用于创建一个渐变边框,同时不影响其父元素的内容。这种方法避免了直接修改父元素样式的复杂性,使得实现渐变边框变得更加简单。

<div class="gradient-border">
  <p>这是一个带渐变边框的元素。</p>
</div><style>
.gradient-border {
  /* 设置内边距,以便为伪元素留出空间 */
  padding: 10px;
  position: relative;
  display: inline-block;
}
​
.gradient-border::before {
  /* 创建伪元素,并设置为相对于其父元素定位 */
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: -1;
​
  /* 使用渐变作为边框的背景 */
  background-image: linear-gradient(to right, red, orange, yellow, green, blue, indigo, violet);
​
  /* 设置边框的宽度 */
  padding: 3px;
​
  /* 使伪元素的边框圆角与父元素的边框圆角相匹配 */
  border-radius: 5px;
}
​
p {
  /* 设置段落的背景颜色、边框和圆角 */
  background-color: white;
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 5px;
  margin: 0;
  padding: 10px;
}
​
</style>

负外边距

负外边距(negative margin)是 CSS 盒模型中的一个概念,它可以在盒子之间创建重叠或者调整盒子的位置。与正外边距(positive margin)增加空间不同,负外边距会减少空间。以下是负外边距在不同情况下的作用:

  1. 水平方向上的负外边距:

    • 当两个块级元素并排时,它们的负外边距会让它们互相重叠。这可以用于调整元素之间的距离或者实现特定的布局效果。
    • 当一个元素的左边距为负时,它会向左移动;当一个元素的右边距为负时,它会向右移动。这可以用于调整元素相对于其父容器的位置。
  2. 垂直方向上的负外边距:

    • 当两个垂直排列的块级元素具有负外边距时,它们会互相重叠。这可以用于调整元素之间的距离,特别是当需要减少默认的垂直间距时。
    • 当一个元素的上边距为负时,它会向上移动;当一个元素的下边距为负时,它会拉近下一个元素与它之间的距离。

需要注意的是,负外边距可能会导致布局上的问题,例如元素重叠、脱离正常文档流等(BFC外边距重叠问题)。因此,在使用负外边距时需要谨慎,确保它不会导致不可预期的布局问题。在某些情况下,使用其他布局技术(如 Flexbox、Grid 或定位)可能会更合适。

image.png

二、布局和定位

常规流、弹性盒子、Grid、定位

image.png

常规流布局

常规流(Normal Flow)布局,也被称为文档流(Document Flow)布局,是浏览器默认的 CSS 布局方式。在常规流布局中,元素按照它们在 HTML 代码中的顺序自上而下、自左向右地排列。常规流布局主要包括两类元素:块级元素(block-level elements)和行内元素(inline elements)。

  1. 块级元素:

    • 块级元素会独占一行,即它们会从上到下排列。
    • 块级元素默认的宽度为其父容器的宽度,高度取决于其内容。
    • 常见的块级元素有:<div><p><h1>-<h6><ul><ol><li>等。
  2. 行内元素:

    • 行内元素会在同一行内从左到右排列,直到容器宽度不足时才会换行。
    • 行内元素的宽度和高度取决于其内容,而不是父容器的尺寸。
    • 常见的行内元素有:<span><a><strong><em><img>等。

在常规流布局中,元素遵循一定的规则进行排列,这些规则取决于元素的 display 属性。display 属性有几个常用值,例如:block(块级元素)、inline(行内元素)和 inline-block(既具有块级元素的特点,又具有行内元素的特点)。

虽然常规流布局是浏览器的默认布局方式,但现代前端开发中,很多布局需求无法仅依靠常规流实现。因此,CSS 提供了更加强大和灵活的布局技术,如 Flexbox、Grid、定位(Positioning)等,来满足各种布局需求。

image.png

BFC(Block Formatting Context,块级格式化上下文)和 IFC(Inline Formatting Context,行内格式化上下文)是两种不同的 CSS 布局方式(格式规范),它们影响着元素如何在页面上排列。在解释 BFC 和 IFC 之前,需要了解一下“格式化上下文(Formatting Context)”。

BFC是什么?

  • BFC本身是block formatting context的缩写,是一种格式规范。如果说一个盒子是BFC或者有BFC特性,那么BFC表示的是block formatting.context root。不管它外部显示类型是什么,但是它的内部显示类型是flow-root,.其实就是这个盒子内部形成了一个新的块级格式化上下文。

image.png

块级格式化上下文(block formatting context)

image.png

格式化上下文的布局规范为:

在一个块格式区域中,盒子会从包含块的顶部开始,按序垂直排列。同级盒子间的垂直距离会由“margin“属性决定。相邻两个块级盒子之间的垂直间距会遵循外边距折叠原则被折叠。 在一个块格式区域中,每个盒子的左外边缘会与包含块左边缘重合(如果是从右到左的排版顺序,则盒子的右外边缘与包含块右边缘重合)。

格式化上下文(Formatting Context)是 CSS 盒子模型的一部分,它定义了一组规则来描述如何对元素进行布局。

  1. BFC(块级格式化上下文):

    形成一个独立的渲染区域,内部元素的渲染不会影响到外部元素。

    • 在BFC中,盒子会在垂直方向上一个挨着一个的排布。
    • 垂直方向的间距由margin决定。
    • 属于同一个BFC的两个相邻盒子的margin会发生重叠。
    • 在BFC中,每个元素的左外边距(margin-left)会触碰到包含块的左边界(对于从左往右的格式化,否则就触碰右边界),即使浮动元素也是如此。

    BFC 可以通过以下方式触发:

    • display 属性值为 blockinline-blocktabletable-celltable-captionflexgridinline-flexinline-grid 等;
    • position 属性值为 absolute 或 fixed
    • float 属性值不为 none
    • overflow 属性值不为 visible
  2. IFC(内联级格式化上下文):

    • IFC 是行内元素的布局环境,这些元素按照水平方向一个接一个地排列。
    • 在 IFC 中,行内元素会根据它们在文档流中的顺序排列,并根据字体的基线对齐。
    • IFC 会自动调整行高以适应最高的行内元素,因此,IFC 中的行高可能不同。
    • IFC 中的元素与块级元素不同,不会独占一行,而是尽可能地填充水平空间,直到容器宽度不足时才会换行。

    IFC 可以通过以下方式触发:

    • display 属性值为 inlineinline-blockinline-table 等

外边距塌陷

外边距塌陷(Margin Collapsing)是 CSS 布局中一个特殊的现象,它发生在垂直方向上相邻的外边距(Margin)之间。当两个或多个垂直方向上相邻的外边距遇到时,它们会合并为一个外边距,而不是简单地相加。合并后的外边距大小等于相邻外边距中最大的一个。

image.png

会产生外边距塌陷的情况

  • 两个兄弟元素之间相邻的上下外边距
  • 父子元素之间相邻的上下外边距
  • 内容为空元素自己上下外边距相邻

消除外边距塌陷的方法:

  • 在两个相邻的上下边距之间增加border、padding或者内联元素,使之不相邻;
  • 在父子元素重叠时,除了上述方法,还可以设置父元素为BFC使得父子不在同级BFC中

内联格式化上下文

“在内联格式区域中,盒子会从包含块的顶部开始,按序水平排列。只有水平外边距、边框和内边距 会被保留。这些盒子可以以不同的方式在垂直方向上对齐:可以底部对齐或顶部对其,或者按文字 底部进行对齐。我们把包含一串盒子的矩形区域称为一个线条框。(The rectangular area that contains the boxes that form a line is called a line box.)"

image.png

  • 水平方向排列: 内联级元素按从左到右(在 LTR(从左到右)文本方向)的顺序排列。如果行内空间不足以容纳一个内联级元素,它会换行到下一行继续排列。

  • 垂直对齐: 内联级元素支持 vertical-align 属性,可以调整元素在垂直方向上的对齐方式。例如,可以设置元素相对于基线(baseline)向上或向下对齐。

  • 行框(Line box): 在 IFC 中,内联级元素被包含在行框内。行框的高度由内联级元素的高度决定。每一行都有一个行框,行框之间没有垂直外边距塌陷。

  • 不支持宽度和高度设置: 内联级元素不支持设置 width 和 height 属性。它们的宽度由内容决定,而高度则由 line-height 属性决定。

  • 支持水平外边距、内边距和边框: 内联级元素支持设置水平方向的外边距、内边距和边框,但垂直方向的设置不会影响其他内联级元素的布局。

  • 匿名文本: 在 IFC 中,不属于任何内联级元素的文本被视为匿名文本。匿名文本会按照内联级元素的布局规则进行排列。

常见使用示例

单行文字垂直居中,比如标题
<div class="title">
    我是标题
</div><style>
    .title {
        height: 100px; /* 设置容器高度 */
        line-height: 100px; /* 设置行高等于容器高度,实现垂直居中 */
        background-color: #f0f0f0; /* 设置容器背景色,便于观察垂直居中效果 */
        font-size: 24px; /* 设置字体大小 */
    }
</style>
文字和icon垂直对齐
  • 利用了line box中计算高度的原理和vertical-align的设置,垂直对齐,但不是完全垂直居中如果设置父元素font-size:0,基线和中线重叠,则居中对齐
  <style>
  .image{
      width: 24px;
      height: 24px;
      vertical-align: middle;
  }
  .text{
      font-size: 16px;
      line-height: 32px;
      margin-left: 4px;
      vertical-align: middle;
  }
  
  </style>
</head>
<body>
  <div class="wrap">
    <img class="image" src="图片地址">
    <span class="text">文本内容</span>
  </div>
</body>

弹性盒子

image.png

image.png