CSS 布局原理

可以少去理解一些不必要的概念,而多去思考为什么会有这样的东西,它解决了什么问题,或者它的运行机制是什么?

CSS 的布局原理是一套基于 ‌浏览器渲染引擎‌ 的复杂规则,其核心逻辑是通过布局模型(Layout Model)‌ 和 ‌盒子模型(Box Model)‌ 的协同工作来确定元素的位置和尺寸。以下是分步解析:

一. 盒子模型‌

定义元素自身的尺寸结构。盒子模型定义了单个元素的‌内容区域(content)‌、‌内边距(padding)‌、‌边框(border)‌ 和 ‌外边距(margin)‌:

div {
  width: 200px;         /* 内容宽度 */
  padding: 20px;        /* 内边距 */
  border: 2px solid;    /* 边框 */
  margin: 10px;         /* 外边距 */
}

总宽度‌ = width + padding*2 + border*2 + margin*2

布局影响‌:盒子模型仅决定元素自身的尺寸,但元素如何与其他元素排列由布局模型决定。

二. 布局模型‌

布局模型定义元素之间的空间分配。CSS 布局基于不同的布局模式‌,每种模式定义了元素如何占据空间和相互影响:

1. ‌常规流(Normal Flow)

  • 默认布局模式‌:元素按 HTML 顺序从上到下、从左到右排列。

  • 块级元素‌(如 div)独占一行,宽度默认撑满父容器。

  • 行内元素‌(如 span)同行排列,宽度由内容决定。‌

  • 示例:

    <div>块级元素1</div>   <!-- 占一行 -->
    <span>行内元素1</span>  <!-- 同行 -->
    <span>行内元素2</span>
    

2. ‌定位(Position)

  • ‌static:没有定位,遵循正常的文档流对象。

  • ‌fixed:固定定位‌(position: fixed):元素的位置相对于浏览器窗口是固定位置。定位使元素的位置与文档流无关,因此不占据空间,重叠。Fixed 定位的元素和其他元素重叠。

  • relative:相对定位元素的定位是相对其自身正常位置。移动相对定位元素,但它原本所占的空间不会改变。相对定位元素经常被用来作为绝对定位元素的容器块。

  • absolute:绝对定位的元素的位置相对于最近的已定位(Position)父元素,如果元素没有已定位的父元素,那么它的位置相对于。元素的定位与文档流无关,因此不占据空间,重叠。

  • sticky:基于用户的滚动位置来定位。粘性定位的元素是依赖于用户的滚动,在 position:relativeposition:fixed 定位之间切换。

  • ‌示例‌:

    .modal {
      position: fixed;
      top: 50%;
      left: 50%;
      transform: translate(-50%, -50%);
    }
    

解析1:若父容器没有设置定位,绝对定位子元素会继续向上查找最近的定位祖先:

<div class="grandparent" style="position: relative">
  <div class="parent"> <!-- 未定位 -->
    <div class="child" style="position: absolute">
      <!-- 将相对于 .grandparent 定位 -->
    </div>
  </div>
</div>

3. ‌浮动(Float)

  • 脱离常规流‌:元素向左/右浮动,其他内容环绕它。

  • 用途‌:传统多栏布局(现逐渐被 Flex/Grid 取代)。

  • ‌示例:

    .left { float: left; width: 30%; }
    .right { float: right; width: 70%; }
    

4. ‌弹性盒子(Flexbox)

4.1 弹性盒子布局概念

引入弹性盒布局模型的目的是提供一种更加有效的方式来对一个容器中的子元素进行排列、对齐和分配空白空间。

Flex 是 Flexible Box 的缩写,意为“弹性布局”,用来为盒状模型提供最大的灵活性。任何一个容器都可以指定为 Flex 布局。比如:

.box{
     display:flex;
}

容器、项目的理解?

采用 Flex 布局的元素,称为 Flex 容器(container),称为“容器”。它的所有子元素自动成为容器成员,称为 Flex 项目、元素(item)。

