最近从别人那听说过来了一道题。具体来源好像是某家公司的面试题。题目乍一看上去很简单。但是冥思苦想之下发现,卧槽?有点东西!!!
好的,话不多说,先来看看是什么题。先和大家说好,这个题目据传当时千锋北京的一个著名主管做了40分钟才搞出来。看题 =>
如图所示
<style>
.big {
display: flex;
width: 600px;
height: 250px;
border: 1px solid black;
}
.big div {
height: 100px;
width: 100px;
border: 1px solid black;
}
</style>
<body>
<div class="big">
<div></div>
<div></div>
<div></div>
</div>
</body>
以上是html及css代码
问题是:你怎么样把第一张图的布局变成下面图中的布局?
你的第一反应一定是,你在侮辱我?这种东西我从出生时候就会做了。
不要着急。因为有要求:
- 不能修改html结构,不允许使用js,只能通过css来修改样式
- 不能使用margin、padding
- 不能使用浮动、定位
好了。现在你还有想法吗?看到这里如果有想去尝试的小伙伴就可以去尝试一下了。等到做不出来可以回来接着看。
好了,下面我们开始公布第一种最符合题意的答案。什么?我一点都想不出来这玩意居然有好多种做法?往下看 =>
第一种做法
我们先看一下题目,题目并没有要求我们必须使用flex布局,但是他起始代码中已经使用了flex,那我们就先往flex布局中考虑一下。一看这个形状我们想到的就是有没有一种特殊的主轴对齐方式,可以让3个盒子直接两个在左边,一个在右边呢?用space-between吗?还是用space-around?但是仔细一想好像都不行吧?因为这个显然不是平均分配,而主轴对齐的几个属性多多少少和平均分配有点关系。那要换轴吗?但是再一仔细想,换轴的本质其实是和不换是一样的啊,你并不能通过换轴来使得三个盒子不平均分配。因此,我们可以想到,这个必然是修改子盒子的某种属性,使得他们可以不平均占空间。那么flex布局中能给子盒子用的属性还有那些?
以下便是可以用在子盒子上的属性:
- order 盒子的排列顺序。数值越小,排列越靠前,默认为0。
- flex-grow 盒子的放大比例,默认为0,即如果存在剩余空间,也不放大。
- flex-shrink 盒子的缩小比例,默认为1,即如果空间不足,该盒子将缩小。
- flex-basis 在分配多余空间之前,盒子占据的主轴空间它的默认值为auto。
- flex 上面三种属性的复合属性,我们通常使用flex:1;或者flex:2;等简写形式
- align-items 单个盒子在侧轴上的位置
- align-content 多行时候的侧轴对齐方式
想到这里,我们就有些许灵感了。这些属性很多都是与占空间相关联。如果让第二个盒子占据剩余空间的所有是不是就能把第三个盒子挤到最右边了?来,试一试:
我们在css中加上这样一行代码:
<style>
.big {
display: flex;
width: 600px;
height: 250px;
border: 1px solid black;
}
.big div {
height: 100px;
width: 100px;
border: 1px solid black;
}
.big div:nth-child(2) {
flex: 1;
}
</style>
<body>
<div class="big">
<div></div>
<div></div>
<div></div>
</div>
</body>
此时,结果变成了这样:
嗯。。。。。这显然与我们所想还差点距离。因为使用了flex:1;属性后,第二个div宽度会被撑开。如果有一个透明的盒子放在这里就好了。。。。。透明的盒子。。。这个透明盒子还要在第二个和第三个盒子中间。。。。这时你陷入了沉思,仿佛进入了王阳明格竹的最后关头,仿佛进入了突破的边缘,仿佛要打开网球王子三扇门中的才气焕发,仿佛有什么东西要炸出来了。然后脑中炸响 ()=>
透明盒子 === 伪元素
顺序 === order
于是乎,你轻而易举的写出了下面的代码:
<style>
.big {
display: flex;
width: 600px;
height: 250px;
border: 1px solid black;
}
.big div {
height: 100px;
width: 100px;
border: 1px solid black;
}
/* .big div:nth-child(2) {
flex: 1;
} */
.big::after {
content: "";
flex: 1;
order: 2;
}
.big div:last-child {
order: 3;
}
</style>
<body>
<div class="big">
<div></div>
<div></div>
<div></div>
</div>
</body>
于是:
痛快!!此时你真的感觉自己简直是天才,才华横溢、才气焕发、英姿勃发,上能摘星揽月,下可入海捉龙。诸如尤雨溪、朴灵等人,皆是插标卖首之辈,如有机会,必将取而代之乎!
第二种做法(transform平移,不推荐,不喜欢)
这道题的题目一直在引导我们向flex布局上想,于是我们就会深陷其中,试了千百回也不能把效果真正的做出来。如果我们跳出禁锢区域呢?
三个盒子在左边,把它变成两个盒子在左边,一个盒子在右边。我们是否可以直接使用transform平移属性直接将第三个平移到最右边?
应该是确实可行的。不过总感觉这种做法失了一丝灵性,有点投机取巧的感觉。我很不喜欢这种做法,感觉像是硬凑出来的。不过不管了,只要我们将题做出来就能在干架时候比别人多一块板砖。看代码 =>
<style>
.big {
display: flex;
width: 600px;
height: 250px;
border: 1px solid black;
}
.big div {
height: 100px;
width: 100px;
border: 1px solid black;
}
.big div:last-child {
transform: translateX(296px); /*由于边框宽度,这里使用296px*/
}
</style>
<body>
<div class="big">
<div></div>
<div></div>
<div></div>
</div>
</body>
第三种做法(grid大人)
现在我们都在重视js以及数不胜数的框架,殊不知css也发展的极为迅速。各位可曾听闻网格(grid)布局?这个布局号称最强布局,即使是风靡世界的flex布局在他面前也只能喊饶命。
grid布局的诸多用法在这里即使说上三天三夜也说不完,废话不多说,且看我是如何使用grid大人手撕上面的题 =>
<style>
div {
box-sizing: border-box;
}
.big {
display: grid;
grid-template-columns: [one] 100px [two]auto [three]100px;
width: 600px;
height: 250px;
border: 1px solid black;
}
.big div {
height: 100px;
width: 100px;
border: 1px solid black;
}
</style>
<body>
<div class="big">
<div></div>
<div></div>
<div></div>
</div>
</body>
看效果
是的,你没看错。只有一行,使用grid大人可以狠狠的将这道题按在地上摩擦。grid不愧是号称最强布局,竟恐怖如斯!虽然grid布局用起来很爽,但前提是你能熟练的使用它,grid有着数不胜数的属性,远非flex可比。他掌握起来必有难度,但是当你能够熟练使用他的那一天,我想即使是普罗米修斯也要惧你三分。
好了,我们来短暂的介绍一下grid在本题中的用法 =>
网格(grid)布局说白了就是可以在当前区域内画格子,你可以随心所欲的控制当前区域内有几行(grid-template-row),每行里面有几个格子(grid-template-columns),格子的大小,也尽在把握之中。
如果后续还可能用到当前格子的话,可以使用[ ]给格子命名 。
比如本题中的用法:grid-template-columns: [one] 100px [two]auto [three]100px;
本题中就是直接把大盒子分成了三个区域,第一和第三个区域的宽度等于小盒子宽度100px,而第二个区域宽度让其自适应就可,便于后续修改。
grid的用法远远不止本文中说的三两句,本文只是让大家了解一下grid大人的出色之处。大家想看完整的介绍请点击下面链接: