一道前端面试题:flex空间分配规则

这是字节跳动的的一道面试题。css

原题

* {
	padding: 0;
	margin: 0;
}
.container {
	width: 600px;
	height: 300px;
	display: flex;
}
.left {
	width: 500px;
	flex-shrink: 2;
	background: red;
}
.right {
	width: 400px;
	flex-shrink: 1;
	background: blue;
}
复制代码

求最终left和right的宽度。面试

解析

先看实际展现的效果bash

left: 285.72px

right: 314.28px
复制代码

从上面的结果来看,当子容器宽度之和超出父容器宽度以后不是仅仅按照500:400 或者 2:1来计算的,实际计算过程应该是这个样子的:布局

  1. 计算出超出部分:500+400-600=300
  2. 注意,重点来了,超出部分实际的分配比例:500x2:400x1 也就是5:2
  3. 那么left的宽就是: 500 - 3005/7 ≈ 285.71, right: 400 - 3002/7 ≈ 314.29, 符合实际状况。

延伸

咱们加上paddingflex

* {
	padding: 0;
	margin: 0;
}
.container {
	width: 600px;
	height: 300px;
	display: flex;
}
.left {
	width: 500px;
	padding: 40px;
	flex-shrink: 2;
	background: red;
}
.right {
	width: 400px;
	padding: 20px;
	flex-shrink: 1;
	background: blue;
}
复制代码

实际效果是:flexbox

left: 280px

right: 320px
复制代码

先想一想结果为何会变化?spa

缘由是code

  1. 当咱们不设置box-sizing时,其默认值是content-box,也就是标准盒模型,盒子的宽是不包括paddingborder的,因此若是不考虑父容器的宽度,left真正占据的空间应该是500 + 40x2 = 580, 而right则是:400 + 40x2=440。
  2. flex项计算可用空间时,padding部分会被冻结不参与分配。因而left的可用空间就是 580-40x2=500, right的可用空间是440-20x2=400。

下面是w3c对flex布局中可用空间的描述get

w3c: Determine the available main and cross space for the flex items. For each dimension, if that dimension of the flex container’s content box is a definite size, use that; if that dimension of the flex container is being sized under a min or max-content constraint, the available space in that dimension is that constraint; otherwise, subtract the flex container’s margin, border, and padding from the space available to the flex container in that dimension and use that value. This might result in an infinite value.it

这里提到flex项的可用空间要减去margin、border、padding。

因此这里计算的过程就是:

  1. 计算超出部分,按照真正占用空间计算:580+440-600=420
  2. 超出部分实际的分配比例,不包含padding:500x2:400x1 也就是5:2
  3. 那么left的宽就是: 580 - 420x5/7 = 280, right的宽是: 440 - 420x2/7 = 320, 符合实际状况。

ok,那咱们再看看 box-sizing: border-box的状况

* {
		padding: 0;
		margin: 0;
	}
	.container {
		width: 600px;
		height: 300px;
		display: flex;
	}
	.left {
		width: 500px;
		padding: 40px;
		flex-shrink: 2;
		background: red;
		box-sizing: border-box;
	}
	.right {
		width: 400px;
		padding: 20px;
		flex-shrink: 1;
		background: blue;
		box-sizing: border-box;
	}
复制代码

实际效果是

left: 290px

right: 310px
复制代码

当咱们设置box-sizing: border-box,也就是IE盒模型,盒子的宽是包括paddingborder的,若是不考虑父容器宽度的话,left真正占据的空间依然是500 right是400,padding依然不能参与分配,那么left、right的可用空间分别就变成了500-40x2=420, 400-20x2=360, 因此这里计算的过程就是:

  1. 计算出超出部分, 按真正占用空间计算:500+400-600=300
  2. 超出部分实际的分配比例, 不包含padding:420x2:360x1 也就是7:3
  3. 那么left的宽就是: 500 - 300x7/10 = 290, right的宽是: 400 - 300x3/10 = 310, 符合实际状况。

总结

咱们总结一下计算过程

  1. 按照子元素实际占用空间(不考虑父容器宽度的状况下),求出超出部分
  2. 根据子元素实际占用空间减去margin、padding、border后获得的可用空间和flex缩小或放大倍数加权计算超出部分的分配比例
  3. 根据缩减分配比例求出具体缩减像素
相关文章
相关标签/搜索