Go to comments

Souffle css3 弹性盒

传统的布局一般使用 display、float、position 实现的,但有局限性,

比如“垂直水平的居中”就不好实现,用定位 position 实现还要设置其他属性配合,所以在 2009 年 css3 提出 flex 弹性盒的布局方案


一、设置弹性盒模型

定义主轴方向

flex-direction: row(默认) | row-reverse | column | column-reverse


溢出换行

flex-wrap: nowrap(默认)| wrap | wrap-reverse

当设置 flex-grow 属性的时候

1. wrap 换行失效,会尽可能按 flex-basis 的值往大了去从而达到折行的目的,根据弹性项目的实际宽度判断是否换行

2. flex-shrink 也会失效


以 align 开头的都是设置侧轴的对齐方式,当容器侧轴还有剩余空间的时候,设置在侧轴的对齐方式

align-content:center 居中对齐,如果只有一行项目不会生效,因为它设置的是整体

align-items:center    单行居中对齐


flex 布局是一个弹性盒子,它让容器里面的所有的子元素有了伸缩的特性

1. 在父元素上设置弹性盒子 display: flex,父元素叫容器

2. 子元素有伸缩性,叫弹性项目

<style>
  .wrapper{
    width: 500px;
    height: 500px;
    background-color: cornsilk;
    display: flex; /* 在父元素上设置弹性布局 */
  }
  .box{
    width: 200px; /* 每个项目宽200,4*200超出了容器宽度 */
    height: 100px;
    background-color: bisque;
  }
  .box:nth-child(2n){
    background-color: burlywood;
  }
  .item1{
    height: 200px;
  }
  .item2{
    background-color: saddlebrown;
  }
  .item3{
    height: 400px;
  }
  .item4{
    height: 600px;
  }
</style>

<div class="wrapper">
  <div class="box item1">box1</div>
  <div class="box item2">box2</div>
  <div class="box item3">box3</div>
  <div class="box item4">box4</div>
</div>

弹性项目默认横向排列,

如果项目的 width 宽之合超出容器的宽度,会按一定比例自动压缩,

弹性项目的高度没有伸缩变化,如果高度超出了容器也不会压缩

box1box2box3box4




二、弹性项目的对齐方式

flex 布局有两个轴主轴和轴,对齐方式就分成两类

1. 主轴上的对齐方式

2. 侧轴上的对齐方式


1、主轴上的对齐方式

justify-content 属性设置在容器上,定义弹性项目在主轴上的对齐方式,单行多行都可以使用

属性值说明
flex-start左对齐(默认),容器起始位置
flex-end右对齐,容器结束位置
center居中
space-between左右两边对齐,并且项目之间的间隔相等
space-around每个项目两侧的间隔相等,所以项目之间的间隔,比项目与边框的间隔大一倍
space-evenly项目之间的间隔与容器与项目之间的空隙是一样的

space-evenly 对齐

<style>
  .wrapper{
    width: 500px;
    height: 500px;
    border:1px solid #ccc;
    display: flex;
    justify-content: space-evenly; /* 项目之间的间隔与容器与项目之间的空隙一样 */
  }
  .box{
    height:100px;
    width: 100px;
    background-color: bisque;
  }
  .box:nth-child(2n){
    background-color: burlywood;
  }
</style>

<div class="wrapper">
  <div class="box item1">box1</div>
  <div class="box item2">box2</div>
  <div class="box item3">box3</div>
  <div class="box item4">box4</div>
</div>

项目之间的间隔与容器与项目之间的空隙一样 

box1box2box3box4


如果主轴设置为垂直方向,间隔就变成上下

<style>
  .wrapper{
    width: 500px;
    height: 500px;
    border:1px solid #ccc;
    display: flex;
    flex-direction: column; /* 设置主轴为垂直方向 */
    justify-content: space-evenly;
  }
  .box{
    height:100px;
    width: 100px;
    background-color: bisque;
  }
  .box:nth-child(2n){
    background-color: burlywood;
  }
</style>

<div class="wrapper">
  <div class="box item1">box1</div>
  <div class="box item2">box2</div>
  <div class="box item3">box3</div>
  <div class="box item4">box4</div>
</div>

主轴垂直,间隔垂直方向

box1box2box3box4


2、侧轴方向的对齐方式

align-items 属性设置沿测轴方向上的对齐方式,该属性也设置在容器上(单行对齐方式)

