当前位置: 首页 > news >正文

CSS复习

CSS


CSS的全称是层叠样式表 (Cascading Style Sheets)。

  • Cascading (层叠):规则如何叠加、冲突如何解决。
  • Specificity (优先级):规则的重要性排序。
  • Style (样式):如何高效、可维护地应用样式。

渲染过程

CSS 渲染过程分为以下几个主要阶段:

解析阶段(Parsing Stage)

在这个阶段,浏览器会处理和解析 HTML 和 CSS 文件,构建 DOM(Document Object Model)树和 CSSOM(CSS Object Model)树。

  • DOM 树:由 HTML 文档解析生成的树形结构,表示文档的结构和内容。
  • CSSOM 树:由 CSS 文件解析生成的树形结构,表示文档中所有样式规则的结构。

这两个树会被合并成一个渲染树(Render Tree),其中包含所有需要显示在页面上的元素以及它们的样式。

布局阶段(Layout Stage)

一旦 DOM 和 CSSOM 被解析,浏览器会开始进行 布局阶段。在这个阶段,浏览器计算每个元素的位置、尺寸、边距、边框等,确定它们如何在页面上显示。

  • 计算元素的位置和大小:浏览器会根据样式信息(如 width, height, margin, padding, position 等)计算每个元素的位置和尺寸。
  • 确定元素的几何信息:这会影响到元素在页面上的显示效果,确保页面的内容正确布局。

布局阶段的输出是 渲染树,它包含了元素的几何信息(如坐标、尺寸等),但还不涉及样式的细节。

绘制阶段(Painting Stage)

在布局计算完成后,浏览器会进入 绘制阶段。这个阶段负责根据 渲染树 来绘制页面的内容。

  • 绘制每个元素的外观:包括背景、边框、文字、阴影、图像等。
  • 绘制顺序:浏览器会根据元素在渲染树中的层级关系(z-index、层叠顺序)来决定绘制顺序。

绘制阶段是一个非常重要的过程,它决定了页面的视觉效果,比如文本颜色、背景色、边框、图片等元素的绘制。

合成阶段(Compositing Stage)

一旦页面的所有元素都绘制完成,浏览器进入 合成阶段。在这个阶段,浏览器会将页面分成多个图层进行合成(比如滚动、动画等效果时)。

  • 图层合成:浏览器会把渲染树中的元素分配到多个图层上。这些图层可能包含背景、文本、动画等内容。
  • GPU 加速:某些元素(如动画、过渡效果等)会被分配到 GPU 图层进行加速处理,从而提高性能。
  • 合成图层:最后,浏览器会将这些图层合并成最终的页面,并呈现给用户。

合成阶段的重点是确保页面上的动态效果(如动画、滚动等)流畅地显示出来。

文本渲染阶段(Text Rendering Stage)

文本渲染阶段是一个特定于文本的渲染过程。它的目的是确保文本的显示符合预期的样式和排版要求。

  • 字体渲染:浏览器会根据字体规则加载字体,计算文本的排版方式。
  • 行高、字间距:确保文本的行高、字间距等样式正确应用。
  • 伪元素的渲染:例如 ::first-line, ::before, ::after 等伪元素会在这个阶段渲染,影响文本的显示。

这个阶段主要影响的是页面中文本的显示效果,确保文本在不同字体和排版要求下呈现正确。

重绘和重排(Repaint and Reflow)

在页面渲染完成之后,可能会出现一些需要更新页面内容的情况,例如改变元素样式、大小、位置等。这时,浏览器会触发 重绘(Repaint)重排(Reflow)

  • 重绘(Repaint):当样式发生变化,但元素的布局没有变化时(例如颜色、背景等),浏览器只需要进行重绘。改变元素的外观属性(不影响布局),开销较小。( color, background-color, visibility)。
  • 重排(Reflow):当元素的布局发生变化时(例如尺寸、位置、边距等),浏览器需要重新计算元素的位置和大小,重新进行布局并重绘。改变元素的几何属性(尺寸、位置),会触发重新计算布局,开销大。(width, height, margin, padding, left, top)

重排重绘 更加消耗性能,因为它涉及到元素位置和尺寸的重新计算。

合成与显示(Compositing and Display)

合成阶段完成后,最终的图层会被合成并呈现到屏幕上,用户看到的是最终渲染出来的页面内容。

层叠

层叠决定了当多个规则应用于同一个元素时,哪个规则最终生效。它取决于三个因素(按重要性降序):

  1. 来源 (Origin) 和 !important:

    • 用户代理样式(浏览器默认样式) < 用户样式 < 作者样式(开发者写的) < !important 作者样式 < !important 用户样式
    • 切记: !important 破坏了自然的层叠规则,仅在极其特殊的情况下使用(如覆盖第三方库的内联样式)。滥用会导致样式难以管理和覆盖。
  2. 优先级 (Specificity):

    权重计算(从高到低):

    组成部分 示例 权重值 (方便记忆)
    内联样式 style="color: red;" 1000
    ID 选择器 #header 100
    类选择器、属性选择器、伪类 .class, [type="text"], :hover 10
    元素选择器、伪元素 div, ::before 1
    通配符、关系选择器 *, >, +, ~ 0

    如何计算?

    • 比较规则:从左到右(内联a->IDb -> Classc -> Elementd),高位胜出后就不再比较低位。如果样式是在元素的 style 属性中直接定义的(即内联样式),则 a=1。否则 a=0注意: 只有内联样式会计入这里,外部或内部样式表里的规则 a 永远为 0。
    • #header .nav-link.active 有一个IDb,2个Classc和0个Elementd,所以它的优先级是 (1, 2, 0) -> 权重 120
    • body #header .title 有一个IDb,1个Classc和1个Elementd的优先级是 (1, 1, 1) -> 权重 111
    • 120 > 111,所以前者胜出。
    <style>body #header .title {color: aquamarine;}#header .nav-link.active {color: red;}
    </style>
    <body><div id="header"><span class="title nav-link active">我是红色还是绿色</span></div>
    </body>
    
  3. 出现顺序 (Order)

如果冲突的规则具有相同的来源相同的特异性,那么最后出现的规则胜出。

  • 在样式表中,后定义的规则会覆盖先定义的规则。
  • 对于引入的多个样式表文件,<link><style> 标签在 HTML 中的顺序至关重要。后引入的样式表具有更高的优先级。
  1. 特殊例子

    <style>
    p#a {color: green;
    }div::first-line {color: blue;
    }</style>
    <div><p id="a">First Paragraph</p>
    </div>
    

    运行上面代码会发现文字颜色不是绿色而是蓝色。根据 CSS 规范,::first-line 伪元素的样式确实可能覆盖子元素的颜色样式,这是因为它是在 文本渲染阶段 直接应用的。

    在渲染时,浏览器会首先确定首行的样式,确保文本的视觉效果符合预期。由于 ::first-line 直接作用于文本的渲染阶段,它的样式会覆盖 子元素(如 p 标签中的文本)的颜色样式。

继承属性

某些属性(非全部)会自动从父元素传递给子元素。

  • 可继承属性: 通常是与文本内容相关的属性,如 color, font, font-size, font-family, text-align, line-height, list-style 等。
  • 不可继承属性: 通常是与盒模型布局相关的属性,如 width, height, margin, padding, border, background, display, position 等。
  • 控制继承:
    • inherit: 显式地从父元素继承该属性。
    • initial: 设置为此属性的初始默认值(不受浏览器默认样式影响)。
    • unset: 如果该属性是自然继承的,则表现为 inherit;否则,表现为 initial
    • revert: 将属性值重置为浏览器的默认样式(用户代理样式表)。
  • 例子:
/* Selects any element that is NOT a paragraph */
:not(p) {color: blue;
}

意思是,:not(p) 可以选择任何不是 <p> 标签的元素。然而,上面的 CSS 选择器,在如下的 HTML 结构,实测的结果不太对劲。

<p>p</p>
<div>div</div>
<span>span</span>
<h1>h1</h1>

由于 :not(p) 同样能够选中 <body>,那么 <body> 的 color 即变成了 blue,由于 color 是一个可继承属性,<p> 标签继承了 <body> 的 color 属性,导致看到的 <p> 也是蓝色。

如果把它改成一个不可继承的属性,这次 <p> 没有边框体现

/* Selects any element that is NOT a paragraph */
:not(p) {border: 1px solid;
}

单位

  • 绝对单位: px (像素)。在Web中,它其实是一个相对单位(相对于设备像素),但通常被视为绝对单位。

    .px {font-size: 14px;width: 200px;height: 60px;border: 1px solid #ccc;
    }
    <div class="px">像素(px):展示了固定尺寸的元素,不随屏幕大小变化</div>
    

​ 这个容器使用像素单位定义尺寸,无论父容器或屏幕如何变化,它都保持固定大小。像素单位提供精确控制,但在响应式设计中不够灵活,因为元素不能根据上下文调整大小。

  • 相对单位(现代响应式设计的核心):

    • %: 相对于父元素的相同属性的值(widthpadding)或父元素的字体大小font-size)。

      .box {padding: 20px;border-radius: 8px;background-color: #e8f4fc;width: 500px;
      }
      .box .sub-box {width: 80%;padding: 5%;background-color: aquamarine;
      }
      <div class="box"><div class="sub-box"><p>百分比(%):展示了相对于父元素宽度的百分比布局</p></div>
      </div>
      

    ​ 这个容器的宽度是其父元素的80%,内边距是自身宽度的5%。

    说明: 百分比单位在创建流动布局时非常有用,允许元素根据父容器调整大小。

    • em: 相对于当前元素font-size2em = 当前字体大小的2倍。用于 margin/padding 时,非常灵活。

      .box.em-box {font-size: 1.2em;padding: 1.5em;
      }<div class="box em-box">基于em单位的尺寸,这个容器的内边距(1.5em)是基于它的字体大小(1.2em)计算的。浏览器预设字体大小为16px,若无特别指定则会直接继承父元素字体大小,那么:.em-box的字体大小就是相对当前字体大小16* 1.2 = 19.2px, 1.5em =1.5 * 19.2=28.8px<br /><p>p的字体大小也是19.2px</p>
      </div>
      

      .em-box盒子原本继承根元素 (<html>) 字体大小是16px,但是样式设置为1.2em的字体,所以相对当前元素的字体,它的实际字体大小是16*1.2 = 19.2pxpadding大小则是1.5 *19.2 = 28.8px

      .em-box盒子下的p元素继承父元素的字体大小,也是19.2px,如果它也设置了1.2em的字体大小,则它的实际字体大小是19.2 * 1.2 = 23.04px

      说明:em单位在设置与文本大小相关的属性(如margin、padding)时非常有用,可以保持比例一致性。

    • rem: 相对于根元素 (<html>)font-size。这使得它成为设置全局尺寸比例的完美选择,易于维护和响应式调整。

      .box.rem-box {font-size: 1.2rem;padding: 1.5rem;
      }
      <div class="box rem-box">这个容器的大小是基于根元素的字体大小(通常是16px)计算的。如果根字体大小是16px,那么:1.2rem = 19.2px, 1.5rem = 24px<p>p的字体大小也是19.2px</p>
      </div>
      

      .rem-box盒子原本继承根元素 (<html>) 字体大小是16px,但是样式设置为1.2rem的字体,所以相对当前元素的字体,它的实际字体大小是16*1.2 = 19.2pxpadding大小则是1.5 *16 = 24px

      .rem-box盒子下的p元素继承了1.2rem的字体属性,所以它的实际字体大小也是16 * 1.2 = 19.2px

      说明: rem单位提供了全局一致性,只需调整根字体大小即可缩放整个布局,非常适合响应式设计。

    • vw / vh: 相对于视口宽度/高度的 1%。50vw = 视口宽度的一半。

      .box.viewport-box {width: 10vw;height: 10vh;
      }       
      <div class="box viewport-box">尝试调整浏览器窗口大小,观察这个容器的变化。
      </div>
      

      说明:视口单位非常适合创建全屏布局或与视口大小直接相关的元素。

    • ch: 相对于当前字体下的数字 “0” 的宽度。常用于限制容器的字符数

      <div class="example"><div style="width: 5ch; overflow: hidden">012345678910</div>
      </div>
      

      这个容器的宽度被设置为5个"0"字符的宽度。可以看到只显示到4,后面超过宽度的数字全被隐藏了。

      说明:ch单位非常适合用于控制文本容器的宽度,以优化每行的字符数,提高阅读体验。

