Advanced-Frontend / Daily-Interview-Question

我是依扬(木易杨),公众号「高级前端进阶」作者,每天搞定一道前端大厂面试题,祝大家天天进步,一年后会看到不一样的自己。

Home Page:https://muyiy.cn/question/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

第 155 题:求最终 left、right 的宽度

yygmind opened this issue · comments

<div class="container">
    <div class="left"></div>
    <div class="right"></div>
</div>

<style>
  * {
    padding: 0;
    margin: 0;
  }
  .container {
    width: 600px;
    height: 300px;
    display: flex;
  }
  .left {
    flex: 1 2 500px;
    background: red;
  }
  .right {
    flex: 2 1 400px;
    background: blue;
  }
</style>

先分析flex属性的信息
1.left容器 放大比例1,缩小比例 2 默认占500px
2.right容器 放大比例2,缩小比例 1 默认占400px

当子项目宽度总和大于父容器宽度时,如果有缩小比例将按照缩小比例进行压缩,比如子项目总和900px大于父容器600px,多出的300px将按照缩小比例进行压缩
left容器将会压缩2/3* 300 = 200px
right容器将会压缩1/3* 300 =100px
所以最终left和right宽度都是300px

同理当子项目宽度总和小于父容器宽度时,如果有放大比例将按照放大比例进行扩张。

浏览器跑一下吧,不是这个结果

left
父元素:600px
left:500px,shrink :2
right:400px,shrink :1
超了300px
left = leftWidth - overWidth * (leftWidth * leftShrink / ( leftWidth * leftShrink + rightWidth * rightShrink))
left = 500 - 300 * (500 * 2/( 500 * 2 + 400 * 1)) = 285.714

先分析flex属性的信息
1.left容器 放大比例1,缩小比例 2 默认占500px
2.right容器 放大比例2,缩小比例 1 默认占400px
当子项目宽度总和大于父容器宽度时,如果有缩小比例将按照缩小比例进行压缩,比如子项目总和900px大于父容器600px,多出的300px将按照缩小比例进行压缩
left容器将会压缩2/3* 300 = 200px
right容器将会压缩1/3* 300 =100px
所以最终left和right宽度都是300px
同理当子项目宽度总和小于父容器宽度时,如果有放大比例将按照放大比例进行扩张。

浏览器跑一下吧,不是这个结果

跑了一下,确实不是这个结果,希望大佬给出正确的解析

子元素的 flex-shrink 的值分别为 2,1
溢出:500+400 - 600 = 300。
总权重为 2 * 500+ 1 * 400 = 1400
两个元素分别收缩:
300 * 2(flex-shrink) * 500(width) / 1400= 214.28
300 * 1(flex-shrink) * 400(width) / 1400= 85.72
三个元素的最终宽度分别为:
500 - 214.28 = 285.72
400 - 85.72 = 314.28

子元素的 flex-shrink 的值分别为 2,1
溢出:500+400 - 600 = 300。
总权重为 2 * 500+ 1 * 400 = 1400
两个元素分别收缩:
300 * 2(flex-shrink) * 500(width) / 1400= 214.28
300 * 1(flex-shrink) * 400(width) / 1400= 85.72
三个元素的最终宽度分别为:
500 - 214.28 = 285.72
400 - 85.72 = 214.28

最后一个是 314.28~哈哈哈

对应题目:

  • 子项溢出空间的宽度为 $500 + 400 - 600 = 300$
  • left 收缩比例:$(500 × 2) ÷ (500 × 2 + 400 × 1) ≈ 0.7143$
  • right 收缩比例:$(400 × 1) ÷ (500 × 2 + 400 × 1) ≈ 0.2857$

对应的:

  • left 收缩宽度:$0.7143 × 300 = 214.29$
  • right 收缩宽度:$0.2857 × 300 = 85.71$

所以:

  • left 最终宽度:$500 - 214.29 = 285.71$
  • right 最终宽度:$400 - 85.71 = 314.29$

Demo

如果container的宽度是1000px, left 和 right 的宽度是怎么计算的?@timeyo @hexuan-aurora

如果container的宽度是1000px, left 和 right 的宽度是怎么计算的?@timeyo @hexuan-aurora

子元素的 flex-grow的值分别为 1,2
剩余空间:1000 - 500+400= 100。
子元素所得到的多余空间分别为:
100 * 1 / 3= 33.33
100 * 2 / 3 = 66.67
子元素最终宽度分别为:
500 + 33.33 = 533.33
400 + 66.67 =466.67

如果container的宽度是1000px, left 和 right 的宽度是怎么计算的?@timeyo @hexuan-aurora

子元素的 flex-grow的值分别为 1,2
剩余空间:1000 - 500+400= 100。
子元素所得到的多余空间分别为:
100 * 1 / 3= 33.33
100 * 2 / 3 = 66.67
子元素最终宽度分别为:
500 + 33.33 = 533.33
400 + 66.67 =466.67

