[TOC]
flex布局
虽然用了很久的flex,但是关于这东西的一些属性确实一知半解,只是知道有这种效果,但是不知道为啥会出现这种情况,所以找了一些资料总结.
Flex是Flexible Box的缩写,意为”弹性布局”,用来为盒状模型提供最大的灵活性。其实说白了就是他会根据自己的宽度去自动调整里面子元素的宽度,即使里面子元素已经设置了宽度;从而达到一种类似于自适应的感觉(虽然实际上并不是自适应)
flex的几个常用属性
布局的传统解决方案,基于盒状模型,依赖 display属性 + position属性 + float属性。它对于那些特殊布局非常不方便,比如,垂直居中就不容易实现。不管是position或者float都会造成本身脱离文档流,直接导致父元素没高度,所以还需要额外的代码进行修正
flex轴线和正负自由空间
采用Flex布局的元素,称为Flex容器(flex container),简称”容器”。它的所有子元素自动成为容器成员,称为Flex项目(flex item),简称”项目”。说白了就是在谁身上写了display:flex谁就是flex容器
容器默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis)。主轴的开始位置(与边框的交叉点)叫做main start,结束位置叫做main end;交叉轴的开始位置叫做cross start,结束位置叫做cross end。(说简单点就是默认X轴为主轴,Y为交叉轴)
flex-directio: row(默认值):主轴为水平方向,起点在左端。
row-reverse:主轴为水平方向,起点在右端。
column:主轴为垂直方向,起点在上沿。
column-reverse:主轴为垂直方向,起点在下沿
这个属性不写就是默认X轴线为主轴,如果设定column,那么就是竖着排,其他两个用的不多,这两个东西会决定positive and negative free space(正负自由空间)的计算方式!!!∑(゚Д゚ノ)ノ...这什么鬼?说的这么邪乎,其实就是当主轴为row,里面的子元素的宽加起来不超过父元素的宽,也就是有剩的,那么这部分剩下的空间就是叫做positive free space
反之就是negative free space;也就是超出的那部分宽度;
当主轴为Y轴,那么计算正负自由空间就是元素的高了;这个所谓的正负自由空间也会影响到下面子元素的两个缩放属性flex-grow和flex-shrink
flex-grow
flex-grow 属性指定了flex增长值, 这决定了当positive free space分配时,flex子元素相对于flex容器中的其余flex子元素的增长程度.举个生活场景就是老爹给自己几个儿子留了一笔遗产,这几个儿子该如何根据比例去分配;
假定下面这个外层包裹为600px;a,b均为100,hello为150,那么可分配空间=600-100-100-150=250px;
现在加上样式
a{
flex-grow:1
}
b{
flex-grow:1
}
b{
flex-grow:2
}
现在按照1:1:2的比例去分配250,就得到了每份62.5px,那么就会变成(图有些不准)
当flex-directio:column 也就是主轴设置Y轴之后,那么正自由空间就会以元素的高为基准
flex-sharink
flex-shrink决定了flex-item的缩放值,跟他相关的就是上面提到的另一个属性,负自由空间,即里面的子元素的宽之和加起来大于父元素的宽,那么超出去的部分就叫做negative free space(负自由空间);
负自由空间和正自由空间相似,只不过变成了负值而已,假定父元素600px,底下3个子元素,100,100,500,负自由空间=600-(100+100+500)=-100;
现在3个子元素的flex-shrink为1,1,2,也就说按照1:1:2的比例分配-100px;
应该得到实际计算宽度:
第一个:(100-100*(2/2+1+2))=60,
第二个(100-100*(1/2+1+2))=80px,
第三个(500-100*(2/2+1+2))=460px;
最后:60+80+460=600px;
骚年,你以为上面的是正确的吗?如果你信了那就是图样图森破ヾ(◍°∇°◍)ノ゙...一开始我也是这样计算的,但是跟浏览器的计算相差了很远,折腾了好久才找到正确的计算方式;
他的计算方式还有些复杂:
先求负空间:600-(100+100+500)=-100
然后自身flex-shrink乘以自身宽度得到消化值:
`a:100*2=200;
b:100*1=100;
c:500*2=1000;`
再求消化值之和:200+100+1000=1300;
第三步:计算自身腾出宽度a:(200/1300)*100=15.38; b:(100/1300)*1=7.69; c:(1000/1300)*100=76.92;
...(▼ヘ▼#)
第四步:计算最后宽度:a:100-15.38=84.62; b:100-7.69=92.31; c:500-76.92=423.08
**所以可以得到一些个结论:
1, 在flex可能会去改变容器里面元素原本设置的绝对宽度,即便你写死了宽度,尤其是在设置了flex-grow和flex-sharink的情况下,他会根据这些比例值去动态计算子元素的宽度
2, 有正自由空间时,flex-grow生效,shrink不生效
3, 有负自由空间时,flex-shrink生效,grow不生效
4, flex-basis在一定程度上等于width;
**
flex-basis
和width一样,他的默认值为auto,把上面几个例子换成width也是一样的。当然工作中最好用flex-basis,更符合规范。
所以在使用flex时候有时候得到了意料之外的宽度时候,明明我写了宽度的啊?ヽ( ̄▽ ̄)ノ.也就知道为啥会得到这个值了...
单个元素靠右
方法1
flex: 1;
text-align: right;
方法二
margin-left:auto;
swiper滑动插件
swiper滑动插件,一款专为手机滑动设计的插件,挺不错的;在做起点官网品牌营销的时候遇到3个地方需要使用,也是相当具有代表性的使用场景(注意这里swiper3和swiper4版本的不同,这里使用的3,4的参数差不多类似,可以看文档);
第一个场景:
在一个页面下可能存在多个swiper区域,所以为了保证唯一性,在实例化的时候传入id是一个机智的选择
这种场景难点在于滑动下面的图片,上面的按钮要跟着切换class,同时,点击上面的按钮下面的图片要跟着切换
做法解析:在滑动结束之后获取当期元素序号,在根据序号匹配上面的按钮;
在swiper实例化的时候可以传入一个对象作为参数,其中有一个回调函数参数onSlideChangeEnd(还有其他的函数,都是一些事件触发),接受当前swiper对象为参数,在滑动结束之后触发,还有一个属性值activeIndex,为当前激活元素的序号,使用这个序号就可以和上面的切换按钮对应起来了;
结构以及代码部分:
var skillSwiper = new Swiper('.skill-model-swiper', { //实例化滑动对象
pagination : '.swiper-pagination-skill', //分页指示器
onSlideChangeEnd: function(swiper) { //滑动结束获取当前激活序号,swiper为当前的swiper对象
var curidx = swiper.activeIndex; //activeIndex关键属性,当前激活元素的序号
$('.skill-lenli-btn button').eq(curidx).addClass('skill-lenli-btn-act').parent().siblings().find('button').removeClass('skill-lenli-btn-act');
}
});
第二个场景
这种场景难点在于在一个大div下面嵌套了多个swiper区域,切伴随tab标签页切换效果,跟随上面的切换按钮切换,其实做出来还是比较简单,但是会有一个意料之外的情况,Σ(っ°Д°;)っ除了第一个swiper之外的剩下的swiper都会存在滑动卡顿的情况
解决办法:
在实例化每一个swiper的时候在加上observer: true, //修改swiper自己或子元素时,自动初始化swiper
observeParents: true, //修改swiper的父元素时,自动初始化swiper
这2个附加参数就可以解决
结构以及代码
$('.ds-sw>div').click(function(event) {
var i = $(this).index();
$(this).addClass('ds-sw-act').siblings().removeClass('ds-sw-act');
$('.ds-person-item').eq(i).addClass('ds-person-item-act').siblings().removeClass('ds-person-item-act')
});
var dsItemSwiperA = new Swiper('.ds-person-swiper-a', {
observer: true, //修改swiper自己或子元素时,自动初始化swiper
observeParents: true, //修改swiper的父元素时,自动初始化swiper
pagination : '.dsItemSwiperASw'
})//下面每一个swiper都一样的写法,再来个B,C,D
第三个场景
这种场景是一种不规则应用场景,需要在一个元素上漏出上一个和下一个,其实也很简单,只需要记得给每一个swiper-slider给上固定宽度就好了,然后在实例化就好了
结构
var dnrSwiper=new Swiper('.swiper-container-dinner',{
slidesPerView: 'auto',
centeredSlides: true,
spaceBetween: 10,
autoplay : 3000,
})
一些其他
里面内容过多或者用了自定义的分页器很有可能出现滑动问题,建议延迟300ms初始化
注意,swiper3和swiper3是有些不一样,swiper3和4都没有鼠标移入停止自动播放和离开继续播放的选项,只能手动写入,代码后面补上
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。