盒模型

盒模型的组成部分

每个HTML元素都被表示为一个矩形盒子,这个盒子由四个部分组成:内容(content)内边距(padding)边框(border)外边距(margin)

pV6Fj6H.png

  1. 内容区域(Content):包含元素的实际内容,如文本、图片等。内容区域的大小由 widthheight 属性设置。
  2. 内边距(Padding):内容区域与边框之间的空间,内边距可以使内容与边框之间保持一定的距离。通过 padding 属性设置,四个方向的内边距可以单独定义或使用简写属性一次性设置。
  3. 边框(Border):围绕内边距和内容区域的边框,边框的样式、宽度和颜色可以通过 border 属性设置。
  4. 外边距(Margin):元素与相邻元素之间的空间,外边距用于调整元素的位置。通过 margin 属性设置,同样支持单独定义每个方向或使用简写属性。

盒模型的计算

元素的总宽度和高度的计算方式取决于盒模型的类型(box-sizing 属性):

标准盒模型 (content-box):

总宽度 = width + padding(左右) + border(左右)+margin(左右)

总高度 = height +padding(上下) + border(上下)+margin(上下)

IE盒模型 (border-box):

总宽度 = width (已包含padding和border)+margin(左右)

总高度 = height (已包含padding和border)+margin(上下)

现代CSS开发中,通常会将所有元素的box-sizing设置为border-box:

*{box-sizing: border-box;
}

这样可以更直观地控制元素的大小,因为padding和border不会增加元素的总宽度。

边距塌陷问题

边距塌陷(Margin Collapsing)是CSS中一个常见但令人困惑的现象,主要发生在垂直方向上。当两个或多个垂直相邻的块级元素的边距相遇时,它们会合并成一个边距,大小取其中较大的那个值。

pV6lvPH.png

* {margin: 0;padding: 0;
}
.box {width: 100px;height: 100px;background-color: bisque;border: 1px solid transparent;
}
.m-b-40 {margin-bottom: 40px;
}
.m-t-30 {margin-top: 30px;
}
.sub-box {width: 50px;height: 50px;background-color: aquamarine;
}//相邻元素塌陷
<div class="box m-b-40"></div>
<div class="box m-t-30"></div>//父子元素塌陷
<div class="box"><div class="sub-box m-t-30"></div>
</div>

注意:相邻元素的外边距合并是CSS的正常行为

解决父子元素塌陷有以下方法:

  1. 使用Flexbox或Grid布局 - 这些现代布局技术会创建新的布局上下文,阻止边距合并

    display:flex; // grid
    
  2. 添加内边距(padding) - 在两个元素之间添加即使很小的内边距也可以阻止边距合并

    padding:1px;
    
  3. 添加边框(border) - 边框会物理上分隔两个元素,阻止它们的边距合并

    border:1px solid transparent;
    
  4. 使用overflow属性 - 设置overflow为非visible值会创建新的块格式化上下文(BFC)

    overflow:auto;
    
  5. 使用inline-block显示 - inline-block元素不会与其它块级元素发生边距合并

    display:inline-block;
    

BFC

BFC(Block Formatting Context)即块级格式化上下文,是Web页面的可视化CSS渲染的一部分,是布局过程中生成块级盒子的区域,也是浮动元素与其他元素的交互限定区域。

通俗来讲,BFC是一个独立的布局环境,其中的元素布局不会影响到外部元素,同时外部环境的布局也不会影响到BFC内部。BFC具有一些特性,例如可以包含浮动元素,可以阻止边距合并等。

BFC的特性

  • 内部块级元素垂直排列

    BFC内的块级元素从上到下依次排列,垂直方向上的间距由margin决定

  • 外边距合并
    BFC内部相邻元素的垂直外边距合并(合并结果以最大的为准),但BFC内部与外部元素的外边距不会合并

  • 包含浮动元素
    如果父元素是BFC,则其内部的浮动子元素的高度会被计算到父容器中(解决高度塌陷问题)

  • 阻止浮动元素覆盖
    BFC的区域不会与浮动元素重叠(例如,用BFC实现两栏自适应布局)

如何触发BFC

创建条件: float (非 none), position (absolute/fixed), display (inline-block, table-cell, flex), overflow (非 visible)。

/* 任意一个属性即可触发 */
.element {overflow: hidden | auto | scroll; /* 非visible值 */float: left | right; /* 非none */position: absolute | fixed; /* 绝对定位 */display: flex | grid | inline-block | table-cell | table-caption | table | table-row | inline-flex | inline-grid | flow-root; /* flow-root适用于现代浏览器,不会产生副作用 */content: layout; /* 新特性,现代浏览器支持 */
}

BFC应用场景

  1. 解决外边距合并问题:

    //相邻元素塌陷  实际间距为30
    <div class="box m-b-40"></div>
    <div class="box m-t-30"></div>

    将其中一个元素包裹在新的BFC容器中,阻断外边距合并

    .bfc-container {display: inline-block;
    }<div class="box m-b-40"></div>
    <div class="bfc-container"><div class="box m-t-30"></div>
    </div>
    
  2. 清除浮动导致的父元素高度塌陷问题:

    .parent {border: 1px solid #ccc;
    }
    .float-child {float: left;width: 100px;height: 100px;background-color: aquamarine;
    }<div class="parent"><div class="float-child">浮动元素</div>
    </div>
    

    触发父元素的BFC,强制包裹浮动子元素

    .overflow-auto {overflow: auto;
    }
    <div class="parent overflow-auto"><div class="float-child">浮动元素</div>
    </div>
    
  3. 解决使用浮动实现自适应两栏布局,右侧内容被左侧浮动元素遮挡问题:

    .overflow-auto {overflow: auto;
    }
    <div class="parent"><div class="float-child">浮动元素</div><div class="child overflow-auto">非浮动右侧元素</div>
    </div>
    

    触发右侧容器的BFC,形成独立布局区域

    <div class="child overflow-auto">非浮动右侧元素</div>
    
  4. 阻止文本环绕浮动元素

    .content {height: 200px;width: 200px;background-color: orange;border: 2px solid blue;
    }
    <div class="parent"><div class="float-child">浮动元素</div><div class="content">这是一段文本内容,它会环绕在浮动元素的周围。这是一段文本内容,它会环绕在浮动元素的周围。</div>
    </div>
    

    触发文本容器的BFC,阻止文本环绕

    <div class="content overflow-auto">这是一段文本内容,它会环绕在浮动元素的周围。这是一段文本内容,它会环绕在浮动元素的周围。
    </div>
    

布局模式

元素通过 display, position, float 属性决定其布局方式。

display 属性

  • block: 块级元素,独占一行,可设置宽高。
  • inline: 行内元素,不独占一行,不可设置宽高,垂直方向的 padding/margin 不生效
  • inline-block: 行内块元素,不独占一行,但可以设置宽高
  • none: 元素不显示,并从渲染树中移除,不占空间。
  • flex:一种用于按或按布局元素的一维布局
  • grid:用于创建一个二维网格布局

position 属性

描述 定位基准 是否脱离文档流
static (默认) 正常流布局 -
relative 相对定位 自身原本的位置 否(原位置保留)
absolute 绝对定位 最近的非 static 定位的祖先元素
fixed 固定定位 视口 (viewport)
sticky 粘性定位 在特定阈值内相对滚动父容器固定 否(但表现类似固定)
  • 脱离文档流: absolute, fixed 元素会脱离正常的布局流,不再占据空间,后续元素会填补其位。
  • 包含块 (Containing Block): 对于 absolute 元素,理解其定位基准至关重要。

包含块的定义:

一般来说,元素的包含块是其最近的块级祖先元素的内容区域。但是,对于绝对定位的元素,包含块是最近的position值不为static(即relative、absolute、fixed或sticky)的祖先元素的内边距区域(padding area)。如果没有这样的祖先元素,那么包含块就是初始包含块(通常是视口或HTML元素)。

对于绝对定位元素:

- 绝对定位元素(position: absolute)的位置是相对于其包含块来计算的。

- 通过top、right、bottom、left属性来指定相对于包含块边缘的偏移。

float 属性

  • 最初设计用于文字环绕图片,后被用于布局(现已过时)。
  • 会使元素脱离文档流,并向左/右浮动直到碰到父容器或其他浮动元素的边缘。
  • 清除浮动 (Clearfix): 父元素包含浮动子元素时,高度会塌陷(因为子元素脱离流)。
.parent::after {content: "";display: table;clear: both;
}<div class="parent"><div class="float-child"></div>
</div>

布局挑战

圣杯布局

(Header, Footer, 固定左右边栏+流动主内容区)

float实现圣杯布局:https://codepen.io/small-windmill/pen/ByoOpbV

思路:

  1. 给包裹左中右区域的主容器.middle 设置左右padding值(值为左右区域的宽度)
  2. 给左中右三个区域设置float:left
  3. 分别给左右两栏设置负margin值,左栏margin-left为-100%,右栏位margin-left为负的其自身宽度(利用了浮动元素的负margin到一定值后会使其自身往上一行移动的原理)
  4. 左右两栏设置position:relative定位,对它们进行定位,移动到两侧

双飞翼布局

不仅能满足main处于优先加载的地位,而且更好的解决了圣杯布局的错乱问题,且CSS代码更简单,缺点是增加了一个标签

float实现双飞翼布局:https://codepen.io/small-windmill/pen/NPGLpaZ

