一道前端面試題: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. 根據縮減分配比例求出具體縮減像素
相關文章
相關標籤/搜索