1. 弹性盒子布局模型

容器两根轴线:主轴、交叉轴:

水平的主轴(main axis):主轴的开始位置(与边框的交叉点)叫做 main start,结束位置叫做 main end;

垂直的交叉轴(cross axis):交叉轴的开始位置叫做 cross start,结束位置叫做cross end。

项目默认沿主轴排列。单个项目占据的主轴空间叫做 main size,占据的交叉轴空间叫做 cross size。

4.2 容器的属性

https://baijiahao.baidu.com/s?id=1711671351238047881&wfr=spider&for=pc

详细记录各项属性之前,先看下基础样式代码及效果如下所示:

<div class="box">
    <div class="item">1</div>
    <div class="item">2</div>
    <div class="item">3</div>
</div>
.box{
	width: 500px;
	height:200px;
	padding: 10px;
	border: 2px solid red;
	display: flex;
}
.item {
	width: 50px;
	height: 50px;
	color: white;
	font-size: 1.4em;
	text-align: center;
	line-height: 50px;
	margin: 1px 1px;
	background: #1f1d99;
}

默认的布局方式,由于子元素是 div 以及自身属于块级元素,所以独立占据一行,下面我们给外层盒子添加 display:flex看看效果:

1.2 示例基础样式

1)布局方向 flex-direction

设置主轴方向(布局方向),即项目排列方式,默认 row。它有如下4个值:row、row-reverse、column、column-reverse。

  • row(默认值):主轴为水平方向,起点在左端。
  • row-reverse:主轴为水平方向,起点在右端。
  • column:主轴为垂直方向,起点在上沿。
  • column-reverse:主轴为垂直方向,起点在下沿。
2)布局换行 flex-wrap

默认情况下,项目都排在一条线(又称”轴线”)上。flex-wrap 属性定义,如果一条轴线排不下,如何换行,它有如下3个值:nowrap(默认)、wrap 、wrap-reverse

  • nowrap(默认):不换行。
  • wrap:换行,每一行子元素按照主轴方向排列。
  • wrap-reverse:换行,每一行子元素按照主轴反方向排列。
3)组合形式 flex-flow

flex-flow 是 flex-direction 属性和 flex-wrap 属性的简写形式,默认值为 row 、nowrap。

4)主轴对齐方式 justify-content

设置项目在主轴上都对其方式,它有如下5个值:center、flex-start、flex-end、space-between、space-around。具体对齐方式与轴的方向有关,这里以主轴为从左到右为例:

  • flex-start(默认值):左对齐。
  • flex-end:右对齐。
  • center:居中。
  • space-between:两端对齐,项目之间的间隔都相等。
  • space-around:每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。
  • space-evenly:完全平均间隔
5)交叉轴对齐方式 align-items

align-items 属性定义项目在交叉轴上如何对齐,它有如下5个值:center、flex-start、flex-end、stretch(默认)、baseline 。具体的对齐方式与交叉轴的方向有关,这里以交叉轴从上到下为例:

  • flex-start:交叉轴的起点对齐。
  • flex-end:交叉轴的终点对齐。
  • center:交叉轴的中点对齐。
  • stretch(默认):如果项目未设置高度或设为auto,将占满整个容器的高度。
  • baseline: 项目的第一行文字的基线对齐。
6)align-content

align-content 属性用于修改 flex-wrap 属性的行为。类似于 align-items, 但它不是设置弹性子元素的对齐,而是设置各个行的对齐。

align-content 属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性与 align-items 属性效果相同。它有如下6个值:center、flex-start、flex-end、space-between、space-around、stretch。

  • flex-start:与交叉轴的起点对齐。
  • flex-end:与交叉轴的终点对齐。
  • center:与交叉轴的中点对齐。
  • space-between:与交叉轴两端对齐,轴线之间的间隔平均分布
  • space-around:每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍。
  • stretch(默认值):轴线占满整个交叉轴。