属性值说明
flex-start交叉轴的起点位置对齐,就是容器顶部
flex-end交叉轴的终点位置对齐,就是容器底部
center交叉轴中心对齐,容器中间
baseline弹性项目第一行文字基线对齐,基线是小写字母 x 的底部
stretch(默认)如果弹性项目没有设置高度或为auto的时候有效,项目高度将占满整个容器高度


基线对齐

第一个元素设置 padding,

第二个元素里面有 p 元素,p 元素有默认 margin,

弹性盒子的顶部不是对齐的,但是盒子里面的文字都是对齐的,因为设置了 baseline 基线对齐

<style>
  .wrapper{
    width: 500px;
    height: 500px;
    border:1px solid #ccc;
    display: flex;
    justify-content: space-between;
    align-items: baseline; /* 侧轴基线对齐 */
  }
  .box{
    height:100px;
    width: 100px;
    background-color: bisque;
  }
  .box:nth-child(2n){
    background-color: burlywood;
  }
  .item1{
    padding-top: 20px; /* 往下移动 */
  }
</style>
</head> 
<body>

<div class="wrapper">
  <div class="box item1">box1</div>
  <div class="box item2">
    <p>box2</p>
  </div>
  <div class="box item3">box3</div>
  <div class="box item4">box4</div>
</div>

基线指的是只要有文字,基线是小写字母 x 的底部,

如果项目里面没有文字,基线是盒子的底边

box1box2box3box4


stretch 字面是伸展延伸的意思,

1. 如果弹性项目不设置高度,侧轴的对齐方式的不是 stretch,默认高度是被内容撑开的

2. 如果弹性项目设置高度轴设置 stretch 没有效果

3. 只有在弹性项目没有设置高度或高度为 auto 的时候,轴设置 stretch 对齐有效,高度将占满整个容器高度

<style>
  .wrapper{
    width: 500px;
    height: 500px;
    border:1px solid #ccc;
    display: flex;
    justify-content: space-between;
    align-items: stretch; /* 默认的对齐方式 */
  }
  .box{
    /* height:100px; */
    width: 100px;
    background-color: bisque;
  }
  .box:nth-child(2n){
    background-color: burlywood;
  }
</style>
</head> 
<body>

<div class="wrapper">
  <div class="box">box1</div>
  <div class="box">box2</div>
  <div class="box">box3</div>
  <div class="box">box4</div>
</div>

项目不设置高度,stretch 默认占满整个容器高度

box1box2box3box4


flex-self 和 align-item 都是设置侧轴对齐的方式

1. flex-self 和 align-item属性值是一样的

2. align-item 设置在容器上,表示设置的是所有的弹性项目

3. flex-self 单独设置在某一个项目上的

4. flex-self 的权重高于 agin-item


flex-self: center 设置居中对齐项目 .item1

<style>
  .wrapper{
    width: 500px;
    height: 500px;
    border:1px solid #ccc;
    display: flex;
    justify-content: space-between;
    align-items: stretch;
  }
  .box{
    /* height:100px; */
    width: 100px;
    background-color: bisque;
  }
  .box:nth-child(2n){
    background-color: burlywood;
  }
  .item1{
    align-self: center; /* 权重高于agin-item */
  }
</style>

<div class="wrapper">
  <div class="box item1">box1</div>
  <div class="box item2">box2</div>
  <div class="box item3">box3</div>
  <div class="box item4">box4</div>
</div>

box1 元素居中对齐

box1box2box3box4


align-content 属性定义了多根主轴线在测轴的对齐方式,如果项目只有一根主轴,该属性不起作用

属性值说明
flex-start与交叉轴起点对齐,整体在容器的顶端
flex-end与交叉轴终点对齐,在容器的下面
center与交叉轴中心点对齐
space-between交叉轴两端对齐,轴与轴之间平均分布剩余空间
space-around每根轴线两侧的间隔相等
space-evenly平均分配剩余空间
stretch(默认值)如果不设置高,高度占满整个交叉轴



容器宽度 300 像素,设置 flex-wrap: wrap 表示换行,弹性项目超出容器尺寸不进行压缩,

1. 换行后有两个主轴,两个主轴平分容器,第二条主轴在容器的中间,

2. 每条主轴默认都是从左到右,从上到下排列

<style>
  .wrapper{
    width: 300px;
    height: 500px;
    border:1px solid #ccc;
    display: flex;
    flex-wrap: wrap; /* 换行 */
  }
  .box{
    height:100px;
    width: 100px;
    background-color: bisque;
  }
  .box:nth-child(2n){
    background-color: burlywood;
  }