谢谢答复, flex-grow 和 flex-shrink 的计算方式还不一样呢

commented

搜到一篇资料详细解释了flex-grow与flex-shrink。详解 flex-grow 与 flex-shrink

溢出300=500+400-600;
溢出部分均分成14份,14=(52+41);
(父元素不足分配时,取flex-shrink值,flex-basis值对应压缩)
left收缩=300*(10/14);
right收缩=300*(4/14);
减去收缩值,即最终长度。

@timeyo codepen 和我自己在页面内写里跑出来竟然都是 左300 右 300。。Chrome 81

image

image
那个是高度老哥。。。

@hansonfang 哈哈哈哈眼拙了不好意思,谢啦谢啦!!

commented
<div class="container">
    <div class="left"></div>
    <div class="right"></div>
</div>

<style>
  * {
    padding: 0;
    margin: 0;
  }
  .container {
    width: 600px;
    height: 300px;
    display: flex;
  }
  .left {
    flex: 1 2 500px;
    padding: 20px;
    border: 2px solid blue;
    background: red;
  }
  .right {
    flex: 2 1 400px;
    padding: 50px;
    border: 1px solid red;
    background: blue;
  }
</style>

我也出道题

commented

image

image

image

上面题目的答案

commented

我是这样理解的:

left + right > container 则此时需要收缩 flex-shrink生效
left + right = container 收缩、扩张均失效
left + right < container 则此时需要扩张 flex-grow生效

收缩计算过程:

  • 1.计算收缩值:500 + 400 - 600 = 300
  • 2.计算总的收缩权重值:500 * 2 + 400 × 1 = 1400
  • 3.计算项目收缩空间:(项目宽度 - 项目宽度 × 总溢出空间 × flex-shrink / 总权重)
    left = 500 - 500 × 300 × 2 / 1400 ≈ 285.71
    right = 400 - 400 × 300 × 1 / 1400 ≈ 314.28

扩张计算过程:

  • 1.计算扩张总内容 container - (left + right)
  • 2.计算每份扩张值:总内容/(left(flex-grow) + right(flex-grow))
  • 3.计算项目扩张大小:(项目宽度 + 每份扩张值 × 扩张系数(flex-grow))

我是这样理解的:

left + right > container 则此时需要收缩,反正则需要扩张

收缩计算过程:

  • 1.计算收缩值:500 + 400 - 600 = 300
  • 2.计算总的收缩权重值:500 * 2 + 400 × 1 = 1400
  • 3.计算项目收缩空间:(项目宽度 - 项目宽度 × 总溢出空间 × flex-shrink / 总权重)
    left = 500 - 500 × 300 × 2 / 1400 ≈ 285.71
    right = 400 - 400 × 300 × 1 / 1400 ≈ 314.28

扩张计算过程:

  • 1.计算扩张总内容 container - (left + right)
  • 2.计算每份扩张值:总内容/(left(flex-grow) + right(flex-grow))
  • 3.计算项目夸张大小:(项目宽度 + 每份扩张值 × 扩张系数(flex-grow))

应该是这样
//如果left + right = container,flex-grow和flex-shrink 失效;

子元素的 flex-shrink 的值分别为 2,1
溢出:500+400 - 600 = 300。
总权重为 2 * 500+ 1 * 400 = 1400
两个元素分别收缩:
300 * 2(flex-shrink) * 500(width) / 1400= 214.28
300 * 1(flex-shrink) * 400(width) / 1400= 85.72
三个元素的最终宽度分别为:
500 - 214.28 = 285.72
400 - 85.72 = 314.28

你们咋都这么厉害

left flex-basis=500
right flex-basis=400

容器总长度600
溢出长度(500+400)-600=300
加权factor综合为(5002+4001)=1400;
需要消化吸收的长度分别为:
500-(500:flex-basis*2:flex-shrink/1400)300:溢出宽度=285.71
400-(400:flex-basis
1:flex-shrink/1400)*300:溢出宽度=314.29

减小宽度计算公式

