文章目录
一,Flex初体验
在学Flex布局时,我们应当已经了解了流式布局,及百分比布局。可以参考博客流式布局之京东首页案例进行复习。
兼容性:Flex布局相较于传统布局来说极为简单,但是在PC端兼容性较差,在移动端则可以任意使用。当然,如果PC端不需要考虑兼容性问题,也可以考虑使用Flex布局。
现在我们来对Flex有一个最初的体验:
div中有三个span。
<div>
<span>1</span>
<span>2</span>
<span>3</span>
</div>
如图所示,我们希望给span宽度并做出如下效果,需要先将span利用display设置为行内块元素,再设置浮动。
但此时此刻,如果我们不给子元素加上display:block与设置浮动,而是直接给父元素加上
display: flex;
一样也可以达到这层效果。请记住这行代码,如果想要flex布局,一定要给父元素加上这个属性。
代码如下:
<style>
div {
display: flex;
width: 80%;
height: 200px;
background-color: purple;
}
div span {
height: 150px;
width: 150px;
background-color: pink;
margin-right: 5px;
}
</style>
可见,flex布局相对于传统布局来说非常简单。此外,flex布局的使用也非常灵活,flex全称为flexible,意为灵活的,所以flex也称为弹性布局。
此外,我们也可以将flex布局称为伸缩布局,伸缩盒布局,flex布局。本节博客将对flex有一个详细的介绍。
二,flex容器介绍及父项常见属性
2.1 flex容器
下面是两个盒子,一个是父盒子,一个是子盒子。我们把父盒子称作容器(flex容器),小盒子称为项目(flex item)
2.2 主轴和侧轴
在flex布局中,有一个主轴和侧轴。这点非常重要,因为元素跟着主轴排列
所以我们先来学习如何调整主轴:
flex-direction: 属性值
属性值:
row: 主轴x轴,默认从左到右(默认)
row-reverse: x轴,从右到左
column: 主轴为y轴,从上到下
column-reserve: y轴,从下到上
==其中,请牢记,如果主轴为x
其中,flex-direction是必须要写的,下面,我们以row和colone来进行演示。请看如下代码:
<div>
<span>1</span>
<span>2</span>
<span>3</span>
</div>
现在,给父元素设置flex,并且设主轴为默认主轴:row
<style>
div {
/* 给父级添加flex属性 */
display: flex;
width: 800px;
height: 300px;
background-color: pink;
/* 默认的主轴是x轴,y轴就是侧轴,元素跟着主轴排列*/
flex-direction: row;
}
div span {
width: 150px;
height: 100px;
background-color: purple;
}
</style>
呈现出来的效果:子元素沿着x轴从左到右排列
当我们把主轴设为y轴,也就是column:
则子元素在父容器中沿着y轴从上到下排列。
注意,flex属性和主轴方向都是写在父元素的样式里的。初次之外,还有很多属性写在父元素中,或者说,大部分属性都写在父元素中。我们接下来意义来看(第二节中的全部)
2.3 主轴上的元素排列方式
需要在父元素中写样式来设置主轴元素排列
其中,我们必须要先设置好主轴才可以设置元素在主轴上排列的方式
代码格式:
justify-content: 属性值
结构如下:
<div>
<span>1</span>
<span>2</span>
<span>3</span>
</div>
属性值如下:
flex-start 默认值,从头部开始,如果主轴是x,则从左到右排列:
<style>
div {
display: flex;
width: 800px;
height: 400px;
background-color: pink;
flex-direction: row;
/* 默认主轴是x轴 */
justify-content: flex-end;
}
div span {
width: 150px;
height: 100px;
background-color: purple;
}
</style>
flex-end 从尾部开始排列:
center 在主轴居中对齐:
space-around 平分剩余空间,每个盒子的margin值都是一样的:
space-between 先两边贴边,再平分剩余空间,这个非常重要
2.4 设置子元素是否换行
flex默认元素不换行,也就是:
flex-wrap: nowrap;
如果盒子装不下会压缩子元素的大小。
请看如下案例;
<div>
<span>1</span>
<span>2</span>
<span>3</span>
<span>4</span>
<span>5</span>
<span>6</span>
</div>
<style>
div {
display: flex;
width: 800px;
height: 300px;
background-color: pink;
flex-direction: row;
justify-content: space-around;
/* flex元素默认子元素不换行,如果装不下会压缩子元素的大小*/
}
div span {
width: 150px;
height: 100px;
background-color: purple;
color: #fff;
}
</style>
当我在父元素中加上:
flex-wrap: wrap;
2.5 设置侧轴上子元素的排列方式
我们刚刚利用justify-content设置元素在主轴上(或者说元素沿着主轴的排列方式),现在我们将去操控侧轴上的元素排列方式。
2.5.1 设置侧轴上单行子元素排列方式
请看如下结构:
<div>
<span>1</span>
<span>2</span>
<span>3</span>
</div>
<style>
div {
display: flex;
width: 800px;
height: 300px;
background-color: pink;
flex-direction: row;
justify-content: center;
/* flex元素默认子元素不换行,如果装不下会压缩子元素的大小*/
}
div span {
width: 150px;
height: 100px;
background-color: purple;
color: #fff;
}
</style>
效果如下:
主轴为x轴,现在我们却想要所有元素在y轴上居中,则需要操控侧轴。也就是添加属性align-items来操控,代码格式如下:
align-itmems: 属性值
属性值:
flex-start: 沿着侧轴方向,这里是y轴,沿着侧轴方向从上到下(侧轴的正向):
flex-end:沿着侧轴方向(y轴)从下到上(反方向):
center:挤在一起居中
stretch:拉伸(默认值),我们来看下效果:
为什么没有反应呢?因为拉伸的时候子盒子不能给高度,如果我们把子盒子高度去掉,即可看到效果:
2.5.2 设置侧轴上多行子元素排列方式
多行与单行什么区别?行数不一样了。我们也知道,flex布局中默认不换行,所以如果是多行的话则需要写上换行样式,在前面介绍过,给父元素添加:
flex-wrap: wrap;
请看最初样式代码(主轴是row,x轴,侧轴为y轴):
<div>
<span>1</span>
<span>2</span>
<span>3</span>
<span>4</span>
<span>5</span>
<span>6</span>
</div>
<style>
div {
display: flex;
width: 800px;
height: 300px;
background-color: pink;
flex-direction: row;
justify-content: space-around;
flex-wrap: wrap;
}
div span {
width: 150px;
height: 100px;
background-color: purple;
color: #fff;
}
</style>
效果如下:
当我们设置好了多行后,就可以来调整样式了。注意,依旧是在侧轴上的样式
代码格式:
align-content: 属性值
属性值如下:
flex-start: 默认值在侧轴头部开始排列:
flex-end: 在侧轴尾部开始排列:
center: 在侧轴中间显示:
space-around: 子轴平分侧轴:
space-between:子轴先分散与侧轴头部,再平分其他位置:
stretch: 子项目分父元素高度,注意子元素不给高度:
2.6 复合写法
我们可以将设置主轴与是否换行写到一起去,但有时候会遇到权重问题,故不建议使用,格式如下:
flex-flow: 主轴 是否换行;
三,flex布局中子项常见属性
3.1 flex属性
这点非常重要
在flex中,子项占有分数,可以分配剩余空间。flex后面可以跟着数字,也可以跟着百分比。大量用于布局以及自适应
我们来举个例子:把一个盒子分成两份。我们首先给父盒子设置flex,再给子盒子设置flex值:
给子盒子1设置了一份,给子盒子2设置了一份,一共分成两份,把大盒子评分了。此时,如果我再加一份,只需要再添加一个盒子并且给第三个盒子设置为一份:
当然,也可以不平分。我们给第一个盒子设置为两份,其余盒子设置为一份:
只需修改flex值即可
flex的值也可以是百分比。比如一共有十个盒子,要排成两行,一行五个。可是如果我设置flex等于1,则十个盒子压缩排成了一行。那么只需要给每个盒子的flex设置为20%即可达到换行效果。
3.2 align-self属性
align-self控制子项在侧轴上的排列方式,给该盒子添加即可。
看以下结构:
<div>
<span>1</span>
<span>2</span>
<span>3</span>
</div>
<style>
div {
display: flex;
width: 80%;
height: 300px;
background-color: pink;
/* align-items: flex-end; */
/* 让三个子盒子沿着底侧多起 */
/* 我们想只让第三个盒子到底侧 */
}
div span {
width: 150px;
height: 100px;
background-color: purple;
margin-right: 5px;
}
</style>
效果如下:
我们现在想要把第三个盒子挪到下面去。(在侧轴上的位置)那么只需要加上align-self属性并单独设置样式即可,属性沿袭侧轴属性。代码如下:
div span:nth-child(3) {
align-self: flex-end;
}
效果如下:
3.3 order属性
order属性可以定义子项目排列顺序。==order数值越小,排列越靠前,默认值为0,如果把想要靠前的子项目设置为-1,因为-1<0所以该项目会靠在前面。
最初效果还是刚刚的初始代码下对应的代码:
给想要靠前的元素加上order即可使其调前,代码及效果如下:
div span:nth-child(2) {
order: -1;
}
大家看图,给2盒子加上了order,2盒子提前,顺序由123变成了213。
四,携程网首页案例
4.1 整体效果
下面只会穿插需要注意的几个问题以及整体代码。
4.2 背景图片快捷更换
我们在做电话费版块的时候,可能需要频繁更换背景图片。但是十张图片的代码整体一样,只有背景图片这一属性不一样,该怎么做?
做法:有一个整体的样式,并且十个盒子每个盒子都有一个样式来单独控制背景图片。
则需要用到属性选择器。
这里是每个盒子的类名:
它们都有一个共同的前缀。我们可以通过属性选择器给相同前缀的类一起添加样式:
然后再给其他类单独添加样式即可。
4.3 背景渐变
想要做出这种背景渐变的效果:
请看下面代码
在background属性中设置
-webkit-linear-gradient()
一共有三个参数,第一个是渐变方向,第二个参数是初始颜色,第三个参数是最终的颜色。其中,方向除了left,right,top,bottom,还可以是top left,left right
记住,只能用于移动端,而且需要加上私有前缀!
4.3 导航栏的做法思路
首先,我们需要准备一个大盒子,然后在大盒子中放入十个小盒子。使用flex布局,给大盒子加上flex,并让大盒子沿x轴从左到右为主轴,且同意换行。
给每个小盒子一个flex:20%让它们占比宽度的百分之二十。
现在,大盒子以及十个小盒子部分完成,接着完成小盒子内部。
现在开始小盒子:小盒子内部放一张图片,一段文字。使用flex布局,给小盒子加上flex,设置主轴沿y轴从上到下。
再让小盒子内部的侧轴(x轴)居中,即可完成。
代码如下:
<ul class="subnav-entry">
<li>
<a href="#">
<span class="subnav-entry-icon"></span>
<span>电话费</span>
</a>
</li>
<li>
<a href="#">
<span class="subnav-entry-icon"></span>
<span>电话费</span>
</a>
</li>
<li>
<a href="#">
<span class="subnav-entry-icon"></span>
<span>电话费</span>
</a>
</li>
<li>
<a href="#">
<span class="subnav-entry-icon"></span>
<span>电话费</span>
</a>
</li>
<li>
<a href="#">
<span class="subnav-entry-icon"></span>
<span>电话费</span>
</a>
</li>
<li>
<a href="#">
<span class="subnav-entry-icon"></span>
<span>电话费</span>
</a>
</li>
<li>
<a href="#">
<span class="subnav-entry-icon"></span>
<span>电话费</span>
</a>
</li>
<li>
<a href="#">
<span class="subnav-entry-icon"></span>
<span>电话费</span>
</a>
</li>
<li>
<a href="#">
<span class="subnav-entry-icon"></span>
<span>电话费</span>
</a>
</li>
<li>
<a href="#">
<span class="subnav-entry-icon"></span>
<span>电话费</span>
</a>
</li>
</ul>
.subnav-entry {
border-radius: 8px;
background-color: #fff;
margin: 0 4px;
display: flex;
flex-wrap: wrap;
padding: 5px 0;
}
.subnav-entry li {
flex: 20%;
}
.subnav-entry li a {
display: flex;
flex-direction: column;
align-items: center;
}
.subnav-entry-icon {
width: 28px;
height: 28px;
background-color: pink;
margin: 4px auto;
background: url('../imges/subnav-bg.png');
background-size: 28px auto;
}
五,整体代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible " content="IE=edge">
<meta name="viewport"
content="width=device-width, initial-scale=1.0, user-scalable=no, maxmum-scale=1.0, minmum-scale=1.0">
<style>
/* 初始css */
/* 去掉a中默认线和后面的高亮蓝色 */
a {
-webkit-tap-highlight-color: transparent;
text-decoration: none;
}
/* 去除按钮的外观效果 */
button {
-webkit-appearance: none;
}
/* 禁止长按图片弹出菜单 */
img,
a {
-webkit-touch-callout: none;
}
ul {
margin: 0;
padding: 0;
}
ul li {
list-style: none;
}
a {
color: #222;
}
body {
max-width: 540px;
min-width: 320px;
margin: 0 auto;
font: 400, 14px/1.5, '微软雅黑';
color: #000;
background: #f2f2f2;
/* overflow: hidden; */
}
/* 搜索模块 */
.search-index {
display: flex;
position: fixed;
top: 0;
left: 50%;
transform: translateX(-50%);
width: 100%;
height: 44px;
min-width: 320px;
max-width: 540px;
background-color: #f6f6f6;
border-top: 1px solid #ccc;
border-bottom: 1px solid #ccc;
}
.search {
position: relative;
flex: 1;
height: 26px;
box-sizing: border-box;
border: 1px solid #ccc;
margin: 6px 10px;
border-radius: 5px;
font-size: 12px;
color: #666;
line-height: 24px;
padding-left: 25px;
box-shadow: 0 2px 4px rgba(0, 0, 0, .2);
}
.search::before {
content: "";
position: absolute;
top: 5px;
left: 5px;
height: 15px;
width: 15px;
background: url('../imges/sprite.png') no-repeat -59px -279px;
background-size: 104px auto;
}
.user {
width: 44px;
height: 44px;
font-size: 12px;
text-align: center;
color: rgb(9, 159, 222);
}
.user::before {
content: "";
display: block;
width: 23px;
height: 23px;
background: url('../imges/sprite.png') no-repeat -59px -194px;
background-size: 104px auto;
margin: 4px auto 0;
}
/* 焦点图 */
.focus {
margin-top: 44px;
}
.focus img {
width: 100%;
}
/* 局部导航栏 */
.local-nav {
display: flex;
height: 65px;
background-color: #fff;
border-radius: 8px;
margin: 3px 4px;
}
.local-nav li {
flex: 1;
}
.local-nav a {
display: flex;
flex-flow: column nowrap;
align-items: center;
font-size: 12px;
}
.local-nav li [class^="local-nav-icon"] {
width: 32px;
height: 32px;
background-color: pink;
margin-top: 8px;
background: url('../imges/localnav_bg.png') no-repeat 0 0;
background-size: 32px auto;
}
.local-nav li .local-nav-icon-icon2 {
background-position: 0 -32px;
}
.local-nav li .local-nav-icon-icon3 {
background-position: 0 -64px;
}
.local-nav li .local-nav-icon-icon4 {
background-position: 0 -96px;
}
.local-nav li .local-nav-icon-icon5 {
background-position: 0 -128px;
}
/* 主导航栏 */
nav {
border-radius: 8px;
margin: 0 4px 3px;
overflow: hidden;
}
.nav-common {
display: flex;
height: 88px;
background-color: pink;
}
.nav-items {
display: flex;
flex: 1;
flex-direction: column;
align-items: center;
}
.nav-items a {
flex: 1;
line-height: 44px;
font-size: 14px;
color: #fff;
text-align: center;
width: 100%;
text-shadow: 1px 1px rgba(0, 0, 0, .2);
}
.nav-items a:nth-child(1) {
border-bottom: 1px solid #fff;
}
.nav-common:nth-child(2) {
margin: 3px 0;
}
.nav-items:nth-child(-n+2) {
border-right: 1px solid #fff;
}
.nav-items:nth-child(1) {
background: url('../imges/hotel.png') no-repeat bottom center;
background-size: 121px auto;
}
.nav-common:nth-child(1) {
background: -webkit-linear-gradient(left, rgb(250, 92, 85), rgb(250, 151, 77));
}
.nav-common:nth-child(2) {
background: -webkit-linear-gradient(left, rgb(75, 145, 237), rgb(82, 187, 237));
}
.nav-common:nth-child(3) {
background: -webkit-linear-gradient(left, rgb(53, 194, 168), rgb(107, 212, 90));
}
/* 侧导航栏 */
.subnav-entry {
border-radius: 8px;
background-color: #fff;
margin: 0 4px;
display: flex;
flex-wrap: wrap;
padding: 5px 0;
}
.subnav-entry li {
flex: 20%;
}
.subnav-entry li a {
display: flex;
flex-direction: column;
align-items: center;
}
.subnav-entry-icon {
width: 28px;
height: 28px;
background-color: pink;
margin: 4px auto;
background: url('../imges/subnav-bg.png');
background-size: 28px auto;
}
/* 销售模块 */
.sales-box {
background-color: #fff;
border-top: 1px solid #ccc;
margin: 4px;
}
.sales-hd {
position: relative;
height: 44px;
border-bottom: 1px solid #ccc;
}
.sales-hd h2 {
position: relative;
text-indent: -999px;
width: 79px;
overflow: hidden;
}
.sales-hd h2::after {
position: absolute;
top: 5px;
left: 8px;
content: "";
width: 79px;
height: 15px;
background: url('../imges/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: 8px;
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);
}
/* 图片模块 */
.sales-bd .row {
display: flex;
}
.row a {
flex: 1;
border: 1px solid #ccc;
}
.row a:nth-child(1) {
border-right: 1px solid #ccc;
}
.row img {
width: 100%;
;
}
</style>
<!-- 引入内部css -->
<title>携程在手,说走就走</title>
<link rel="stylesheet" href="./css/index.css">
</head>
<body>
<!-- 搜索模块 -->
<div class="search-index">
<div class="search">搜索:目的地/酒店/景点/航班号</div>
<a href="#" class="user">我 的</a>
</div>
<!-- 焦点图模块 -->
<div class="focus">
<img src="./imges/focus.jpg" alt="">
</div>
<!-- 局部导航栏 -->
<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>
<!-- 主导航栏 -->
<nav>
<div class="nav-common">
<div class="nav-items">
<a href="#">海外酒店</a>
</div>
<div class="nav-items">
<a href="#">海外酒店</a>
<a href="#">特价酒店</a>
</div>
<div class="nav-items">
<a href="#">海外酒店</a>
<a href="#">特价酒店</a>
</div>
</div>
<div class="nav-common">
<div class="nav-items">
<a href="#">海外酒店</a>
</div>
<div class="nav-items">
<a href="#">海外酒店</a>
<a href="#">特价酒店</a>
</div>
<div class="nav-items">
<a href="#">海外酒店</a>
<a href="#">特价酒店</a>
</div>
</div>
<div class="nav-common">
<div class="nav-items">
<a href="#">海外酒店</a>
</div>
<div class="nav-items">
<a href="#">海外酒店</a>
<a href="#">特价酒店</a>
</div>
<div class="nav-items">
<a href="#">海外酒店</a>
<a href="#">特价酒店</a>
</div>
</div>
</nav>
<!-- 侧导航栏 -->
<ul class="subnav-entry">
<li>
<a href="#">
<span class="subnav-entry-icon"></span>
<span>电话费</span>
</a>
</li>
<li>
<a href="#">
<span class="subnav-entry-icon"></span>
<span>电话费</span>
</a>
</li>
<li>
<a href="#">
<span class="subnav-entry-icon"></span>
<span>电话费</span>
</a>
</li>
<li>
<a href="#">
<span class="subnav-entry-icon"></span>
<span>电话费</span>
</a>
</li>
<li>
<a href="#">
<span class="subnav-entry-icon"></span>
<span>电话费</span>
</a>
</li>
<li>
<a href="#">
<span class="subnav-entry-icon"></span>
<span>电话费</span>
</a>
</li>
<li>
<a href="#">
<span class="subnav-entry-icon"></span>
<span>电话费</span>
</a>
</li>
<li>
<a href="#">
<span class="subnav-entry-icon"></span>
<span>电话费</span>
</a>
</li>
<li>
<a href="#">
<span class="subnav-entry-icon"></span>
<span>电话费</span>
</a>
</li>
<li>
<a href="#">
<span class="subnav-entry-icon"></span>
<span>电话费</span>
</a>
</li>
</ul>
<!-- 销售模块 -->
<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="./imges/pic1.jpg" alt="">
</a>
<a href="#">
<img src="./imges/pic2.jpg" alt="">
</a>
</div>
<div class="row">
<a href="#">
<img src="./imges/pic3.jpg" alt="">
</a>
<a href="#">
<img src="./imges/pic4.jpg" alt="">
</a>
</div>
<div class="row">
<a href="#">
<img src="./imges/pic5.jpg" alt="">
</a>
<a href="#">
<img src="./imges/pic6.jpg" alt="">
</a>
</div>
</div>
</div>
</body>
</html>
最后,希望本篇文章可以帮助大家更加细致的理解flex布局。写文不易,请多多关注,希望能帮到大家!