</style>
</head> 
<body>

<div class="wrapper">
  <div class="box item1">box1</div>
  <div class="box item2">box2</div>
  <div class="box item3">box3</div>
  <div class="box item4">box4</div>
  <div class="box item5">box5</div>
</div>

换行后两个主轴平分容器

box1box2box3box4box5


设置 align-content: center 多行项目整体居中

<style>
  .wrapper{
    width: 300px;
    height: 500px;
    border:1px solid #ccc;
    display: flex;
    flex-wrap: wrap;
    align-content:center; /* 多行居中对齐 */
  }
  .box{
    height:100px;
    width: 100px;
    background-color: bisque;
  }
  .box:nth-child(2n){
    background-color: burlywood;
  }
</style>
</head> 
<body>

<div class="wrapper">
  <div class="box item1">box1</div>
  <div class="box item2">box2</div>
  <div class="box item3">box3</div>
  <div class="box item4">box4</div>
  <div class="box item5">box5</div>
</div>

换行后多行居中对齐

box1box2box3box4box5


align-items 和 align-content

1. 只要 align 开头的属性都是设置侧轴的

2. align-content 把多行看做一个整体在交叉轴对齐的方式(align-content 属性和 justity-content 属性的值是类似的)

3. align-item 每一行项目在交叉轴对齐的方式


三、弹性项目的伸缩变化

flex-grow 放大比例,按比例分配剩余空间,也就是放大比例,默认值 0

flex-shrink 缩小比例,压缩比例,默认值 1 表示按照 1:1:1 比例伸缩变换

flex-basis  伸缩基准值

order 排列顺序,默认值是0

align-self 单个项目的对齐方式

flex 复合属性由 flex-grow, flex-shrink, flex-basis 三个子属性组成


flex-shrink  属性设置的是,如果项目尺寸超出容器,按什么比例压缩,默认值是 1


弹性项目的宽度合 1100,大于父元素宽度,多出了 600 像素

500 + 200 + 200 + 200 = 1100

1100 - 500 = 600

<style>
  .wrapper{
    width: 500px;
    height: 500px;
    background-color: cornsilk;
    display: flex;
  }
  .box{
    width: 200px;
    height: 100px;
    background-color: bisque;
  }
  .box:nth-child(2n){
    background-color: burlywood;
  }
  .item1{
    width: 500px; /* 第一个盒子宽度500 */
  }
</style>

<div class="wrapper">
  <div class="box item1">box1</div>
  <div class="box item2">box2</div>
  <div class="box item3">box3</div>
  <div class="box item4">box4</div>
</div>

项目自动缩减尺寸,根据 flex-shrink 默认值 1 进行压缩

box1box2box3box4


压缩的计算公式 

(flex-shrink * width1) / (flex-shrink * width1 + flex-shrink * width2 + flex-shrink * width3  + flex-shrink * width4) * moreWidth


计算第一个盒子 .demo1 的缩减后的尺寸,

1. 计算缩减的比例

    (1 * 500) / (1 * 500 + 1 * 200 + 1 * 200 + 1 * 200) = 0.45454545454545453

2. 计算需要缩减的尺寸,

    缩减比例乘以超出的尺寸 600

    0.45454545454545453 * 600 = 272.7272727272727

3. 最后得出 .dome1 缩减后的尺寸,用第一个元素宽度 500 减掉 272.7272727272727

    500 - 272.7272727272727 = 227.272727272728


注意这样的问题

如果只有第一个子元素 .item1 进行缩减 flex-shrink:1

其他子元素不进行缩减 flex-shrink: 0,

其它三个子项目的宽度还是超出父元素的宽度,会出现问题


flex-grow 表示按比例分配容器剩余部分,默认值为 0 表示不分配


每个盒子宽度 100px,容器出现剩余的空间,

设置第一个元素 flex-grow:1 表示按比例吃掉容器的剩余部分,第一个元素变成 200 像素

<style>
  .wrapper{
    width: 500px;
    height: 500px;
    background-color: cornsilk;
    display: flex;
  }
  .box{
    width: 100px;
    height: 100px;
    background-color: bisque;
  }
  .box:nth-child(2n){
    background-color: burlywood;
  }
  .item1{
    flex-grow:1; /* 吃掉剩余部分 */
  }