4.3 项目的属性

https://zhuanlan.zhihu.com/p/440852043

1)order

order 属性定义项目的排列顺序。数值越小,排列越靠前,默认为 0。

2)flex-grow

flex-grow 弹性放大,属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。

3)flex-shrink

flex-shrink 弹性收缩,属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。如果设置为0,该项目不缩小。

4)flex-basis

flex-basis 在 Flex 布局中,一个 Flex 子项的宽度是由元素自身尺寸,flex-basis 设置的基础尺寸,以及外部填充(flex-grow)或收缩(flex-shrink)规则3者共同决定的。

https://blog.csdn.net/qq_41635167/article/details/104190865

5)flex

flex 属性是 flex-grow、flex-shrink、和 flex-basis 的简写,默认值为 0 1 auto。后两个属性可选。

6)align-self

align-self 属性用于设置弹性元素自身在侧轴(纵轴)方向上的对齐方式。

align-self 属性允许单个项目有与其他项目不一样的对齐方式,可覆盖 align-items 属性。默认值为 auto,表示继承父元素的 align-items 属性,如果没有父元素,则等同于 stretch。

5. ‌网格布局(Grid)

二维布局‌:将容器划分为行和列的网格单元。

用途‌:复杂页面布局(如仪表盘、新闻排版)。

示例‌:

.container {
  display: grid;
  grid-template-columns: 1fr 2fr; /* 两列,比例1:2 */
  gap: 20px;                      /* 间距 */
}

6. 布局模式对比

布局模式 维度 典型用途 控制粒度
Normal Flow 一维 文档基础排版
Flexbox 一维 弹性排列、对齐
Grid 二维 复杂网格布局 极高
Float 一维 图文混排(传统方案)
Absolute 坐标 弹窗、固定元素 精确

三、‌布局引擎的工作流程

浏览器渲染引擎按以下步骤计算布局:

  1. 构建 DOM 树‌:解析 HTML 生成节点树。
  2. 构建 CSSOM 树‌:解析 CSS 生成样式规则。
  3. 合并生成渲染树‌:将 DOM 和 CSSOM 结合,排除不可见元素(如 display: none)。
  4. 布局(Layout/Reflow)‌:计算每个渲染树节点的位置和尺寸。
  5. 绘制(Paint)‌:将布局结果转换为屏幕像素。

四、‌核心布局规则

  1. 包含块(Containing Block)‌:元素的尺寸和位置通常相对于其包含块计算。例如:

    • 块级元素的宽度默认撑满包含块。
    • position: absolute 的包含块是最近的非 static 祖先。
  2. 块级格式化上下文(BFC)‌:一种隔离的布局环境,解决浮动、外边距合并等问题:

    .container {
      overflow: hidden; /* 创建 BFC */
    }
    
  3. 外边距合并(Margin Collapsing)
    相邻块级元素的上下外边距会合并为单个外边距(取较大值)。

五. 布局最佳实践‌

  1. 优先使用 Flex/Grid‌:替代传统的 Float 和绝对定位。

  2. 避免过度嵌套‌:减少布局复杂度。

  3. ‌利用 CSS 变量‌:动态调整布局参数:

    :root {
      --gap: 20px;
    }
    .container {
      gap: var(--gap);
    }
    
  4. 响应式设计:通过媒体查询适配不同屏幕

    @media (max-width: 768px) {
      .container {
        grid-template-columns: 1fr;
      }
    }
    

CSS 布局通过盒子模型‌定义元素自身尺寸,再通过布局模型‌(如 Flexbox、Grid)决定元素之间的空间分配。它不是简单的坐标或约束,而是通过一系列规则(包含块、格式化上下文等)动态计算元素的位置和尺寸,最终实现灵活、响应式的页面排版。

posted @ 2024-01-17 16:29  背包の技术  阅读(439)  评论(0)    收藏  举报