Flex 布局目前已经非常流行了,现在几乎已经兼容所有浏览器了。在文章开始之前我们需要思考一个问题:我们为什么要使用 Flex 布局?
其实答案很简单,那就是 Flex 布局好用。一个新事物的出现往往是因为旧事物不那么好用了,比如,如果想让你用传统的 css 布局来实现一个块元素垂直水平居中你会怎么做?实现水平居中很简单,margin: 0 auto就行,而实现垂直水平居中则可以使用定位实现:
<div class="container">
<div class="item"></div>
</div>
.container {
position: relative;
width: 300px;
height: 300px;
background: red;
}
.item {
position: absolute;
background: black;
width: 50px;
height: 50px;
margin: auto;
left: 0;
top: 0;
bottom: 0;
right: 0;
}
或者
.item {
position: absolute;
background: black;
width: 50px;
height: 50px;
margin: auto;
left: calc(50% - 25px);
top: calc(50% - 25px);
}
但是这样都显得特别繁琐,明明可以一个属性就能解决的事情没必要写这么麻烦。而使用 Flex 则可以使用 place-content 属性简单的实现(place-content 为 justify-content 和 align-content 简写属性)
.container {
width: 300px;
height: 300px;
background: red;
display: flex;
place-content: center;
}
.item {
background: black;
width: 50px;
height: 50px;
}
接下来的本篇文章将会带领大家一起来探讨Flex布局
我们先写一段代码作为示例(部分属性省略)
html
<div class="container">
<div class="item">flex项目</div>
<div class="item">flex项目</div>
<div class="item">flex项目</div>
<div class="item">flex项目</div>
</div>
.container {
display: flex;
width: 800px;
gap: 10px;
}
.item {
color: #fff;
}
我们可以将一个元素的 display 属性设置为 flex,此时这个元素则成为flex 容器比如container元素
flex 容器的子元素称为flex 项目,比如item元素
flex 布局有两个轴,主轴和交叉轴,至于哪个是主轴哪个是交叉轴则有flex 容器的flex-direction属性决定,默认为:flex-direction:row,既横向为主轴,纵向为交叉轴,
flex-direction还可以设置其它三个属性,分别为row-reverse,column,column-reverse。
从这里我们可以看出 Flex 轴的方向不是固定不变的,它受到flex-direction的影响
当 Flex 项目总宽度小于 Flex 容器宽度时就会出现剩余空间
当 Flex 项目总宽度大于 Flex 容器宽度时就会出现不足空间
Flex 项目之间的间距可以直接在 Flex 容器上设置 gap 属性即可,如
<div class="container">
<div class="item">A</div>
<div class="item">B</div>
<div class="item">C</div>
<div class="item">D</div>
</div>
.container {
display: flex;
width: 500px;
height: 400px;
gap: 10px;
}
.item {
width: 150px;
height: 40px;
}
flex属性是flex-grow,flex-shrink,flex-basis三个属性的简写。下面我们来看下它们分别是什么。
flex-basis可以设定 Flex 项目的大小,一般主轴为水平方向的话和 width 解析方式相同,但是它不一定是 Flex 项目最终大小,Flex 项目最终大小受到flex-grow,flex-shrink以及剩余空间等影响,后面文章会告诉大家最终大小的计算方式
flex-grow为 Flex 项目的扩展系数,当 Flex 项目总和小于 Flex 容器时就会出现剩余空间,而flex-grow的值则可以决定这个 Flex 项目可以分到多少剩余空间
flex-shrink为 Flex 项目的收缩系数,同样的,当 Flex 项目总和大于 Flex 容器时就会出现不足空间,flex-shrink的值则可以决定这个 Flex 项目需要减去多少不足空间
既然flex属性是这三个属性的简写,那么flex属性简写方式分别代表什么呢?
flex属性可以为 1 个值,2 个值,3 个值,接下来我们就分别来看看它们代表什么意思
如果flex属性只有一个值的话,我们可以看这个值是否带单位,带单位那就是flex-basis,不带就是flex-grow
.item {
flex: 1;
/* 相当于 */
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
}
.item {
flex: 30px;
/* 相当于 */
flex-grow: 1;
flex-shrink: 1;
flex-basis: 30px;
}
当flex属性有两个值的话,第一个无单位的值就是flex-grow,第一个无单位的值则是flex-shrink,有单位的就是flex-basis
.item {
flex: 1 2;
/* 相当于 */
flex-grow: 1;
flex-shrink: 2;
flex-basis: 0;
}
.item {
flex: 30px 2;
/* 相当于 */
flex-grow: 2;
flex-shrink: 1;
flex-basis: 30px;
}
当flex属性有三个值的话,第一个无单位的值就是flex-grow,第一个无单位的值则是flex-shrink,有单位的就是flex-basis
.item {
flex: 1 2 10px;
/* 相当于 */
flex-grow: 1;
flex-shrink: 2;
flex-basis: 10px;
}
.item {
flex: 30px 2 1;
/* 相当于 */
flex-grow: 2;
flex-shrink: 1;
flex-basis: 30px;
}
.item {
flex: 2 30px 1;
/* 相当于 */
flex-grow: 2;
flex-shrink: 1;
flex-basis: 30px;
}
另外,flex 的值还可以为initial,auto,none。
initial 为默认值,和不设置 flex 属性的时候表现一样,既 Flex 项目不会扩展,但会收缩,Flex 项目大小有本身内容决定
.item {
flex: initial;
/* 相当于 */
flex-grow: 0;
flex-shrink: 1;
flex-basis: auto;
}
当 flex 设置为 auto 时,Flex 项目会根据自身内容确定flex-basis,既会拓展也会收缩
.item {
flex: auto;
/* 相当于 */
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;
}
none 表示 Flex 项目既不收缩,也不会扩展
.item {
flex: none;
/* 相当于 */
flex-grow: 0;
flex-shrink: 0;
flex-basis: auto;
}
首先看一下 flex-grow 的计算方式
面试中经常问到: 为什么 flex 设置为 1 的时候,Flex 项目就会均分 Flex 容器? 其实 Flex 项目设置为 1 不一定会均分容器(后面会解释),这里我们先看下均分的情况是如何发生的
同样的我们先举个例子
<div class="container">
<div class="item">Xiaoyue</div>
<div class="item">June</div>
<div class="item">Alice</div>
<div class="item">Youhu</div>
<div class="item">Liehuhu</div>
</div>
.container {
display: flex;
width: 800px;
}
.item {
flex: 1;
font-size: 30px;
}
flex 容器总宽度为 800px,flex 项目设置为flex:1,此时页面上显示
我们可以看到每个项目的宽度为 800/5=160,下面来解释一下为什么会均分:
首先
.item {
flex: 1;
/* 相当于 */
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
}
因为flex-basis为 0,所有 Flex 项目扩展系数都是 1,所以它们分到的剩余空间都是一样的。下面看一下是如何计算出最终项目大小的
这里先给出一个公式:
Flex项目弹性量 = (Flex容器剩余空间/所有flex-grow总和)*当前Flex项目的flex-grow
其中Flex项目弹性量指的是分配给 Flex 项目多少的剩余空间,所以 Flex 项目的最终宽度为
flex-basis+Flex项目弹性量。
根据这个公式,上面的均分也就很好理解了,因为所有的flex-basis为 0,所以剩余空间就是 800px,每个 Flex 项目的弹性量也就是(800/1+1+1+1+1)*1=160,那么最终宽度也就是160+0=160
刚刚说过 flex 设置为 1 时 Flex 项目并不一定会被均分,下面就来介绍一下这种情况,我们修改一下示例中的 html,将第一个 item 中换成一个长单词
<div class="container">
<div class="item">Xiaoyueyueyue</div>
<div class="item">June</div>
<div class="item">Alice</div>
<div class="item">Youhu</div>
<div class="item">Liehu</div>
</div>
此时会发现 Flex 容器并没有被均分
因为计算出的灵活性 200px 小于第一个 Flex 项目的min-content(217.16px),此时浏览器会采用 Flex 项目的min-content作为最终宽度,而后面的 Flex 项目会在第一个 Flex 项目计算完毕后再进行同样的计算
我们修改一下 flex,给它设置一个 flex-basis,看下它计算之后的情况
.item {
text-align: center;
flex: 1 100px;
}
因为每个项目的flex-basis都是 100px,Flex 容器剩余空间为800-500=300px,所以弹性量就是(300/5)*1=60px,最终宽度理论应该为100+60=160px,同样的因为第一个 Flex 项目的min-content为 217.16px,所以第一个 Flex 项目宽度被设置为 217.16px,最终表现和上面一样
我们再来看一下为什么第 2,3,4,5 个 Flex 项目宽度为什么是 145.71px
当浏览器计算完第一个 Flex 项目为 217.16px 后,此时的剩余空间为800-217.16-100*4=182.84,第 2 个 Flex 项目弹性量为(182.84/1+1+1+1)*1=45.71,所以最终宽度为100+45.71=145.71px,同样的后面的 Flex 项目计算方式是一样的,但是如果后面再遇到长单词,假如第五个是长单词,那么不足空间将会发生变化,浏览器会将第五个 Flex 项目宽度计算完毕后再回头进行一轮计算,具体情况这里不再展开
所以说想要均分 Flex 容器 flex 设置为 1 并不能用在所有场景中,其实当 Flex 项目中有固定宽度元素也会出现这种情况,比如一张图片等,当然如果你想要解决这个问题其实也很简单,将 Flex 项目的min-width设置为 0 即可
.item {
flex: 1 100px;
min-width: 0;
}
flex-grow 的值不仅可以为正整数,还可以为小数,当为小数时也分为两种情况:所有 Flex 项目的 flex-grow 之和小于等于 1 和大于 1,我们先看小于等于 1 的情况,将例子的改成
<div class="container">
<div class="item">Acc</div>
<div class="item">Bc</div>
<div class="item">C</div>
<div class="item">DDD</div>
<div class="item">E</div>
</div>
.item:nth-of-type(1) {
flex-grow: 0.1;
}
.item:nth-of-type(2) {
flex-grow: 0.2;
}
.item:nth-of-type(3) {
flex-grow: 0.2;
}
.item:nth-of-type(4) {
flex-grow: 0.1;
}
.item:nth-of-type(5) {
flex-grow: 0.1;
}
效果如图
我们可以发现项目并没有占满容器,它的每个项目的弹性量计算方式为
Flex项目弹性量=Flex容器剩余空间*当前Flex项目的flex-grow
相应的每个项目的实际宽度也就是flex-basis+弹性量,首先先不设置 flex-grow,我们可以看到每个项目的 flex-basis 分别为: 51.2 , 33.88 , 20.08 , 68.56 , 16.5
所以我们可以计算出 Flex 容器的剩余空间为800-51.2 -33.88 - 20.08 - 68.56 - 16.5=609.78,这样我们就可以算出每个项目的实际尺寸为
A: 实际宽度 = 51.2 + 609.78*0.1 = 112.178
B: 实际宽度 = 33.88 + 609.78*0.2 = 155.836
...
下面看下 flex-grow 之和大于 1 的情况,将例子中的 css 改为
.item:nth-of-type(1) {
flex-grow: 0.1;
}
.item:nth-of-type(2) {
flex-grow: 0.2;
}
.item:nth-of-type(3) {
flex-grow: 0.3;
}
.item:nth-of-type(4) {
flex-grow: 0.4;
}
.item:nth-of-type(5) {
flex-grow: 0.5;
}
此时的效果为
可以看出 Flex 项目是占满容器的,它的计算方式其实和 flex-grow 为正整数时一样
Flex项目弹性量 = (Flex容器剩余空间/所有flex-grow总和)*当前Flex项目的flex-grow
所以我们可以得出一个结论: Flex 项目的 flex-grow 之和小于 1,Flex 项目不会占满 Flex 容器
flex-shrink 其实和 flex-grow 基本一样,就是扩展变成了收缩,flex-grow 是项目比例增加容器剩余空间,而 flex-shrink 则是比例减去容器不足空间
修改一下我们的例子:
.item {
flex-basis: 200px;
/* 相当于 */
flex-shrink: 1;
flex-grow: 0;
flex-basis: 200px;
}
此时项目的总宽度200*5=1000px已经大于容器总宽度800px,此时计算第一个项目的不足空间就是800-200*5=-200px,第二个项目的不足空间则是800-第一个项目实际宽度-200*4,依次类推
最终计算公式其实和 flex-grow 计算差不多
Flex项目弹性量 = (Flex容器不足空间/所有flex-shrink总和)*当前Flex项目的flex-shrink
只不过,所以上面例子每个项目可以计算出实际宽度为
第一个 Flex 项目: 200+((800-200x5)/5)*1 = 160px
第二个 Flex 项目: 200+((800-160-200x4)/4)*1 = 160px
第三个 Flex 项目: 200+((800-160-160-200x3)/3)*1 = 160px
第四个 Flex 项目: 200+((800-160-160-160-200x2)/2)*1 = 160px
第五个 Flex 项目: 200+((800-160-160-160-160-200x1)/1)*1 = 160px
如果 Flex 项目的min-content大于flex-basis,那么最终的实际宽度将会取该项目的min-content,比如改一下例子,将第一个 Flex 项目改成长单词
<div class="container">
<div class="item">XiaoyueXiaoyue</div>
<div class="item">June</div>
<div class="item">Alice</div>
<div class="item">Youhu</div>
<div class="item">Liehu</div>
</div>
可以看出浏览器最终采用的是第一个 Flex 项目的min-content作为实际宽度,相应的后面 Flex 项目的宽度会等前一个 Flex 项目计算完毕后在进行计算
比如第二个 Flex 项目宽度= 200+((800-228.75-200x4)/4)*1 = 142.81px
同样的 flex-shrink 也会出现小数的情况,也分为 Flex 项目的 flex-shrink 之和小于等于 1 和大于 1 两种情况,如果大于 1 和上面的计算方式一样,所以我们只看小于 1 的情况,将我们的例子改为
.item {
flex-basis: 200px;
flex-shrink: 0.1;
}
效果为
此时我们会发现 Flex 项目溢出了容器,所以我们便可以得出一个结论:Flex 项目的 flex-shrink 之和小于 1,Flex 项目会溢出 Flex 容器
下面看一下它的计算公式
Flex项目弹性量=Flex容器不足空间*当前Flex项目的flex-shrink
Flex项目实际宽度=flex-basis + Flex项目弹性量
比如上面例子的每个 Flex 项目计算结果为
第一个 Flex 项目宽度 = 200+(800-200x5)x0.1=180px,但是由于它本身的min-content为 228.75,所以最终宽度为 228.75
第二个 Flex 项目宽度 =200-(800-228.75-200x4)x0.1=117.125
第三个 Flex 项目宽度...
Flex 中关于对齐方式的属性有很多,其主要分为两种,一是主轴对齐方式:justify-*,二是交叉轴对齐方式:align-*
首先改一下我们的例子,将容器设置为宽高为 500x400 的容器(部分属性省略)
<div class="container">
<div class="item">A</div>
<div class="item">B</div>
<div class="item">C</div>
</div>
.container {
display: flex;
width: 500px;
height: 400px;
}
.item {
width: 100px;
height: 40px;
}
这里以横向为主轴,纵向为交叉轴
justify-content的值可以为:
align-content 属性控制整个 Flex 项目在 Flex 容器中交叉轴的对齐方式
**注意设置 align-content 属性时候必须将 flex-wrap 设置成 wrap 或者 wrap-reverse。**它可以取得值为
比如将 Flex 元素宽度去掉
.item {
width: 100px;
}
此时我们改下例子中 Flex 项目的宽度使其换行,因为如果 Flex 项目只有一行,那么 space-between 与 flex-start 表现一致
.item {
width: 300px;
}
align-items 属性定义 flex 子项在 flex 容器的当前行的交叉轴方向上的对齐方式。它与 align-content 有相似的地方,它的取值有
stretch 默认值,当我们 Flex 元素不设置高度的时候,默认是拉伸的
center 元素位于容器的中心,每个当前行在图中已经框起来
flex-start 位于容器开头
flex-end 位于容器结尾
baseline 位于容器的基线上
比如给 A 项目一个 padding-top
.item:nth-of-type(1) {
padding-top: 50px;
}
没设置 baseline 的表现
设置 baseline 之后
通过上面的例子我们可以发现,如果想要整个 Flex 项目垂直对齐,在只有一行的情况下,align-items 和 align-content 设置为 center 都可以做到,但是如果出现多行的情况下 align-items 就不再适用了
上面都是给 Flex 容器设置的属性,但是如果想要控制单个 Flex 项目的对齐方式该怎么办呢?
其实 Flex 布局中已经考虑到了这个问题,于是就有个 align-self 属性来控制单个 Flex 项目在 Flex 容器侧交叉轴的对齐方式。
align-self 和 align-items 属性值几乎是一致的,比如我们将整个 Flex 项目设置为 center,第二个 Flex 项目设置为 flex-start
.container {
display: flex;
width: 500px;
height: 400px;
align-items: center;
}
.item {
width: 100px;
height: 40px;
}
.item:nth-of-type(2) {
align-self: flex-start;
}
注意,除了以上提到的属性的属性值,还可以设置为 CSS 的关键词如 inherit 、initial 等
place-content 为 justify-content 和 align-content 的简写形式,可以取一个值和两个值,如果设置一个值那么 justify-content 和 align-content 都为这个值,如果是两个值,第一个值为 align-content,第二个则是 justify-content
到这里关于Flex布局基本已经介绍完了,肯定会有些细枝末节没有考虑到,这可能就需要我们在平时工作和学习中去发现了
点个赞吧~
我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123
当我的预订模型通过rake任务在状态机上转换时,我试图找出如何跳过对ActiveRecord对象的特定实例的验证。我想在reservation.close时跳过所有验证!叫做。希望调用reservation.close!(:validate=>false)之类的东西。仅供引用,我们正在使用https://github.com/pluginaweek/state_machine用于状态机。这是我的预订模型的示例。classReservation["requested","negotiating","approved"])}state_machine:initial=>'requested
我有这个html标记:我想得到这个:我如何使用Nokogiri做到这一点? 最佳答案 require'nokogiri'doc=Nokogiri::HTML('')您可以通过xpath删除所有属性:doc.xpath('//@*').remove或者,如果您需要做一些更复杂的事情,有时使用以下方法遍历所有元素会更容易:doc.traversedo|node|node.keys.eachdo|attribute|node.deleteattributeendend 关于ruby-Nokog
我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c
是否可以为特定(或所有)项目使用多个布局?例如,我有几个项目,我想对其应用两种不同的布局。一个是绿色的,一个是蓝色的(但是)。我想将它们编译到我的输出目录中的两个不同文件夹中(例如v1和v2)。我一直在玩弄规则和编译block,但我不知道这是怎么回事。因为,每个项目在编译过程中只编译一次,我不能告诉nanoc第一次用layout1编译,第二次用layout2编译。我试过这样的东西,但它导致输出文件损坏。compile'*'doifitem.binary?#don’tfilterbinaryitemselsefilter:erblayout'layout1'layout'layout2'
我们有一个字符串:“”这个正则表达式://i如何从当前字符串中获取所有匹配项? 最佳答案 "".scan(//)参见scan在ruby-docs上 关于ruby-如何遍历Ruby中所有正则表达式匹配的字符串?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/6857852/
是否可以在所有delayed_job任务之前运行一个方法?基本上,我们试图确保每个运行delayed_job的服务器都有我们代码的最新实例,所以我们想运行一个方法来在每个作业运行之前检查它。(我们已经有了“check”方法并在别处使用它。问题只是关于如何从delayed_job中调用它。) 最佳答案 现在有一种官方方法可以通过插件来做到这一点。这篇博文通过示例清楚地描述了如何执行此操作http://www.salsify.com/blog/delayed-jobs-callbacks-and-hooks-in-rails(本文中描述
我们如何捕获或/和处理ruby中所有未处理的异常?例如,这样做的动机可能是将某种异常记录到不同的文件或发送电子邮件给系统管理。在Java中我们会做Thread.setDefaultUncaughtExceptionHandler(UncaughtExceptionHandlerex);在Node.js中process.on('uncaughtException',function(error){/*code*/});在PHP中register_shutdown_function('errorHandler');functionerrorHandler(){$error=error_
我有一个随机大小的散列,它可能有类似"100"的值,我想将其转换为整数。我知道我可以使用value.to_iifvalue.to_i.to_s==value来做到这一点,但我不确定我将如何在我的散列中递归地做到这一点,考虑到一个值可以是一个字符串,或一个数组(哈希或字符串),或另一个哈希。 最佳答案 这是一个非常简单的递归实现(尽管必须同时处理数组和散列会增加一些技巧)。deffixnumifyobjifobj.respond_to?:to_i#IfwecancastittoaFixnum,doit.obj.to_ielsifobj
我希望访问我机器上的所有HTTP流量(我的Windows机器-不是服务器)。据我了解,拥有一个本地代理是所有流量路线的必经之路。我一直在谷歌搜索但未能找到任何资源(关于Ruby)来帮助我。非常感谢任何提示或链接。 最佳答案 WEBrick中有一个HTTP代理(Rubystdlib的一部分)和here's一个实现示例。如果你喜欢生活在边缘,还有em-proxy伊利亚·格里戈里克。这postIlya暗示它似乎确实需要一些调整来解决您的问题。 关于ruby-如何捕获所有HTTP流量(本地代理)