思路:

  1. 给.main区域包裹一个div标签.middle,.main区域设置左右margin为侧边栏宽度
  2. 给.middle设置float:left,宽度100%和高度
  3. 给侧边栏设置float:left,分别给左右两栏设置负margin值,左栏margin-left为-100%,右栏位margin-left为负的其自身宽度(利用了浮动元素的负margin到一定值后会使其自身往上一行移动的原理)

等高卡片布局

无论每个卡片的内容量如何,所有卡片都保持相同的高度,创造整洁统一的外观。

使用flex布局实现:https://codepen.io/small-windmill/pen/qEOMJvw

使用grid布局实现:https://codepen.io/small-windmill/pen/OPyoaNp

垂直水平居中(多种方法)

  • 使用position定位

    .relative-container {position: relative;width: 100px;height: 100px;background-color: bisque;
    }
    .absolute-item {position: absolute;top: 50%;left: 50%;width: 50px;height: 50px;background-color: aqua;/* margin-top: -25px; *//* margin-left: -25px; */transform: translate(-50%, -50%);
    }
    <div class="relative-container"><div class="absolute-item"></div>
    </div>
    
  • 使用flex布局

    .flex-container {display: flex;/* align-items: center;justify-content: center; */width: 100px;height: 100px;background-color: bisque;
    }
    .flex-item {width: 50px;height: 50px;margin: auto;background-color: aqua;
    }
    <div class="flex-container"><div class="flex-item"></div>
    </div>
    
  • 使用grid布局

    .grid-container {display: grid;place-items: center;width: 100px;height: 100px;background-color: bisque;
    }
    .grid-item {width: 50px;height: 50px;background-color: aqua;
    }
    <div class="grid-container"><div class="grid-item"></div>
    </div>
    
  • 使用表格布局

    .table-container {display: table;width: 100px;height: 100px;background-color: bisque;
    }
    .table-item {display: table-cell;text-align: center; /* 水平居中 */vertical-align: middle; /* 垂直居中 */background-color: aqua;
    }
    <!-- 使用表格布局实现水平垂直居中 -->
    <div class="table-container"><!-- 表格单元格会根据父表格单元的尺寸自动扩展。即使设置子元素的宽高,它仍然会尝试填满父容器的 100px 的高度和宽度。 --><div class="table-item">222</div>
    </div>
    
  • 特殊场景使用line-height

    .text-container {width: 100px;line-height: 100px; /* 等于容器高度 */text-align: center;background-color: bisque;
    }
    .text-item {display: inline-block;vertical-align: middle;line-height: normal; /* 重置文本行高 */background-color: aqua;
    }
    <div class="text-container"><div class="text-item">居中文本</div>
    </div>
    

瀑布流布局

使用column-count和column-gap:https://codepen.io/small-windmill/pen/bNVxzap

思路:

  1. 使用column-count属性指定列数
  2. 使用column-gap属性设置列间距
  3. 使用break-inside: avoid防止项目被分割到不同的列

使用flex:https://codepen.io/small-windmill/pen/WbQgmNE

  1. 创建一个flex容器
  2. 在容器内创建多个列
  3. 每个列也是一个flex容器,方向为column
  4. 需要手动将内容项分配到各列中

使用grid:https://codepen.io/small-windmill/pen/vENVMQd

思路:

  1. 使用grid-template-columns定义列数和列宽
  2. 使用gap属性设置项目之间的间距
  3. 使用grid-auto-rows设置基础行高
  4. 使用grid-row-end控制每个项目在垂直方向上的跨度

background属性

background属性就是专门设置背景的属性,可以设置背景色,也可以设置背景图片。

属性 描述
background-color: 设置元素的背景颜色,可以使用颜色名称十六进制值RGBRGBAHSLHSLA值。
background-image: 设置元素的背景图像,可以使用url()函数指定图像路径,或使用渐变函数创建渐变背景。
background-repeat: 控制背景图像是否重复
background-position: 控制背景图像在元素中的位置,可以使用关键词、百分比或长度值。
background-attachment: 控制背景图像是否跟随窗口滚动,常用值:scrollfixedlocal
background-size 设置背景图像的尺寸,可以使用covercontain、具体尺寸或百分比值。
background-origin 设置 background-position 属性相对于什么位置来定位背景图像,常用值:border-boxpadding-boxcontent-box
background-clip 设置背景图像的显示区域,常用值:border-boxpadding-boxcontent-boxtext
background 背景属性的缩写,可以在一个声明中设置所有的背景属性

background-origin

background-origin 属性用于指定背景图像的定位区域,即决定背景图像相对于哪些区域来定位。它控制了背景图像的坐标系,以决定背景图像如何与元素的边框和内容区域对齐。

  • border-box (默认值):背景图像相对于元素的 边框区域 来定位。背景图像将覆盖元素的内容区域、内边距区域和边框区域。
  • padding-box:背景图像相对于元素的 内边距区域 来定位。背景图像不会覆盖边框区域,而是仅限于元素的内容区域和内边距区域。
  • content-box:背景图像相对于元素的 内容区域 来定位。背景图像仅会显示在内容区域内,完全不覆盖内边距或边框区域。
<style>
.box {display: inline-block;margin-bottom: 12px;width: 100px;height: 100px;
}
.bg-origin {border: 10px solid rgba(255, 0, 0, 0.1);padding: 40px;background-image: url(./NATOURS/img/hero.jpg);background-repeat: no-repeat;background-position: center;background-size: 100% 100%;
}
</style><div class="bg-item"><div class="box bg-origin bg-origin-border"></div><span> background-origin border-box效果示例</span>
</div>
<div class="bg-item"><div class="box bg-origin bg-origin-padding"></div><span> background-origin padding-box效果示例</span>
</div>
<div class="bg-item"><div class="box bg-origin bg-origin-content"></div><span> background-origin content-box效果示例</span>
</div>

backgroun-origin属性

background-clip

background-clip 是CSS中用于设置元素背景绘制区域的属性。它决定了背景(颜色或图像)是否延伸到边框、内边距或内容区域。

  • border-box: 默认值。背景将扩展到整个元素,包括边框区域。背景图像/颜色会绘制在元素的内容区域内边距区域边框区域
  • padding-box: 背景将限制在元素的 内边距区域 内,背景图像/颜色不会扩展到边框区域,但会扩展到内容区域和内边距区域。
  • content-box: 背景将限制在元素的 内容区域 内,背景图像/颜色不会覆盖内边距边框区域
  • text: 实验性属性。背景图像仅在 文本内容 区域内绘制,这个值主要用于文字背景。在文字上设置背景时,背景图像会只显示在文本上,而不是在整个容器内。
<style>
.bg-clip {border: 10px solid rgba(255, 0, 0, 0.1);padding: 40px;background-image: url(./NATOURS/img/nat-10.jpg);background-repeat: no-repeat;background-position: center;
}
.bg-clip-border {background-clip: border-box;
}
.bg-clip-padding {background-clip: padding-box;
}
.bg-clip-content {background-clip: content-box;
}
.bg-clip-text {width: 450px;font-size: 30px;font-weight: 900;color: transparent;-webkit-background-clip: text;background-clip: text;
}
</style><!-- background-clip -->
<div class="bg-item"><div class="box bg-clip bg-clip-border"></div><span>background-clip border-box效果示例</span>
</div>
<div class="bg-item"><div class="box bg-clip bg-clip-padding"></div><span>background-clip padding-box效果示例</span>
</div>
<div class="bg-item"><div class="box bg-clip bg-clip-content"></div><span>background-clip content-box效果示例</span>
</div>
<div class="bg-item"><div class="box bg-clip bg-clip-text">background-clip text效果示例</div>
</div>

background-clip

渐变背景

CSS渐变是使用background-image属性创建的图像,可以实现平滑的颜色过渡。

渐变背景

线性渐变 (linear-gradient)

创建沿着一条直线变化的颜色渐变。可以指定方向(角度或关键词)和颜色停止点(特定颜色出现的位置)。