</style>

<div class="wrapper">
  <div class="box item1">box1</div>
  <div class="box item2">box2</div>
  <div class="box item3">box3</div>
  <div class="box item4">box4</div>
</div>

.box1 吃的剩余部分

box1box2box3box4


主轴和侧轴

主轴,弹性项目默认在水平方向,从左到右排列,这种默认的排列方式我们叫主轴,弹性项目沿着主轴进行压缩或扩展

轴,与主轴垂直的轴叫侧轴(也可以叫交叉轴)


flex-direction: column  在容器上设置主轴为垂直排列

<style>
  .wrapper{
    width: 500px;
    height: 500px;
    background-color: cornsilk;
    display: flex;
    flex-direction: column; /* 主轴纵向排列 */
  }
  .box{
    width: 200px;
    height: 100px;
    background-color: bisque;
  }
  .box:nth-child(2n){
    background-color: burlywood;
  }
  .item1{
    height: 200px;
  }
  .item3{
    height: 400px;
  }
  .item4{
    height: 600px;
  }
</style>

<div class="wrapper">
  <div class="box item1">box1</div>
  <div class="box item2">box2</div>
  <div class="box item3">box3</div>
  <div class="box item4">box4</div>
</div>

设置纵向排列后,变成了对高度 height 的压缩或扩展

box1box2box3box4


flex-basis 表示沿着主轴方向的“伸缩的基准值”,因为主轴的方向是可以变化的

1. 当主轴水平方向时,基准值相当于 width 宽度

2. 当主轴垂直方向时,基准值相当于 height 高度

3. flex-basis 的优先级高于 width/height,并按照基准值进行伸缩变化


给所有的盒子设置基准值 flex-basis: 200px

设置基准值后 width 就失效了,按照基准值的宽度压缩盒子

<style>
  .wrapper{
    width: 500px;
    height: 500px;
    background-color: cornsilk;
    display: flex;
  }
  .box{
    flex-basis: 200px; /* 设置基准值,每个盒子宽度200像素 */
    height: 100px;
    background-color: bisque;
  }
  .box:nth-child(2n){
    background-color: burlywood;
  }
  .item1{
    width:100px;
    flex-shrink: 1; /* 压缩 */
  }
  .item2{
    width:300px;
    flex-shrink: 1; /* 压缩 */
  }
  .item3{
    width: 400px;
    flex-shrink: 1; /* 压缩 */
  }
  .item4{
    width: 600px;
    flex-shrink: 1; /* 压缩 */
  }
</style>

<div class="wrapper">
  <div class="box item1">box1</div>
  <div class="box item2">box2</div>
  <div class="box item3">box3</div>
  <div class="box item4">box4</div>
</div>


计算压缩尺寸

1. 缩减比例 (200 * 1) / (200*1 + 200*1 + 200*1 + 200*1) = 0.25

2. 超出的尺寸 (4 * 200) - 500 = 300

3. 项目要减去的尺寸 300 * 0.25 = 75

4. 最后 200 - 75 = 125


flex: flex-grow flex-shrink flex-basis

该复合属性,由三个子属性复合而成,上面的效果可以简写为 flex: 0 1 200px


flex 复合属性

设置一个值代表 flex-grow

设置二个值分别代表 flex-grow 和 flex-shrink

设置二个值分别代表 flex-grow flex-shrink flex-basis


order  设置元素的顺序,默认从左到右,默认值 0

.wrapper{
  width: 500px;
  height: 500px;
  background-color: cornsilk;
  display: flex;
}
.box{
  height: 100px;
  background-color: bisque;
}
.box:nth-child(2n){
  background-color: burlywood;
}
.item1{
  flex: 0 1 200px;
  order: 2; /* 第四 */
}
.item2{
  flex: 0 1 200px;
  order: 1; /* 第三 */
}
.item3{
  flex: 0 1 200px;
  order: 0; /* 第二 */
}
.item4{
  flex: 0 1 200px;
  order: -1; /* 第一*/
}



align-self  设置单个项目在侧轴方向(交叉轴)的对齐方式

center 居中

flex-start 测轴方向的起始位置

flex-end 测轴方向的终止位置

baseline

stretch


因为主轴是可以变换的

如果主轴是水平排列,align-self 代表垂直方向的排列

如果主轴是垂直排列,align-self 代表水平方向的排列



Leave a comment 0 Comments.

Leave a Reply

换一张