学习完移动web开发的flex布局,给自己做下小结。
传统布局和flex布局对比
1.传统布局:
- 兼容性好
- 布局繁琐
- 局限性,不能再移动端很好的布局
2.flex布局:
- 操作方便,布局极其简单,移动端使用比较广泛
- pc端浏览器支持情况比较差
- IE11或更低版本不支持flex或仅支持部分
建议如果是开发移动端,或者不考虑兼容的pc端就可以使用flex布局哟。
flex布局原理
- flex 是 flexible Box 的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性,任何一个容器都可以指定为 flex 布局。
- 当我们为父盒子设为 flex 布局以后,子元素的 float、clear 和 vertical-align 属性将失效。
- flex布局又叫伸缩布局 、弹性布局 、伸缩盒布局 、弹性盒布局
- 采用 Flex 布局的元素,称为 Flex 容器(flexcontainer),简称"容器"。它的所有子元素自动成为容器成员,称为 Flex 项目(flexitem),简称"项目"。
所以总的来说flex布局就是通过给父盒子添加flex属性,来控制子盒子的位置和排列方式,这个父盒子可以是任何一个容器元素哟。
给父元素开启flex布局方式就是:
display:flex;
设置了这个属性就开启了哟。
父项常见属性
1.flex-direction:设置主轴的方向。
在flex布局中有主轴和侧轴二个方位,结合数学里的x,y轴。
默认主轴是x轴,侧轴是y轴,但是我们可以通过该属性来改变
主侧轴方向。
在布局里,我们经常就使用y轴为主轴,来让子flex项目垂直排列。
下面图片里是该属性对应的值及其效果:
其中,标红字体属性值较为常用哟~
2.justify-content :设置主轴上的子元素排列方式。
下面图片里是该属性对应的值及其效果:
这个可以让我们来对主轴里的子元素排列顺序方式进行控制,为我们省下了不少功夫哟~
3.flex-wrap:设置是否换行。
该属性的值只有二个:
- nowrap :不换行
- wrap :换行
默认情况下,项目都排在一条线(又称”轴线”)上。flex-wrap属性定义,flex布局中默认是不换行的。
简单的说就是你会发现你在父级元素开启了flex布局后,你创建多少个子项目都会在一行显示,只是里面的子项目的宽度会减小,如果开启换行后,一行放不下后就会在第二行显示。
4.align-items :设置侧轴上的子元素排列方式(单行 )。
该属性是控制子项在侧轴(默认是y轴)上的排列方式 在子项为单项(单行)的时候使用,记住哟,一定要是子项目是单行时哟,因为控制多行子项目时有别的属性来哟。
- flex-start :从头部开始
- flex-end :从尾部开始
- center :居中显示
- stretch :拉伸
我们经常会将 设置主轴为y轴结合设置侧轴的子元素居中显示结合起来,就可以将水平的二个元素变为上下二个元素居中显示啦。
5.align-content 设置侧轴上的子元素的排列方式(多行)。
设置子项在侧轴上的排列方式 并且只能用于子项出现 换行 的情况(多行),这个是对应多行的哟,在单行下是没有效果的。
align-content 和align-items区别:
- align-items 适用于单行情况下, 只有上对齐、下对齐、居中和 拉伸
- align-content适应于换行(多行)的情况下(单行情况下无效), 可以设置 上对齐、下对齐、居中、拉伸以及平均分配剩余空间等属性值。
- 总结就是单行找align-items 多行找 align-content
6.flex-flow 属性是 flex-direction 和 flex-wrap 属性的复合属性。
这个就不用多说啦,就是结合起来啦,示范一个:
flex-flow:row wrap;
x为主轴,换行显示。
flex布局子项常见属性
1.flex 属性:
flex 属性定义子项目分配剩余空间,用flex来表示占多少份数。
这里如果我们给每个子项目设为1,那么就是平分父元素的宽度哟。
.item {
flex: <number>; /* 默认值 0 */
}
2.align-self:控制子项自己在侧轴上的排列方式。
如果我们要让一个子项目有自己的在侧轴排列的方式,就是覆盖掉父元素的align-items 属性,就可以用该属性。
默认值为 auto,表示继承父元素的 align-items 属性,如果没有父元素,则等同于 stretch。
span:nth-child(2) {
/* 设置自己在侧轴上的排列方式 */
align-self: flex-end;
}
3.order 属性定义项目的排列顺序。
这个的属性含义简单来说就是一堆子项目在按正常的顺序排队在,我们要定义的一个子元素在后面,我们想插队了,怎么办,我们就可以用这个属性,数值越小,排列越靠前,默认为0。当然,插队是不对的哟。
注意:和 z-index 不一样z-index是排列元素上下顺序的。
.item {
order: <number>; 还可以取负数哟。
}
携程网移动端首页案例练习
1.先将项目环境搭建好。
然后我们就开始设置初始化。
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<!--视图标签 设置手机端和pc端一比一,不允许用户缩放,最大和最小缩放都是1 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no,maximum-scale=1.0,minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<!-- 引入css初始化文件 -->
<link rel="stylesheet" type="text/css" href="css/normalize.css" />
<!-- 引入首页css样式文件 -->
<link rel="stylesheet" type="text/css" href="css/index.css" />
<title></title>
</head>
<body>
</body>
</html>
给body结合具体需求方案添加默认样式,以及其他一些标签默认样式。
/* 初始化body标签 */
body {
max-width: 540px;
min-width: 320px;
margin: 0 auto;
font: normal 14px/1.5 Tahoma, "Lucida Grande", Verdana, "Microsoft Yahei", STXihei, hei;
color: #000;
background: #fff;
overflow-x: hidden;
-webkit-tap-highlight-color: transparent;
height: 1000px;
}
a {
text-decoration: none;
color: #222;
}
div {
box-sizing: border-box; /* 将div都转换为css3盒子模型 */
}
ul {
margin: 0;
padding: 0; /* 出去ul默认的样式 */
list-style: none;
}
2. 搜索栏部分制作。
html部分:
<div class="search-index">
<div class="search">
<span>搜索:目的地/酒店/景点/航班号</span>
</div>
<a href="#" class="user">
<span>我 的</span>
</a>
</div>
css部分:
/* 搜索栏部分 */
.search-index {
display: flex;
position: fixed;
width: 100%; /* 固定定位的元素要给宽度哟 */
max-width: 540px;
min-width: 320px;
height: 44px;
transform: translateX(-50%);
left: 50%; /* 这里运用到了另一种居中的方法 向左偏移屏幕50%,然后向右偏移自身的50% */
color: #666;
font-size: .94rem;
}
.search {
flex: 1; /* 运用flex布局,左边部分直接划分为剩余的全部空间 */
height: 28px;
line-height: 28px;
background-color: #fff;
border-radius: 15px;
margin: 7px 3px 0 11px;
padding-left: 40px;
position: relative;
}
.search::before {
content: "";
position: absolute;
left: 0;
top: 0;
width: 35px;
height: 100%;
background: url(../images/un_ico.png) no-repeat 15px 7px;
background-size: 21px auto;
}
.user {
display: block;
width: 51px;
height: 44px;
font-size: 12px;
text-align: center;
color: #fff;
}
.user::before {
content: "";
display: block;
width: 22px;
height: 22px;
background: url(../images/un_ico.png) no-repeat 1px -36px;
background-size: 21px auto;
margin: 4px auto 1px;
}
这个部分是要固定定位,我们给最外面的盒子一个宽度是100%,能自适应,但是我们还要给一个最大宽度和最小宽度,不然固定定位元素是相对屏幕来说,会和屏幕一样宽。
我们又发现该盒子没有居中,那么我们就要让居中,这里采用的是让该元素向左浮动50%,在让其向右浮动其自身宽度的一半(transform: translateX(-50%);)就可以实现啦。
在看里面有子元素,我们让父盒子开启flex布局,给右边部分一个固定宽度,然后二个块级元素会是上下二行,左边部分我们直接设置flex:1;
这样就会自动占用剩余的空间啦,然后给其margin值,让其宽度变小,padding值,让其向右移动,给里面的放大镜腾出位置,里面的放大镜是用绝对定位,让其脱离普通文档流。
3.背景图部分。
html部分:
<!-- 背景图 -->
<div class="header-bg">
</div>
css部分:
/* 背景图 */
.header-bg {
width: 100%;
height: 198.72px;
background: url(../images/bg.jpg) no-repeat;
background-size: 100% 100%;
border-radius: 0 0 30px 30px;
}
这个部分没有太多要说的,上面一个模块脱离了普通文档流,我们这个设置个宽和高,插入背景图片就可以自动在上面一个模块的下面了。
4. 局部导航栏 。
先说一点小知识:
我们在flex布局中,将水平的二个元素变为垂直居中的二个元素,就可以采用如上图的方法。
html部分:
<ul class="local-nav">
<li>
<a href="#" title="攻略景点">
<span class="local-nav-icon-icon1"></span>
<span>攻略·景点</span>
</a>
</li>
<li>
<a href="#" title="门票玩乐">
<span class="local-nav-icon-icon2"></span>
<span>门票·玩乐</span>
</a>
</li>
<li>
<a href="#" title="美食林">
<span class="local-nav-icon-icon3"></span>
<span>美食林</span>
</a>
</li>
<li>
<a href="#" title="周边游">
<span class="local-nav-icon-icon4"></span>
<span>周边游</span>
</a>
</li>
<li>
<a href="#" title="一日游">
<span class="local-nav-icon-icon5"></span>
<span>一日游</span>
</a>
</li>
</ul>
css部分:
* 局部导航栏 */
.local-nav {
display: flex;
margin: -35px 12px 10px;
padding: 4px 0 8px;
border-radius: 8px;
box-shadow: 0 2px 6px rgba(0,0,0,.1);
background-color: #fff;
}
.local-nav li {
flex: 1;
}
.local-nav a {
display: flex;
flex-direction: column; /* 这里将内部flex布局主轴变为y,在将侧轴居中对齐 */
align-items: center;
font-size: 12px;
}
.local-nav li [class^="local-nav-icon"] {
width: 40px;
height: 40px;
background: url(../images/home-fivemain.15.png) 0 0 no-repeat;
background-size: 40px auto;
}
.local-nav li .local-nav-icon-icon2 {
background-position: 0 -40px;
}
.local-nav li .local-nav-icon-icon3 {
background-position: 0 -80px;
}
.local-nav li .local-nav-icon-icon4 {
background-position: 0 -120px;
}
.local-nav li .local-nav-icon-icon5 {
background-position: 0 -160px;
}
这里我们开启父盒子flex布局,然后让子项目flex:1;
,一下子就让里面的小li平均划分啦,由于父盒宽度是继承body,所以这些子元素也是自适应的啦。
小li里面是a标签,在a标签里是二个span,我们这里采用上面介绍的方法,让a标签开启flex布局,主轴变为y轴,侧轴对齐方式为居中对齐,这样图标和文字就垂直居中对齐啦。
还有一点要说明的是,这里面的图标都不相同,但他们是精灵图,我们只需要改变精灵图的位置就可以切换背景图效果,不用直接换图片。这里我们是用的一个属性选择器,选择class=‘local-nav-icon’开头的,因为这些子元素都有这个开头,给他们设置公共样式,然后单独给每个子元素设置背景图位置。
5.主导航栏。
html部分:
<!-- 主导航栏 -->
<nav>
<div class="nav-common">
<a href="#" class="nav-items">
<span>酒店</span>
</a>
<a href="#" class="nav-items">
<span>民宿·客栈</span>
</a>
<a href="#" class="nav-items">
<span>机票/火车票+酒店 </span>
</a>
</div>
<div class="nav-common">
<a href="#" class="nav-items">
<span>机票</span>
</a>
<a href="#" class="nav-items">
<span>火车票</span>
</a>
<a href="#" class="nav-items car">
<span>汽车·船票</span>
<span>专车·租车</span>
</a>
</div>
<div class="nav-common">
<a href="#" class="nav-items">
<span>酒店</span>
</a>
<a href="#" class="nav-items">
<span>民宿·客栈</span>
</a>
<a href="#" class="nav-items car">
<span>邮轮游</span>
<span>定制游</span>
</a>
</div>
</nav>
css部分:
/* 主导航栏部分 */
nav {
margin: 0 12px 1px;
border-radius: 8px;
overflow: hidden;
}
.nav-common {
display: flex;
height: 66px;
}
.nav-common:nth-child(2) {
margin: 1px 0;
}
.nav-common a {
color: #fff;
font-size: 14px;
line-height: 66px;
}
/* 第一行 */
.nav-items:nth-child(1) {
flex: 30%;
padding-left: 12px;
border-right: 1px solid #fff;
background: url(../images/grid-nav-items-hotel.png) no-repeat;
background-size: 73px auto;
background-position: right bottom;
background-color: #fa6b53;
}
.nav-items:nth-child(2) {
flex: 23%;
text-align: center;
border-right: 1px solid #fff;
background: url(../images/grid-nav-items-minsu.png) no-repeat;
background-size: 37px auto;
background-position: left bottom;
background-color: #fb8251;
}
.nav-items:nth-child(3) {
flex: 47%;
text-align: center;
background: url(../images/grid-nav-items-jhj.png) no-repeat;
background-size: 86px auto;
background-position: right bottom;
background-color: #ffbd49;
}
/* 第二行及第三行 */
.car {
display: flex;
}
.car span {
flex: 1;
}
.car span:nth-child(1) {
border-right: 1px solid #fff;
}
.nav-common:nth-child(2) .nav-items {
background-color: #4d99ed;
}
.nav-common:nth-child(3) .nav-items {
background-color: #47c88d;
}
这个部分每行背景颜色真实做法是用的背景线性渐变,我的做法错啦,嘿嘿,看看就好了啦,毕竟我是小白啦,练习过程就是认错改错啦。
背景线性渐变语法:
background: linear-gradient(起始方向, 颜色1, 颜色2, ...);
background: -webkit-linear-gradient(left, red , blue);
background: -webkit-linear-gradient(left top, red , blue);
背景渐变必须添加浏览器私有前缀 起始方向可以是: 方位名词 或者 度数 , 如果省略默认就是 top
做这一板块也是用的flex属性,给子元素划分大小,按照具体项目来划分各个子元素的大小,可能还需要在子元素里面在进行划分哟。这里是第二行给的1px的上线外边距,里面子元素是给中间二个给了1px白色的左右边框。
6.图标导航部分。
html部分:
<!-- 图标导航部分 -->
<ul class="subnav-entry">
<li>
<a href="#">
<span class="subnav-entry-icon-icon1"></span>
<span>自由行</span>
</a>
</li>
<li>
<a href="#">
<span class="subnav-entry-icon-icon2"></span>
<span>WiFi电话卡</span>
</a>
</li>
<li>
<a href="#">
<span class="subnav-entry-icon-icon3"></span>
<span>保险·签证</span>
</a>
</li>
<li>
<a href="#">
<span class="subnav-entry-icon-icon4"></span>
<span>换钞·购物</span>
</a>
</li>
<li>
<a href="#">
<span class="subnav-entry-icon-icon5"></span>
<span>当地向导</span>
</a>
</li>
<li>
<a href="#">
<span class="subnav-entry-icon-icon6"></span>
<span>特价机票</span>
</a>
</li>
<li>
<a href="#">
<span class="subnav-entry-icon-icon7"></span>
<span>礼品卡</span>
</a>
</li>
<li>
<a href="#">
<span class="subnav-entry-icon-icon8"></span>
<span>申卡·借钱</span>
</a>
</li>
<li>
<a href="#">
<span class="subnav-entry-icon-icon9"></span>
<span>旅拍</span>
</a>
</li>
<li>
<a href="#">
<span class="subnav-entry-icon-icon10"></span>
<span>更多</span>
</a>
</li>
</ul>
css部分:
/* 图标导航部分 这一部分和上面底部导航栏类似 */
.subnav-entry {
display: flex;
flex-wrap: wrap; /* 让小li换行显示 */
margin: 0 12px 12px;
border-radius: 8px;
overflow: hidden;
}
.subnav-entry li {
flex: 20%; /* 这里让每个小li占百分之20,就可以让10个小li分二行显示 */
}
.subnav-entry a {
display: flex;
flex-direction: column;
align-items: center;
font-size: 12px;
}
.subnav-entry a [class^="subnav-entry-icon"] {
width: 28px;
height: 28px;
background: url(../images/un_ico_subnav2x.png) no-repeat;
background-size: 28px auto;
}
.subnav-entry a .subnav-entry-icon-icon2 {
background-position: 0 -28px ;
}
.subnav-entry a .subnav-entry-icon-icon3 {
background-position: 0 -56px ;
}
.subnav-entry a .subnav-entry-icon-icon4 {
background-position: 0 -84px ;
}
.subnav-entry a .subnav-entry-icon-icon5 {
background-position: 0 -112px ;
}
.subnav-entry a .subnav-entry-icon-icon6 {
background-position: 0 -140px ;
}
.subnav-entry a .subnav-entry-icon-icon7 {
background-position: 0 -168px ;
}
.subnav-entry a .subnav-entry-icon-icon8 {
background-position: 0 -196px ;
}
.subnav-entry a .subnav-entry-icon-icon9 {
background-position: 0 -224px ;
}
.subnav-entry a .subnav-entry-icon-icon10 {
background-position: 0 -252px ;
}
这一部分和上面的导航很相似,这里要说的是让父元素开启换行,然后给每个子元素flex:20%
,就可以让10个小li在二行平分显示,当然这里是计算得来的,十个二行,那么每个宽度就是0.2呀。然后就是垂直居中显示文字和图标也是上面的方法,这里图标的切换也是用的上面的方法,因为这里也是用的精灵图做背景。
7.销售部分。
html部分:
<!-- 销售板块 -->
<div class="sales-box">
<div class="sales-hd">
<h2>热门活动</h2>
<a href="#" class="more">获取更多福利</a>
</div>
<div class="sales-bd">
<div class="row">
<a href="#">
<img src="upload/pic1.jpg" alt="">
</a>
<a href="#">
<img src="upload/pic2.jpg" alt="">
</a>
</div>
<div class="row">
<a href="#">
<img src="upload/pic3.jpg" alt="">
</a>
<a href="#">
<img src="upload/pic4.jpg" alt="">
</a>
</div>
<div class="row">
<a href="#">
<img src="upload/pic5.jpg" alt="">
</a>
<a href="#">
<img src="upload/pic6.jpg" alt="">
</a>
</div>
</div>
</div>
css部分:
/* sales-box */
.sales-box {
border-top: 1px solid #bbb;
background-color: #fff;
margin: 4px;
}
.sales-hd {
position: relative;
height: 44px;
border-bottom: 1px solid #ccc;
}
.sales-hd h2 {
position: relative;
text-indent: -999px;
overflow: hidden;
}
.sales-hd h2::after {
position: absolute;
top: 5px;
left: 8px;
content: "";
width: 79px;
height: 15px;
background: url(../images/hot.png) no-repeat 0 -20px;
background-size: 79px auto;
}
.more {
position: absolute;
right: 5px;
top: 0px;
background: -webkit-linear-gradient(left, #FF506C, #FF6BC6);
border-radius: 15px;
padding: 3px 20px 3px 10px;
color: #fff;
}
.more::after {
content: "";
position: absolute;
top: 9px;
right: 9px;
width: 7px;
height: 7px;
border-top: 2px solid #fff;
border-right: 2px solid #fff;
transform: rotate(45deg);
}
.row {
display: flex;
}
.row a {
flex: 1;
border-bottom: 1px solid #eee;
}
.row a:nth-child(1) {
border-right: 1px solid #eee;
}
.row a img {
width: 100%;
}
这一板块是分为上下二个部分,上面部分是我们给整个大盒子一个上边框,然后给上面部分盒子一个下边框就有了上面二个边框的效果,里面是二个背景图,然后都是绝对定位,定位到二侧,还要说一下,那个右侧图片里面的小三角是用的css3里面的旋转45°,然后设置上和右边框就可以实现啦。
下面部分就更简单啦,每一行是二个图片,然后在父元素上启动flex布局,给每行二个子元素flex为1就可以平分一行的宽度,然后插入图片,记得给每行的子元素设置下边框,然后每行第一个子元素设置右边框即可。
做完这个练习还是获益匪浅,有点熟悉flex布局的用法,对比学习的流式布局更加的简单方便,更加有利于我们进行移动网页的开发。