分配到的减小宽度 = 超出宽度 * (自身宽度 *(自身元素的 flex-shrink 值 / (所有子元素的 flex-shrink 值 * 自身宽度的和))

解题思路
flex: 1 2 500px;
// 等价于
flex-grow: 1;
flex-shrink: 2;
flex-basis: 500;

flex: 2 1 400px;
// 等价于
flex-grow: 2;
flex-shrink: 1;
flex-basis: 400;

因为 500 + 400 > 600,故需要使用 减小宽度计算公式

  • left 的宽度 = 500 - 300 * (500 * 2 / (500 * 2 + 1 * 400)) = 285.714
  • right 的宽度 = 400 - 300 * (400 * 1 / (500 * 2 + 1 * 400)) = 314.286

专门看了一眼定义,感觉这是我们初中做题时都会遇到的坑,放大和缩小计算方式不同的根本原因是比例问题的基准值
flex-grow: 项目的放大比例,按照比例分配多余空间,这个按比例放大的基准值是多出来的空间,所以156题的解法大家都觉得没什么问题
相同的解法,这题的答案却不正确了
flex-shrink: 项目的缩小比例,空间不足时,项目按比例缩小,缩小之后的宽度为600px,比例的问题不能简单的反向计算
设:left的缩小比例是2x,right的缩小比例是x
则:500 * (1 - 2x) + 400 * (1 - x) = 600

解得:x = 300 / 1400

left = 500 * (1 - 2x) = 285.7px
right = 400 * (1 - x) = 314.3px

这就是个初中就会遇到的的比例问题……大家要审题啊!

专门看了一眼定义,感觉这是我们初中做题时都会遇到的坑,放大和缩小计算方式不同的根本原因是比例问题的_基准值_
flex-grow: 项目的放大比例,按照比例分配_多余空间_,这个按比例放大的基准值是多出来的空间,所以156题的解法大家都觉得没什么问题
相同的解法,这题的答案却不正确了
flex-shrink: 项目的缩小比例,空间不足时,项目按比例缩小,缩小之后的宽度为600px,比例的问题不能简单的反向计算
设:left的缩小比例是2x,right的缩小比例是x
则:500 * (1 - 2x) + 400 * (1 - x) = 600

解得:x = 300 / 1400

left = 500 * (1 - 2x) = 285.7px
right = 400 * (1 - x) = 314.3px

这就是个初中就会遇到的的比例问题……大家要审题啊!

不错的角度,符合正常的逻辑

假如说有border以及padding,还需要考虑这些参数的影响,参考链接
填充和边框中的flex-shrink

先分析flex属性的信息
1.left容器 放大比例1,缩小比例 2 默认占500px
2.right容器 放大比例2,缩小比例 1 默认占400px
当子项目宽度总和大于父容器宽度时,如果有缩小比例将按照缩小比例进行压缩,比如子项目总和900px大于父容器600px,多出的300px将按照缩小比例进行压缩
left容器将会压缩2/3* 300 = 200px
right容器将会压缩1/3* 300 =100px
所以最终left和right宽度都是300px
同理当子项目宽度总和小于父容器宽度时,如果有放大比例将按照放大比例进行扩张。

浏览器跑一下吧,不是这个结果

image

专门看了一眼定义,感觉这是我们初中做题时都会遇到的坑,放大和缩小计算方式不同的根本原因是比例问题的_基准值_
flex-grow: 项目的放大比例,按照比例分配_多余空间_,这个按比例放大的基准值是多出来的空间,所以156题的解法大家都觉得没什么问题
相同的解法,这题的答案却不正确了
flex-shrink: 项目的缩小比例,空间不足时,项目按比例缩小,缩小之后的宽度为600px,比例的问题不能简单的反向计算
设:left的缩小比例是2x,right的缩小比例是x
则:500 * (1 - 2x) + 400 * (1 - x) = 600

解得:x = 300 / 1400

left = 500 * (1 - 2x) = 285.7px
right = 400 * (1 - x) = 314.3px

这就是个初中就会遇到的的比例问题……大家要审题啊!

这个思路很棒!

commented

专门看了一眼定义,感觉这是我们初中做题时都会遇到的坑,放大和缩小计算方式不同的根本原因是比例问题的_基准值_
flex-grow: 项目的放大比例,按照比例分配_多余空间_,这个按比例放大的基准值是多出来的空间,所以156题的解法大家都觉得没什么问题
相同的解法,这题的答案却不正确了
flex-shrink: 项目的缩小比例,空间不足时,项目按比例缩小,缩小之后的宽度为600px,比例的问题不能简单的反向计算
设:left的缩小比例是2x,right的缩小比例是x
则:500 * (1 - 2x) + 400 * (1 - x) = 600

解得:x = 300 / 1400

left = 500 * (1 - 2x) = 285.7px
right = 400 * (1 - x) = 314.3px

这就是个初中就会遇到的的比例问题……大家要审题啊!

由left = 500 * (1 - 2x) = 285.7px 可推导出left须缩小 300* 1000 / 1400=500-left;
由right = 400 * (1 - x) = 314.3px 可推导出right须缩小 300* 400 / 1400=400-right;
缩小时基准可为乘积的和,即500 * 2+400 * 1。

commented

总权重和 2 * 500+ 1 * 400 = 1400
溢出空间 500 + 400 - 600 = 300px
盒子宽度 = 默认宽度 - (盒子收缩权重/收缩总权重和) * 总溢出空间

left宽度 = 500px - (5002/1400) * 300 = 285.7px
right宽度 = 400px - (400
1/1400) * 300 = 314.3px