background-image: linear-gradient(to right, #ccc, #000);

径向渐变 (radial-gradient)

创建从一个中心点向外辐射的颜色渐变。可以指定形状、大小和位置。

background-image: radial-gradient(#ccc, #000);

角向渐变 (conic-gradient)

创建围绕中心点旋转的颜色渐变。颜色围绕中心点旋转,而不是从中心辐射。

background-image: conic-gradient(#ccc, #000);

渐变技巧

在渐变中使用transparent

当我们需要实现这样一种遮罩效果的时候,就可以使用从白色到透明色的渐变,通过叠加在元素上方的方式,实现该效果。

<style>.search-container {display: flex;position: relative;width: 400px;column-gap: 12px;align-items: center;}.search-container ul {display: flex;overflow-x: auto;padding: 0;flex: 1;align-items: center;column-gap: 4px;}.search-container ul ::before {position: absolute;top: 0;right: 0;bottom: 0;width: 100px;background: linear-gradient(to right, transparent, #fff);content: "";}/* 完全隐藏滚动条 */::-webkit-scrollbar {display: none;}li {list-style: none;border: 1px solid #000;border-radius: 4px;padding: 4px;}.search-title {font-weight: bold;}.search-del {position: relative;border-radius: 4px;padding: 4px;font-size: 12px;background-color: #ccc;}</style><div class="search-container"><div class="search-title">搜索历史</div><ul><li>Button</li><li>Button</li><li>Button</li><li>Button</li><li>Button</li><li>Button</li></ul><div class="search-del">删除</div>
</div>

在渐变中使用transparent

利用渐变绘制三角形

<style>.triangle {width: 100px;height: 100px;background: linear-gradient(45deg,#f00 0%,#f00 50%,transparent 50%,transparent 100%);}
</style><div class="triangle"></div>

如果不设置渐变方向,默认是从上到下,它将页面分为两部分:上半部分红色,下半部分透明。当使用 45deg 时,渐变方向改变为对角线(左上到右下)。这意味着红色和透明的分割线会沿对角线延伸。因为渐变是沿对角线进行的,所以渐变的 50% 分界点会从左上角到右下角的对角线上,这样就产生了一个三角形的效果。

渐变是可以叠加多层的

CSS允许为一个元素设置多个背景图像,用逗号分隔。先列出的图像会绘制在后续图像的上面。

<style>.internal {margin: 12px 0;width: 100px;height: 80px;background-image: linear-gradient(135deg, transparent 15px, deeppink 0),linear-gradient(-135deg, transparent 15px, deeppink 0),linear-gradient(-45deg, transparent 15px, deeppink 0),linear-gradient(45deg, transparent 15px, deeppink 0);background-repeat: no-repeat;background-position: top left, top right, bottom right, bottom left;background-size: 50% 50%, 50% 50%, 50% 50%, 50% 50%;}</style>
<div class="internal"></div>

叠加渐变

利用repeating-linear-gradient节省代码

有的时候,我们需要用到不断重复的渐变。这个时候,除了 background-repeat: repeat 之外,官方还提供了一个 repeating-linear-gradient,可以创建一个由线性渐变重复组成的图形。

.box {display: inline-block;margin-bottom: 12px;width: 100px;height: 100px;
}.bg-multi-img {background: repeating-linear-gradient(90deg,red 0,red 1px,transparent 1px,transparent 10px),repeating-linear-gradient(red 0,red 1px,transparent 1px,transparent 10px),#ccc;background-position: 5px 0, 0 5px; /* 第一层偏移 5px,第二层偏移 5px */
}<div class="box bg-multi-img"></div>

多背景图像

repeating-linear-gradient 做了什么事情呢?其实是按照每 1px 安排一段 red,每 9px 安排一段 transparent

预留衔接空间消除渐变产生的锯齿

在使用渐变生成不同颜色的直接过渡时,非常容易就会产生锯齿效果。

     .circle {margin: 12px 0;width: 100px;height: 100px;background: radial-gradient(#9c27b0 0%,#9c27b0 47%,#ffeb3b 47%,#ffeb3b 100%);}

使用 radial-gradient(#9c27b0 0%, #9c27b0 47%, #ffeb3b 47%, #ffeb3b 100%) 生成的一个图形,从一种颜色直接到另外一种颜色,但是,仔细看看衔接处,会发现有非常明显的锯齿效果。

锯齿

遇到此类问题的解决方案是:在衔接处,适当留出一些渐变空间

     .circle {margin: 12px 0;width: 100px;height: 100px;background: radial-gradient(#9c27b0 0%,#9c27b0 47%,#ffeb3b 47.8%,#ffeb3b 100%);}

这多出来的 0.8% 就是为了消除锯齿的,0.8不是写死的,可以多调试选取既不会看出模糊,又能尽可能消除锯齿的一个范围幅度。

顺滑

渐变色动画

线性渐变(径向渐变、角向渐变)是不支持 animation 的,单色的 background 是支持的。

因此,在传统的 CSS 中,我们通常想实现背景色渐变动画,有几种方式:

  1. 通过 background-position 的移动模拟渐变动画;
  2. 通过 background-size 的缩放过程来模拟渐变动画;
  3. 通过外层的大渐变图形的移动(transform)来模拟渐变动画。
通过 background-position 模拟渐变动画
<style>.bg-position {margin-bottom: 12px;width: 200px;height: 100px;background: linear-gradient(to right,#ffc700 0%,#e91e1e 50%,#6f27b0 100%);background-position: 0 0;background-size: 200% 100%;animation: bgPosition infinite 2s linear alternate;}@keyframes bgPosition {0% {background-position: 0 0;}100% {background-position: 100% 0;}}
</style><div class="bg-position"></div>

background-position:指定图片的初始位置。这个初始位置是相对于以 background-origin 定义的背景位置图层来说的。

background-size:设置背景图片大小。当取值为百分比时,表示指定背景图片相对背景区的百分比大小。当设置两个参数时,第一个值指定图片的宽度,第二个值指定图片的高度。

通过 background-size: 200% 100% 将图片的宽度设置为两倍背景区的宽度,再通过改变 background-position 的 x 轴初始位置来移动图片,由于背景图设置的大小是背景区的两倍,所以 background-position 的移动是由 0 0 -> 100% 0

通过 background-size 模拟渐变动画
<style>.bg-size {margin-bottom: 12px;width: 200px;height: 100px;background: linear-gradient(to right,#ffc700 0%,#ff9100 33%,#e91e1e 66%,#6f27b0 100%);background-position: 100% 0;animation: bgSize infinite 5s ease-in-out alternate;}@keyframes bgSize {0% {background-size: 300% 100%;}100% {background-size: 100% 100%;}}
</style>
<div class="bg-size"></div>

上述两种方式,由于使用了 background-positionbackground-size,并且在渐变中改变这两个属性,导致页面不断地进行大量的重绘(repaint),对页面性能消耗非常严重。

通过 transform 模拟渐变动画

使用伪元素配合 transform 进行渐变动画,通过元素的伪元素 before 或者 after ,在元素内部画出一个大背景,再通过 transform 对伪元素进行变换:

<style>.bg-transform {overflow: hidden;position: relative;margin-bottom: 12px;width: 200px;height: 100px;}.bg-transform::before {position: absolute;top: 0;right: -100%;bottom: 0;left: -100%;background-image: linear-gradient(to right,#ff9100 33%,#e91e1e 66%,#6f27b0 100%);background-size: 100% 100%;animation: bgTransform infinite 3s linear alternate;content: "";}@keyframes bgTransform {0% {transform: translateX(-30%);}25% {transform: translateX(-15%);}50% {transform: translateX(0%);}75% {transform: translateX(15%);}100% {transform: translateX(30%);}}</style>
<div class="bg-transform"></div>
通过滤镜 hue-rotate 实现渐变动画

hue-rotate:为色相旋转滤镜,默认的值为 0deg,当旋转 360deg 后,相当于回到了本身的颜色值。

通过滤镜 hue-rotate,可以非常方便地实现背景色渐变动画,过渡效果也非常的自然,代码量也少。

<style>.bg-hue {margin-bottom: 12px;width: 200px;height: 100px;background-image: linear-gradient(to right, #ff9100, #6f27b0);background-size: 100% 100%;animation: bgHue infinite 3s linear alternate;}@keyframes bgHue {0% {filter: hue-rotate(0);}100% {filter: hue-rotate(360deg);}}
</style>
<div class="bg-hue"></div>
使用 CSS @property 实现背景色渐变动画

根据 MDN -- CSS Property,@property CSS at-rule 是 CSS Houdini API 的一部分,它允许开发者显式地定义他们的 CSS 自定义属性,允许进行属性类型检查、设定默认值以及定义该自定义属性是否可以被继承。

简单解读下,CSS @property 其实就是灵活度更高的 CSS 自定义属性,我们也可以称其为 CSS Houdini 自定义属性。其中:

  • @property --property-name 中的 --property-name 就是自定义属性的名称,定义后可在 CSS 中通过 var(--property-name) 进行引用。
  • syntax:该自定义属性的语法规则,也可以理解为表示定义的自定义属性的类型。
  • inherits:是否允许继承。
  • initial-value:初始值。

可以利用 CSS Houdini 自定义属性,将原本定义在 background 的过渡效果嫁接到了 color 之上,而 CSS 是支持一个颜色变换到另外一个颜色的。

<style>@property --colorA {syntax: "<color>";inherits: false;initial-value: fuchsia;}@property --colorB {syntax: "<color>";inherits: false;initial-value: #f79188;}@property --colorC {syntax: "<color>";inherits: false;initial-value: red;}.bg-property {margin-bottom: 12px;width: 200px;height: 100px;background-image: linear-gradient(to right,var(--colorA),var(--colorB),var(--colorC));background-size: 100% 100%;animation: bgProperty infinite 3s linear alternate;}@keyframes bgProperty {0% {--colorA: red;--colorC: #a93ee0;--colorF: fuchsia;}25% {--colorA: #ff3c41;--colorC: #e228a0;--colorF: #2e4c96;}50% {--colorA: orange;--colorC: green;--colorF: teal;}75% {--colorA: #ae63e4;--colorC: #0ebeff;--colorF: #efc371;}}
</style><div class="bg-property"></div>

background-attachment

background-attachment 是一个 CSS 属性,用于控制背景图像在滚动页面时的固定方式。它指定背景图像是随着页面的滚动一起滚动,还是固定在视口中,或者在其他方式下表现出来。

为了更好地理解,我们通常将页面内容分为几个层次:

  • 元素内容:在最上层,随滚动条移动。
  • 元素背景:在内容层之下。
  • 视口(Viewport):就是你看网页的“窗口”,它本身是固定不动的。

background-attachment 控制的就是背景层相对于哪个“框”来移动。

scroll (默认值)

  • 行为:背景图片相对于元素本身固定,不会随元素内容的滚动而滚动。

  • 通俗解释:图片被“粘”在了元素上。当你滚动元素的内容时(如果元素有滚动条),背景图不动;但当你滚动整个页面时,元素和它的背景图会一起滚动。

  • 关键点:背景的定位基准是元素的边界,而不是它的内容。

    示例
    一个 <div> 设置了 background-attachment: scroll;,当你滚动这个 div 的滚动条时,里面的文字向上移动,但背景图片保持在 div 的顶部,不会随文字移动。

    <style>.attachment-scroll {overflow-y: auto;height: 400px;background-image: url("./NATOURS/img/nat-3-large.jpg");/* background-repeat: no-repeat; */background-attachment: scroll;background-size: cover;}.attachment-scroll p {font-size: 30px;font-weight: bold;text-align: center;color: #000;}
    </style><div class="attachment-scroll"><p>1</p><p>2</p><p>3</p><p>4</p><p>5</p><p>6</p><p>7</p><p>8</p><p>9</p><p>10</p><p>11</p><p>12</p>
    </div>
    

fixed

  • 行为:背景图片相对于视口(viewport)固定

  • 通俗解释:图片被“粘”在了浏览器窗口的玻璃上。无论你如何滚动页面或元素的内容,背景图片都纹丝不动,永远停留在窗口的同一个位置。

  • 关键点:背景的定位基准是浏览器的视口。这会创造一种强烈的景深效果,背景仿佛在所有内容之后。

  • 注意:在移动设备上,fixed 值的行为可能不一致且支持不佳,通常表现不如桌面浏览器稳定。

    经典应用:创建“视差滚动”效果。页面内容在滚动,但背景图固定不动,营造出深度感和沉浸感。

    background-attachment: fixed;
    

local

  • 行为:背景图片相对于元素的内容固定
  • 通俗解释:图片被“粘”在了元素的内容上。如果你滚动元素的内容(比如一个带滚动条的盒子),背景图片会随内容一起滚动。当你滚动整个页面时,元素和它的背景内容也会一起滚动。
  • 关键点:背景的定位基准是元素的内容区域。这个值是后来添加的,用于解决 scroll 无法满足的某些需求。
background-attachment: fixed;

三者对比

滚动页面时 滚动元素内容时(元素有滚动条) 定位基准
scroll (默认) 背景随元素一起滚动 背景固定不动 元素本身
fixed 背景固定不动 背景固定不动 浏览器视口
local 背景随元素一起滚动 背景随内容一起滚动 元素的内容

使用background-attachment实现滚动视差

  1. 背景图都设定了 background-attachment: fixed,所以背景图都是相对页面视口进行定位的。
  2. 通过滚动操作,改变的其实是不同的 <section> 在视口内的展示区域,通过这个区域的改变,这个区域内的背景图逐渐展现。
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>使用background-attachment实现滚动视差</title><style>* {margin: 0;box-sizing: border-box;padding: 0;}section {box-sizing: border-box;height: 100vh;font-size: 20vh;line-height: 100vh;text-align: center;color: #fff;background: rgba(0, 0, 0, 0.7);background-attachment: fixed;background-position: center center;background-size: cover;}.bg-attachment1 {background-image: url("./NATOURS/img/nat-3.jpg");}.bg-attachment2 {background-image: url("./NATOURS/img/nat-4.jpg");}.bg-attachment3 {background-image: url("./NATOURS/img/nat-5.jpg");}</style></head><body><section class="bg-attachment1">IMG1</section><section class="bg-attachment2">IMG2</section><section class="bg-attachment3">IMG3</section></body>
</html>

使用 background-attachment 实现滚动阴影

像element-ui/plus的table如果左侧为固定栏,右侧列可以滚动时,会给垂直于滚动的一侧添加一个阴影,用于表明当前有元素被滚动给该滚出了可视区域,类似这样:

滚动阴影

滚动阴影的难点在于,初始没有滚动的时候是没有阴影展现的,只有当开始滚动,阴影才会出现

需要借助 background-attachment: srcollbackground-attachment: local 两个属性,在滚动初始的时候,利用两层背景叠加在一起隐藏阴影背景,真正滚动的时候,将叠加的部分移走,只漏出阴影部分即可。

<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>使用 background-attachment 实现滚动阴影</title><style>* {margin: 0;box-sizing: border-box;padding: 0;}ul,li {list-style: none;}.container {display: flex;width: 500px;}.left-area {flex: 0 0 200px;}.right-area {display: flex;overflow-x: auto;background: linear-gradient(to right, #fff, transparent 100%),linear-gradient(to right, rgba(0, 0, 0, 0.5), transparent 100%);background-repeat: no-repeat;background-attachment: local, scroll;background-size: 100px 100%, 10px 100%;flex: 1;}.column {border: 1px solid #ccc;text-align: center;}li {border-bottom: 1px solid #ccc;min-width: 200px;white-space: nowrap;}li:last-child {border-bottom: none;}</style></head><body><div class="container"><div class="left-area"><div class="column"><div class="column-header">姓名</div><ul><li>小王</li><li>小赵</li><li>小白</li><li>小胡</li><li>小李</li></ul></div></div><div class="right-area"><div class="column"><div class="column-header">性别</div><ul><li>男</li><li>男</li><li>女</li><li>男</li><li>女</li></ul></div><div class="column"><div class="column-header">入学时间</div><ul><li>2025年9月5日17:39:32</li><li>2025年9月5日17:39:38</li><li>2025年9月5日17:39:40</li><li>2025年9月5日17:39:42</li><li>2025年9月5日17:39:44</li></ul></div><div class="column"><div class="column-header">自我介绍</div><ul><li>特别可爱,宇宙超级无敌</li><li>特别帅气,宇宙超级无敌</li><li>特别酷,宇宙超级无敌</li><li>特别牛,宇宙超级无敌</li><li>特别厉害,宇宙超级无敌</li></ul></div></div></div></body>
</html>

背景混合模式

background-blend-mode 是一个用于定义元素的背景图层如何相互混合的 CSS 属性。这里的“背景图层”指的是通过 background-imagebackground-color 等属性设置的多层背景。

简单来说,它就像 Photoshop 中的图层混合模式,你可以让一张背景图片和它下面的另一张图片,或者与背景色进行融合,创造出各种视觉效果(如变暗、变亮、叠加、滤色等)。

background-blend-mode: <blend-mode>;

常用的混合模式值

混合模式主要分为以下几类,以下是几个最常用和实用的模式:

  1. 变暗类
    • normal:默认值,正常显示,不混合。
    • multiply:正片叠底。将颜色值相乘,结果通常更暗。白色会变为透明,黑色保持不变。非常适合创建阴影效果或加深图像。
    • darken:变暗。比较混合层和基层的颜色,保留较暗的一个。
  2. 变亮类
    • screen:滤色。将颜色值反转后相乘,再反转结果。效果通常更亮。黑色会变为透明,白色保持不变。适合创建高光效果或提亮图像。
    • lighten:变亮。比较混合层和基层的颜色,保留较亮的一个。
  3. 对比类
    • overlay:叠加。结合了 multiplyscreen 的特点。保留基层(下层)的明暗对比,同时混合颜色。基层的亮部区域会更亮,暗部区域会更暗,增加对比度。
    • hard-light:强光。类似于 overlay,但基于混合层(上层)的明度。如果上层比50%灰亮,则效果类似 screen(变亮);如果比50%灰暗,则效果类似 multiply(变暗)。
  4. 组分类
    • color:颜色。使用混合层的色相和饱和度,以及基层的明度。非常适合为灰度图像上色。
    • luminosity:明度。与 color 相反。使用混合层的明度,以及基层的色相和饱和度

实用示例

示例 1:为图片添加色调

这是最常见的用法,用一张图片和一个背景色混合。

.tinted-image {background-image: url("portrait.jpg");background-color: #3498db; /* 蓝色 */background-blend-mode: multiply;/* 图片会蒙上一层蓝色调,高光部分保留,阴影部分变为蓝色 */
}

示例 2:创建双色调效果

使用两张相同的图片(比如一张原图,一张去色的),通过混合模式创造效果。

.duotone {background-image: url("portrait.jpg"), url("portrait.jpg");background-size: cover;background-color: #e74c3c; /* 红色 */background-blend-mode: luminosity, multiply;/* 解释:顶层图片(portrait.jpg)使用 luminosity 模式,只保留明度信息。下层图片(portrait.jpg)和红色背景色使用 multiply 模式混合。最终效果是:高光为红色,阴影为深红色的双色调效果。*/
}

示例 3:纹理叠加

将一张纹理图片叠加到纯色背景或另一张图片上。

.textured-box {background-image: url("paper-texture.jpg"), url("solid-color.jpg");background-blend-mode: overlay;/* 纸纹理会以 overlay 模式叠加在纯色背景上,增加质感 */
}

clip-path

clip-path 属性允许你通过定义一個裁剪区域(Clipping Region)来“剪掉”元素的某些部分。只有在裁剪区域内的内容才是可见的,区域外的内容(如内容、背景、边框等)都会被隐藏。

它可以创建出各种非矩形的视觉效果,比如圆形、椭圆形、多边形或自定义的复杂 SVG 路径形状。

inset() - 内切矩形

定义一个矩形,类似于 borderpadding。你可以指定从元素各边向内偏移的距离。

语法: inset( <top> <right> <bottom> <left> round <border-radius> )

示例

<style>.element-inset {width: 50px;height: 50px;background-color: aquamarine;clip-path: inset(5px 10px);}.element-inset-round {width: 50px;height: 50px;background-color: aquamarine;clip-path: inset(10px round 15px);}
</style><div class="element-inset"></div>
<div class="element-inset-round"></div>

inset

circle() - 圆形

定义一个圆形裁剪区域。

语法: circle( [ <radius> ]? [ at <position> ]? )

  • radius: 圆的半径。可以使用长度(如 20px)或关键字(如 closest-side,默认值,意思为半径到最近边的距离)。
  • at position: 圆心的位置。默认为元素中心。

示例

<style>.element-circle {width: 50px;height: 50px;background-color: deeppink;clip-path: circle(50%);}.element-circle2 {width: 50px;height: 50px;background-color: deeppink;clip-path: circle(closest-side at 25px 25px);}
</style><div class="element-circle"></div>
<div class="element-circle2"></div>

circle

ellipse() - 椭圆形

定义一个椭圆形裁剪区域。

语法: ellipse( [ <x-radius> <y-radius> ]? [ at <position> ]? )

  • x-radius, y-radius: X轴和Y轴的半径。默认为 closest-side
  • at position: 椭圆中心的位置。默认为元素中心。

示例

.element-ellipse {width: 50px;height: 50px;background-color: deepskyblue;clip-path: ellipse(10px 20px at center);
}
.element-ellipse2 {width: 50px;height: 50px;background-color: deepskyblue;clip-path: ellipse(10% 20% at center);
}

polygon() - 多边形

通过定义一系列顶点坐标来创建任意复杂多边形。这是功能最强大的方式。

通过定义一系列顶点坐标来创建任意复杂多边形。这是功能最强大的方式。

语法: polygon( [ <fill-rule> , ]? [ <x> <y> ]# )

  • fill-rule: (可选) 指定如何判断点在多边形内部还是外部,常用 nonzero(默认)和 evenodd
  • x y: 多边形的各个顶点的坐标。坐标是相对于元素自身的左上角(0,0)计算的。

示例

<style>.element-polygon-triangle {width: 50px;height: 50px;background-color: coral;clip-path: polygon(50% 0, 100% 100%, 0 100%);}.element-polygon-diamond {width: 50px;height: 50px;background-color: hotpink;clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);}.element-polygon-bubble {width: 50px;height: 50px;background-color: cornflowerblue;clip-path: polygon(0% 0%,100% 0%,100% 75%,75% 75%,75% 100%,50% 75%,0% 75%);}
</style>
<div class="element-polygon-triangle"></div>
<div class="element-polygon-diamond"></div>
<div class="element-polygon-bubble"></div>

path() - SVG 路径

使用 SVG 路径语法来定义极其复杂的形状。这是最灵活的方式,也是 SVG clipPath 在 CSS 中的直接对应物。

语法: path( [ <fill-rule>, ]? <string> )

  • string: SVG 路径数据字符串。
  • 注意: path() 的浏览器兼容性相比其他函数稍差

示例:

.element-path {width: 200px;height: 200px;background-color: burlywood;clip-path: path("M 10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80");
}

url() - 引用 SVG <clipPath>

引用一个内联或外部 SVG 中的 <clipPath> 元素。这是复用复杂 SVG 形状的绝佳方式。

语法: url( #clipPathId )

示例

<style>.element-url {width: 50px;height: 50px;background-color: tomato;clip-path: url(#myCustomClipPath);}
</style><svg width="0" height="0"><defs><clipPath id="myCustomClipPath"><circle cx="25" cy="25" r="25" /></clipPath></defs>
</svg><div class="element-url"></div>

参考框 (Reference Box)

clip-path 默认使用元素的边框盒 (Border Box) 作为坐标系参考。你可以使用 clip-path 的第二个参数来改变它:

  • margin-box: 以元素的外边距框(Margin Box) 为参考。
  • border-box(默认值) 以元素的边框框(Border Box) 为参考。
  • padding-box: 以元素的内边距框(Padding Box) 为参考。
  • content-box: 以元素的内容框(Content Box) 为参考。
  • fill-box: (用于 SVG 元素)
  • stroke-box: (用于 SVG 元素)
  • view-box: (用于 SVG 元素)

有一个如下样式的 div

.clip-box {margin: 20px;border: 10px solid blue;padding: 30px;width: 200px;height: 100px;line-height: 100px;text-align: center;background-color: lightcoral;/* 我们将改变这个属性的值 */clip-path: circle(25% at center); /* 默认基于 border-box */
}<div class="box">Clipping Example</div>

这个元素的盒子模型尺寸如下:

  • 内容区域 (Content Box): 200 x 100 px
  • 内边距区域 (Padding Box): (200 + 30**2) x (100 + 30*2) = 260 x 160 px
  • 边框区域 (Border Box): (260 + 10**2) x (160 + 10*2) = 280 x 180 px
  • 外边距区域 (Margin Box): (280 + 20**2) x (180 + 20*2) = 320 x 220 px

示例 1: border-box (默认)

clip-path: circle(25% at center) border-box;
  • 效果: 圆的半径是 border-box 宽度和高度的 25%
  • 计算:
    • 半径 = 280px * 0.25 = 70px
    • 圆心在 border-box 的中心 (140px, 90px)

示例2padding-box

clip-path: circle(25% at center) padding-box;
  • 效果: 圆的半径是 padding-box 宽度和高度的 25%
  • 计算:
    • 半径 = 260px * 0.25 = 65px
    • 圆心在 padding-box 的中心 (130px, 80px)

示例3content-box

clip-path: circle(25% at center) content-box;
  • 效果: 圆的半径是 content-box 宽度和高度的 25%
  • 计算:
    • 半径 = 200px * 0.25 = 50px
    • 圆心在 content-box 的中心 (100px, 50px)

示例4margin-box

clip-path: circle(25% at center) margin-box;
  • 效果: 圆的半径是 margin-box 宽度和高度的 25%
  • 计算:
    • 半径 = 320px * 0.25 = 80px
    • 圆心在 margin-box 的中心 (160px, 110px)

与 CSS 动画/过渡 (Animation/Transition) 的结合

示例:鼠标悬停时从圆形变为方形

<style>.clip-button {width: 100px;height: 50px;line-height: 50px;text-align: center;background-color: #4caf50;/* 添加过渡效果 */transition: clip-path 0.5s ease-in-out;cursor: pointer;/* 初始状态:圆形 */clip-path: circle(40% at 50% 50%);}.clip-button:hover {/* 结束状态:方形(inset矩形) */clip-path: inset(0% 0% 0% 0% round 0px); /* 也可以直接用`inset(0)` */}</style><div class="clip-button">clip me</div>

示例:动画关键帧实现多种形状变换

<style>.animated-element {width: 50px;height: 50px;background-color: #ccc;animation: morph 2s infinite ease-in-out alternate;}@keyframes morph {0% {clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);} /* 菱形 */100% {clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%);} /* 矩形 */}
</style>
<div class="animated-element"></div>

过渡和动画

过渡

CSS过渡允许在CSS属性值发生变化时平滑地改变属性值,而不是立即生效。过渡可以控制动画的速度、延迟和时序函数。

/* 基本语法 */
transition: property duration timing-function delay;

过渡属性

属性 描述 示例值
transition-property 指定应用过渡的CSS属性 all, width, opacity, transform
transition-duration 指定过渡效果持续的时间 0.3s, 1s, 200ms
transition-timing-function 定义过渡效果的速度曲线 ease, linear, ease-in, ease-out, ease-in-out
transition-delay 指定过渡效果开始之前的延迟时间 0s, 0.5s, 1s

过渡实例

<style>.box {width: 50px;height: 50px;background-color: aqua;transition: all 0.4s ease;}.box:hover {border-radius: 50%;background: #e74c3c;transform: rotate(45deg) scale(1.2);}
</style>
<div class="box"></div>

时序函数(Timing Functions)

时序函数定义了过渡动画的速度曲线,影响动画的加速和减速方式。

/* 使用不同的时序函数 */
.element {transition-timing-function: ease;transition-timing-function: linear;transition-timing-function: ease-in;transition-timing-function: ease-out;transition-timing-function: ease-in-out;transition-timing-function: cubic-bezier(0.68, -0.55, 0.27, 1.55);
}

代码示例:

<style>.timing-demo {display: flex;margin: 20px 0;flex-direction: column;gap: 10px;}.timing-box {margin: 5px 0;width: 100px;height: 50px;background: #3498db;transition: all 1s;}.timing-demo:hover .timing-box {margin-left: calc(100% - 100px);}.ease {transition-timing-function: ease;}.linear {transition-timing-function: linear;}.ease-in {transition-timing-function: ease-in;}.ease-out {transition-timing-function: ease-out;}.ease-in-out {transition-timing-function: ease-in-out;}.cubic-bezier {transition-timing-function: cubic-bezier(0.68, -0.55, 0.27, 1.55);}
</style><div class="timing-demo"><div class="timing-box ease">ease(默认)</div><div class="timing-box linear">linear(线性)</div><div class="timing-box ease-in">ease-in(渐入)</div><div class="timing-box ease-out">ease-out(渐出)</div><div class="timing-box ease-in-out">ease-in-out(渐入渐出)</div><div class="timing-box cubic-bezier">cubic-bezier(贝塞尔曲线)</div>
</div>

动画

CSS 动画允许元素在不使用 JavaScript 的情况下,从一个样式配置逐渐变化到另一个样式配置。它由两个核心部分组成:关键帧 (@keyframes)动画属性 (animation-\*)

关键帧 (@keyframes)

@keyframes 规则定义了动画在不同时间点上的样式状态。

语法:

@keyframes animation-name {from {/* 起始状态 (0%) */opacity: 0;}to {/* 结束状态 (100%) */opacity: 1;}
}/* 或者使用百分比来定义更复杂的过程 */
@keyframes bounce {0% {transform: translateY(0);}50% {transform: translateY(-30px);}100% {transform: translateY(0);}
}
  • animation-name: 你为这个关键帧序列自定义的名称(如 fadeIn, bounce)。
  • 关键帧选择器:
    • from / 0%: 动画的起点。
    • to / 100%: 动画的终点。
    • 25%, 50%...: 在动画序列中间定义的状态。百分比定义了该状态发生的时间点。

动画属性 (animation)

将定义好的 @keyframes 应用到一个或多个元素上,并控制动画的具体行为(如持续时间、速度曲线等)。

属性 描述 示例值
animation-name 指定要使用的 @keyframes 名称。 fadeIn, bounce
animation-duration 必须设置。定义一个动画周期的时长。 1s, 200ms
animation-timing-function 定义动画的速度曲线,即如何完成一个周期。 ease, linear, ease-in-out, cubic-bezier(0.1, 0.7, 1.0, 0.1)
animation-delay 定义动画开始前的等待时间。 2s, -1s (负值表示立即开始,但跳过指定时间)
animation-iteration-count 定义动画应播放的次数。 1(默认), 3, infinite(无限循环)
animation-direction 定义动画是否反向播放。 normal(默认), alternate(正反向交替)
animation-fill-mode 定义动画在执行前后如何将样式应用于其目标。 none, forwards(保留结束状态), backwards(应用起始状态), both
animation-play-state 允许暂停和恢复动画。 running(默认), paused

简写语法:

/* animation: name | duration | timing-function | delay | iteration-count | direction | fill-mode | play-state; */
.element {animation: bounce 2s ease-in-out 0.5s infinite alternate both paused;
}

重要属性

  1. animation-timing-function (速度曲线)

这是动画的灵魂,它决定了动画的“感觉”。

  • 关键字值:
    • ease: 默认值。慢开始,加速,然后慢结束。
    • linear: 匀速运动。
    • ease-in: 慢开始。
    • ease-out: 慢结束。
    • ease-in-out: 慢开始和慢结束。
  • cubic-bezier(n, n, n, n):
    • 贝塞尔曲线,允许你自定义速度曲线。
    • 可以使用浏览器的开发者工具来调试和生成。
    • 例如 cubic-bezier(0.68, -0.55, 0.27, 1.55) 可以创建一个弹跳效果。
  • steps(n, start|end):
    • 将动画分成 n 个等长的步进,而不是平滑过渡。
    • end(默认):每一步在每段结束时发生。
    • start:每一步在每段开始时发生。
    • 非常适合制作逐帧动画或打字机效果。
  1. animation-fill-mode (填充模式)

控制动画非执行阶段(开始前/结束后)的样式。

  • none (默认): 动画未执行时,元素使用其默认样式。
  • forwards: 动画完成后,元素将保留最后一帧的样式(由 100%to 定义)。
  • backwards: 在动画延迟 (animation-delay) 期间,元素将立即应用第一帧的样式(由 0%from 定义)。
  • both: 同时应用 forwardsbackwards 的规则。
  1. animation-direction (方向)
  • normal: 每次迭代都从 0% -> 100% 正向播放。
  • reverse: 每次迭代都从 100% -> 0% 反向播放。
  • alternate: 奇数次正向 (normal),偶数次反向 (reverse)。
  • alternate-reverse: 奇数次反向 (reverse),偶数次正向 (normal)。

实例

示例 1: 淡入效果 (Fade In)

<style>.box {width: 50px;height: 50px;background-color: aquamarine;}.fade-in {animation: fadeIn 1.5s ease-out forwards;}@keyframes fadeIn {from {opacity: 0;}to {opacity: 1;}}
</style><div class="box fade-in"></div>

示例 2: 跳动效果 (Bounce)

<style>.bounce {border-radius: 50%;animation: bounce 2s infinite;}@keyframes bounce {0%,20%,50%,80%,100% {transform: translateY(0);}40% {transform: translateY(-30px);}60% {transform: translateY(-15px);}}
</style><div class="box bounce"></div>

实例3:打字机效果

<style>.typewriter {width: fit-content;height: 100px;display: flex;justify-content: center;align-items: center;margin: 20px 0;}.typewriter-text {font-weight: bold;color: #fdbb2d;overflow: hidden;border-right: 3px solid #fdbb2d;white-space: nowrap;animation: typing 4s steps(28) infinite,blink-cursor 0.7s step-end infinite;}@keyframes typing {0% {width: 0;}50% {width: 100%;}90%,100% {width: 100%;}}@keyframes blink-cursor {from,to {border-color: transparent;}50% {border-color: #fdbb2d;}}
</style><div class="typewriter"><div class="typewriter-text">CSS steps() 动画非常强大!</div>
</div>

性能与最佳实践

  1. 优先使用 transformopacity

    • 更改这些属性不会触发昂贵的重排(Layout)或重绘(Paint),只会触发合成(Composition)。它们是性能最好的属性。
    • 高性能属性: transform, opacity, filter
    • 低性能属性: width, height, top, left, margin, padding 等(会触发重排)
  2. 使用 will-change 提示浏览器

    如果你知道某个元素即将被动画化,可以提前告知浏览器以优化性能。

    慎用:不要对所有元素都使用,这会消耗大量系统资源。只对需要复杂动画的元素使用。

    .element-to-animate {will-change: transform, opacity;
    }
    

网格布局Grid

CSS Grid 布局是一个二维的布局系统,这意味着它可以同时处理。Grid 允许你通过将 HTML 元素定义为一个网格容器,并将其子项目放置在预先定义或动态生成的网格单元格中,来构建复杂且响应式的布局。

概念

Grid Container(网格容器):通过设置 display: grid;display: inline-grid; 的元素。它的所有直接子元素都会自动成为 Grid Items(网格项目)

Grid Item(网格项目):Grid Container 的直接子元素。孙子元素不受影响。

.container {display: grid;
}

网格容器(Grid Container)的属性

这些属性定义在容器上,用于控制整个网格的结构。

1. 定义网格轨道(行和列)

  • grid-template-columns: 定义列的数量和宽度。

    • grid-template-columns: 100px 200px 100px; → 三列,宽度分别为 100px, 200px, 100px。
    • grid-template-columns: 1fr 2fr 1fr; → 三列,使用新的 fr 单位(fraction,分数)。意思是“将可用空间分成 4 等份(1+2+1),第一列和第三列各占 1 份,第二列占 2 份”。
    • grid-template-columns: repeat(3, 1fr);repeat() 函数,创建 3 列,每列宽度为 1fr
    • grid-template-columns: 200px 1fr auto; → 混合使用,非常灵活。
  • grid-template-rows: 定义行的数量和高度。

    • 用法与 grid-template-columns 完全相同。
  • grid-auto-rows / grid-auto-columns: 定义那些被隐式创建(即超出 template 定义范围)的网格轨道的大小。

    • 例如:你定义了 grid-template-rows: 100px;(只有一行),但你有 10 个项目,它们创建了 10 行。后面的 9 行就是隐式网格。你可以用 grid-auto-rows: 50px; 让它们都是 50px 高。
  • grid-auto-flow :控制着自动放置的网格项(即没有明确指定位置的网格项)在网格中的流动方向。也就是说,当网格项没有被明确指定放在哪个网格区域时,浏览器会自动为它们分配位置,而grid-auto-flow就决定了这个自动放置算法如何工作。

    • 语法:

      grid-auto-flow: [ row | column ] | dense | row dense | column dense;
      
    • 取值:

      • row(默认值):自动放置算法按照行依次填充,必要时会添加新行。
      • column:自动放置算法按照列依次填充,必要时会添加新列。
      • dense:使用“密集”打包算法,如果后面出现较小的网格项,则尝试填充网格中较早的空隙。这可能会改变网格项的自然顺序,但可以填满网格中的空白。
      • row dense:按行进行密集打包。
      • column dense:按列进行密集打包。
    • 如果没有设置dense,布局可能有空白,因为浏览器严格按顺序排列。如果设置dense,浏览器会尝试填充空白,布局更紧凑。

2. 网格间隙(Gutters)

  • gap (或 grid-gapgrid-gap 是旧标准,现推荐使用 gap)
    • row-gap: 设置行与行之间的间隙。
    • column-gap: 设置列与列之间的间隙。
    • gap: 20px 10px; → 第一个值是行间隙,第二个值是列间隙(类似于 margin 的简写)。

3. 网格区域和模板

  • grid-template-areas: 通过命名网格区域来定义一种可视化的布局结构,非常直观。

    .container {grid-template-areas:"header header header""sidebar main main""footer footer footer";
    }
    

    然后,项目可以使用 grid-area: header; 来将自己放置到对应的命名区域。

4. 对齐内容(在网格容器内)

这些属性控制整个网格在容器内的对齐方式(当网格总尺寸小于容器时)。

  • justify-content: 整个网格在水平方向上的对齐(start, end, center, stretch, space-around, space-between, space-evenly)。
  • align-content: 整个网格在垂直方向上的对齐(值同上)。
  • place-content: align-content / justify-content 的简写形式。

网格项目(Grid Item)的属性

这些属性定义在单个网格项目上,用于控制该项目在网格中的位置。

1. 基于线的放置(Line-based Placement)

Grid 网格有编号的线(从 1 开始,而不是 0)。你可以通过指定从哪条线开始到哪条线结束来放置项目。

  • grid-column-start: 项目开始的垂直网格线。
  • grid-column-end: 项目结束的垂直网格线。
  • grid-row-start: 项目开始的水平网格线。
  • grid-row-end: 项目结束的水平网格线。

简写形式:

  • grid-column: <start-line> / <end-line>;
    • grid-column: 1 / 3; → 从第1条垂直线跨越到第3条垂直线(即占据第1和第2列)。
    • grid-column: 2 / span 2; → 从第2条垂直线开始,跨越2个单元格。
  • grid-row: <start-line> / <end-line>; (用法同 grid-column)

2. 基于区域的放置(Area Placement)

  • grid-area: 为项目指定一个在 grid-template-areas 中定义的区域名称。

    css

    .item {grid-area: header;
    }
    

    它也可以是 grid-row-start / grid-column-start / grid-row-end / grid-column-end 的简写形式:
    grid-area: 1 / 1 / 3 / 2; (行开始 / 列开始 / 行结束 / 列结束)

3. 对齐项目(在单元格内)

这些属性控制单个项目在其所在网格单元格内的对齐方式。

  • justify-self: 项目在单元格内的水平对齐(start, end, center, stretch)。
  • align-self: 项目在单元格内的垂直对齐(值同上)。
  • place-self: align-self / justify-self 的简写形式。

4. 例子

<!DOCTYPE html>
<html>
<head>
<style>
.container {display: grid;grid-template-columns: 1fr 3fr 1fr; /* 三列,中间列是两侧的三倍宽 */grid-template-rows: 80px auto 80px; /* 三行,首尾固定高度,中间自适应 */gap: 15px;height: 100vh;grid-template-areas: "header header header""sidebar main ads""footer footer footer";
}.header   { grid-area: header; background: lightblue; }
.sidebar  { grid-area: sidebar; background: lightgreen; }
.main     { grid-area: main; background: lightyellow; }
.ads      { grid-area: ads; background: lightcoral; }
.footer   { grid-area: footer; background: lightgray; }/* 另一种基于线的放置方式(注释掉上面的 grid-area 规则即可启用) */
/*
.header {grid-column: 1 / 4;grid-row: 1;
}
.sidebar {grid-column: 1;grid-row: 2;
}
.main {grid-column: 2;grid-row: 2;
}
.ads {grid-column: 3;grid-row: 2;
}
.footer {grid-column: 1 / 4;grid-row: 3;
}
*/
</style>
</head>
<body><div class="container"><div class="header">Header</div><div class="sidebar">Sidebar</div><div class="main">Main Content</div><div class="ads">Ads</div><div class="footer">Footer</div>
</div></body>
</html>

综合练习1:https://codepen.io/small-windmill/pen/emJRXpZ?editors=1100

综合练习2:https://codepen.io/small-windmill/pen/MYKvOpa

min-content和max-content

min-content

  • 最小内容尺寸:元素在不溢出情况下能容纳内容的最小可能宽度
  • 对于文本:等于最长单词或不可断行元素的宽度
  • 会尽可能收缩,让内容换行

max-content

  • 最大内容尺寸:元素在不换行情况下能容纳内容的理想宽度
  • 对于文本:等于所有文本在一行内显示所需的宽度
  • 会尽可能扩展,避免内容换行
<style>.container {display: grid;gap: 10px;margin-bottom: 20px;width: 1000px;background-color: #ddd;}/* min-content 示例 */.min-content-example {grid-template-columns: min-content min-content min-content;}/* max-content 示例 */.max-content-example {grid-template-columns: max-content max-content max-content;}/* 固定宽度对比 */.fixed-example {grid-template-columns: 100px 100px 100px;}.item--1 {background-color: orangered;}.item--2 {background-color: yellowgreen;}.item--3 {background-color: blueviolet;}
</style><section class="grid-test"><!-- min-content-example / max-content-example / fixed-example--><div class="container max-content-example"><div class="item item--1">这是一个相对较长的文本内容</div><div class="item item--2">短文本</div><div class="item item--3">supercalifragilisticexpialidocious(超长单词)</div></div>
</section>

repeat(),minmax(), auto-fill和auto-fit

repeat()

repeat()是CSS Grid布局中的一个函数,它允许你重复一个轨道模式若干次,而不需要重复编写相同的值。

基本语法:repeat(重复次数, 轨道大小)

例如:创建4个等宽的列

.grid-container {/** grid-template-columns: 1fr 1fr 1fr 1fr; **/grid-template-columns: repeat(4, 1fr);
}

minmax()函数

minmax()函数允许你为网格轨道定义尺寸范围:

  • 第一个参数是最小值
  • 第二个参数是最大值
  • 例如:minmax(200px, 1fr) 表示轨道宽度至少200px,但最多不超过1fr

auto-fill

  • 尽可能多地创建网格轨道,即使它们没有内容也会保留空间
  • 适合需要固定网格线数量的布局
  • 示例:grid-template-columns:repeat(auto-fill,100px);

auto-fill

auto-fit

  • 尽可能多地创建网格轨道,但会折叠空轨道并将空间分配给现有项目
  • 适合内容数量可变的流体布局
  • 示例:grid-template-columns:repeat(auto-fit,100px);

auto-fit

区别

以下例子可以看到auto-fit和auto-fill的区别

<style>.grid-container {display: grid;margin: 12px auto;width: 1140px;column-gap: 12px;}.grid-item {background-color: deepskyblue;}.auto-fit {grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));}.auto-fill {grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));}
</style><div class="grid-container auto-fit"><div class="grid-item">测试1</div><div class="grid-item">测试2</div><div class="grid-item">测试3</div>
</div><div class="grid-container auto-fill"><div class="grid-item">测试1</div><div class="grid-item"></div><div class="grid-item">测试3</div>
</div>

对比

例子

auto-fit / auto-fill 与minmax的搭配使用

https://codepen.io/small-windmill/pen/qEbXVwY?editors=1100

应用例子

以下是用float写的布局

<style>:root {--grid-width: 1140px;--gutter-vertical: 80px;--gutter-horizontal: 60px;}.row {margin: 0 auto;max-width: var(--grid-width);background-color: #eee;}/* 除了最后一个孩子之外的所有行 */.row:not(:last-child) {margin-bottom: var(--gutter-vertical);}/* 清除浮动 */.row::after {display: table;clear: both;content: "";}/* 以col-开头的class属性 */[class^="col-"] {float: left;background-color: orangered;}[class^="col-"]:not(:last-child) {margin-right: var(--gutter-horizontal);}.col-1-of-2 {width: calc((100% - var(--gutter-horizontal)) / 2);}.col-1-of-3 {width: calc((100% - 2 * var(--gutter-horizontal)) / 3);}.col-2-of-3 {width: calc(((100% - 2 * var(--gutter-horizontal)) / 3) * 2 +var(--gutter-horizontal));}.col-1-of-4 {width: calc((100% - 3 * var(--gutter-horizontal)) / 4);}.col-2-of-4 {width: calc(((100% - 3 * var(--gutter-horizontal)) / 4) * 2 +var(--gutter-horizontal));}.col-3-of-4 {width: calc(((100% - 3 * var(--gutter-horizontal)) / 4) * 3 +var(--gutter-horizontal) * 2);}
</style><section class="grid-test"><div class="row"><div class="col-1-of-2">Col 1 of 2</div><div class="col-1-of-2">Col 1 of 2</div></div><div class="row"><div class="col-1-of-3">Col 1 of 3</div><div class="col-1-of-3">Col 1 of 3</div><div class="col-1-of-3">Col 1 of 3</div></div><div class="row"><div class="col-1-of-3">Col 1 of 3</div><div class="col-2-of-3">Col 2 of 3</div></div><div class="row"><div class="col-1-of-4">Col 1 of 4</div><div class="col-1-of-4">Col 1 of 4</div><div class="col-1-of-4">Col 1 of 4</div><div class="col-1-of-4">Col 1 of 4</div></div><div class="row"><div class="col-1-of-4">Col 1 of 4</div><div class="col-1-of-4">Col 1 of 4</div><div class="col-2-of-4">Col 2 of 4</div></div><div class="row"><div class="col-1-of-4">Col 1 of 4</div><div class="col-3-of-4">Col 3 of 4</div></div>
</section>

float布局

如果用grid改写的话:

<style>.grid {display: grid;margin: 0 auto var(--gutter-vertical); /* 设置行间距 */max-width: var(--grid-width);background-color: #eee;grid-template-columns: repeat(12, 1fr); /* 创建12列等宽网格 */gap: var(--gutter-horizontal); /* 设置列间距 */}.grid-item {background-color: orangered;}.col-3 {grid-column: span 3;}.col-4 {grid-column: span 4;}.col-6 {grid-column: span 6;}.col-8 {grid-column: span 8;}.col-9 {grid-column: span 9;}
</style><!-- 2等分 -->
<div class="grid"><div class="grid-item col-6">1 of 2</div><div class="grid-item col-6">2 of 2</div>
</div><!-- 3等分 -->
<div class="grid"><div class="grid-item col-4">1 of 3</div><div class="grid-item col-4">2 of 3</div><div class="grid-item col-4">3 of 3</div>
</div><!-- 1/3 + 2/3 -->
<div class="grid"><div class="grid-item col-4">1 of 3</div><div class="grid-item col-8">2 of 3</div>
</div><!-- 4等分 -->
<div class="grid"><div class="grid-item col-3">1 of 4</div><div class="grid-item col-3">2 of 4</div><div class="grid-item col-3">3 of 4</div><div class="grid-item col-3">4 of 4</div>
</div><!-- 1/4 + 1/4 + 2/4 -->
<div class="grid"><div class="grid-item col-3">1 of 4</div><div class="grid-item col-3">2 of 4</div><div class="grid-item col-6">3 of 4</div>
</div><!-- 1/4 + 3/4 -->
<div class="grid"><div class="grid-item col-3">1 of 4</div><div class="grid-item col-9">3 of 4</div>
</div>

Flex布局

参考阮一峰老师的Flex布局介绍

概念

Flexbox 一次只能处理一个维度(一行或一列)的布局。这与 CSS Grid 布局(二维,同时处理行和列)形成对比。

  • Flex容器:通过设置display属性为flexinline-flex来创建。它的所有直接子元素都会成为Flex项目。
  • Flex项目:Flex容器内的直接子元素。

Flex布局有两个轴:主轴交叉轴。主轴的方向由flex-direction属性定义,交叉轴则垂直于主轴。

Flex容器属性

display

定义容器为Flex布局。

.container {display: flex; /* 块级Flex容器 *//* 或者 */display: inline-flex; /* 行内Flex容器 */
}

flex-direction

.container {flex-direction: row; /* 默认值,主轴为水平方向,起点在左端 */flex-direction: row-reverse; /* 主轴为水平方向,起点在右端 */flex-direction: column; /* 主轴为垂直方向,起点在上沿 */flex-direction: column-reverse; /* 主轴为垂直方向,起点在下沿 */
}

flex-wrap

默认情况下,项目都排在一条轴线上。此属性定义如果一条轴线排不下,如何换行。

.container {flex-wrap: nowrap; /* 默认,不换行 */flex-wrap: wrap; /* 换行,第一行在上方 */flex-wrap: wrap-reverse; /* 换行,第一行在下方 */
}

flex-flow

flex-directionflex-wrap的简写形式,默认值为row nowrap

.container {flex-flow: row wrap;
}

justify-content

定义项目在主轴上的对齐方式。

.container {justify-content: flex-start; /* 默认值,左对齐 */justify-content: flex-end; /* 右对齐 */justify-content: center; /* 居中 */justify-content: space-between; /* 两端对齐,项目之间的间隔相等 */justify-content: space-around; /* 每个项目两侧的间隔相等,所以项目之间的间隔比项目与边框的间隔大一倍 */justify-content: space-evenly; /* 每个项目的间隔(包括与边框的间隔)都相等 */
}

align-items

定义项目在交叉轴上的对齐方式。

.container {align-items: stretch; /* 默认值,如果项目未设置高度或设为auto,将占满整个容器的高度 */align-items: flex-start; /* 交叉轴的起点对齐 */align-items: flex-end; /* 交叉轴的终点对齐 */align-items: center; /* 交叉轴的中点对齐 */align-items: baseline; /* 项目的第一行文字的基线对齐 */
}

align-content

定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。

.container {align-content: stretch; /* 默认值,轴线占满整个交叉轴 */align-content: flex-start; /* 与交叉轴的起点对齐 */align-content: flex-end; /* 与交叉轴的终点对齐 */align-content: center; /* 与交叉轴的中点对齐 */align-content: space-between; /* 与交叉轴两端对齐,轴线之间的间隔平均分布 */align-content: space-around; /* 每根轴线两侧的间隔都相等,所以轴线之间的间隔比轴线与边框的间隔大一倍 */align-content: space-evenly; /* 每根轴线的间隔(包括与边框的间隔)都相等 */
}

align-content 生效的关键条件:

  1. flex-wrap: wrapwrap-reverse
  2. ✅ 实际存在多行布局(项目换行)
  3. ✅ 容器在交叉轴方向有明确尺寸(高度或宽度)

Flex项目属性详解

order

控制项目的排列顺序:

.item {order: 0; /* 默认值 */order: 1; /* 数值越大,排列越靠后 */order: -1; /* 数值越小,排列越靠前 */
}

flex-grow

定义项目的放大比例:

.item {flex-grow: 0; /* 默认,不放大 */flex-grow: 1; /* 等分剩余空间 */flex-grow: 2; /* 占据其他项目两倍的空间 */
}

flex-shrink

定义项目的缩小比例:

.item {flex-shrink: 1; /* 默认,空间不足时缩小 */flex-shrink: 0; /* 不缩小,保持原尺寸 */flex-shrink: 2; /* 比其他项目缩小得更快 */
}

flex-basis

定义项目在分配多余空间之前的主轴尺寸:

.item {flex-basis: auto; /* 默认,项目本来大小 */flex-basis: 200px; /* 固定宽度 */flex-basis: 20%; /* 百分比宽度 */flex-basis: content; /* 基于内容自动计算 */
}

flex

flex-grow, flex-shrink, flex-basis 的简写:

.item {flex: 0 1 auto; /* 默认值 */flex: 1; /* 等价于 flex: 1 1 0% */flex: auto; /* 等价于 flex: 1 1 auto */flex: none; /* 等价于 flex: 0 0 auto */flex: 0 0 200px; /* 固定200px,不放大不缩小 */
}

align-self

允许单个项目有不同于其他项目的对齐方式:

.item {align-self: auto; /* 默认,继承 align-items */align-self: flex-start;align-self: flex-end;align-self: center;align-self: baseline;align-self: stretch;
}

例子

经典水平垂直居中

<style>
.center-container {display: flex;justify-content: center;align-items: center;height: 500px;
}
.item{width:50px;height:50px;background-color:pink;
}
</style><div class="center-container"><div class="item"></div>
</div>

圣杯布局

<style>
.holy-grail {display: flex;flex-direction: column;height: 500px;background-color: #bbb;
}.main-content {display: flex;flex: 1;
}main {flex: 1;order: 2;background-color: pink;
}nav {flex: 0 0 200px;order: 1;background-color: cornflowerblue;
}aside {flex: 0 0 250px;order: 3;background-color: bisque;
}
</style><div class="holy-grail"><header>Header</header><div class="main-content"><main>Main Content</main><nav>Navigation</nav><aside>Sidebar</aside></div><footer>Footer</footer>
</div>
http://www.hskmm.com/?act=detail&tid=32356

相关文章:

  • 长视频理解与生成技术突破
  • 27 LCA模拟赛3T3 三等分的数组 题解
  • 26 LCA模拟赛3T2 连边 题解
  • 28 S2模拟赛T2 开会council 题解
  • 25 LCA模拟赛3T1 ROI 2012马赛克 题解
  • 实验记录2025/10/14
  • 个人微信开发框架
  • 投资指标技术分析
  • linux源码编译python
  • uni-app x开发商城系统,Swiper 轮播图
  • 昂瑞微OM6651A:国产车规级蓝牙芯片的破局者
  • 2025年中央空调/锅炉房/机房运维服务厂家最新权威推荐榜:专业托管与维修外包一体化解决方案精选
  • 【终极解决方案】api-ms-win-core-path-l1-1-0.dll 缺失?Win7/Win10/Win11完整修复教程
  • 2025 年最新推荐分切机实力厂家权威榜单:覆盖全自动高速、铝箔、薄膜、高精度等机型,为软包装企业精选优质设备
  • 打破应用跳转流失困局,提升推广链接转化率
  • 性能测试进阶秘籍:如何用JMeter分布式压测挖掘系统极限潜
  • Codeforces Round 1058 (Div. 2) A~E
  • 2025 年生料带厂家最新推荐排行榜:解析优质品牌优势,涵盖新型、彩色、液态等多类型生料带厂家企业推荐
  • openresty开发lua-resty-openssl之对称加密解密 - liuxm
  • 哈希乱搞:CF1418G Three Occurrences
  • 2025 年废旧轮胎裂解加热生产厂家最新推荐榜单:优质企业专利技术、产能规模与口碑实力全景解析锂化工焚烧炉/氟化热风系统/煤化工热风炉厂家推荐
  • 悲伤 自卑 乖戾 独自哭泣 陪伴空虚 kill my memory 让我将痛苦全忘记
  • 日志 | 2025.10
  • 工程师的 “指尖实验室”!正点原子 LT1 电桥镊子深度测评:同价位竞品谁能打?
  • 【ACM出版|EI检索稳定】2025年AI驱动下:业务转型和数据科学创新国际学术会议(ICBTDS 2025)
  • 破解跨域监控难题:国标GB28181算法算力平台EasyGBS视频调阅技术在跨域安防监控中的核心应用
  • 2025 年电缆桥架源头厂家最新推荐排行榜:聚焦优质供应商核心竞争力,助力工程采购精准选型
  • 2025 年厂房出售公司服务推荐排行榜:珠三角/广州/深圳/东莞/佛山/珠海等城市优质厂房出售公司全面测评解析
  • 构建智能视觉中枢:国标GB28181算法算力平台EasyGBS的全域感知与播放方案
  • 别再乱排查了!Kafka 消息积压、重复、丢失,根源基本都是 Rebalance!