flex布局的应用 —— 模仿携程移动端的首页
写在前面
昨天已经过去,未来还未到来,所以当下是上天给的最好的恩赐,好好把握。
昨天又很仔细的看了看flex布局,今天下午动手用flex布局做了一个练习,就是模仿携程移动端首页。有一段时间没写html和css了,今天就是使用纯html和css搭建的一个首页,没有用到js。不过页面中确实有一个点可以用js做比较轻松,就是可以使用循环来生成精灵图,因为今天想写样式了,就没有用js写,下次再用js写一遍。
看到页面时,感觉不难。咳咳咳咳咳咳咳。。。。。 在写的时候,真的是各种的慢动作,还有用了一下午做出来的。这次的效果自我感觉比上次写京东移动端首页好点,可能是用的布局方式不同造成的吧。真心,flex布局就是比较好用。
家里停电了,电脑要没电了,废话不多说感觉撸,撸完就关机了。
ok,下面先看看我做的效果。
就是这样一个移动端的首页。emmm,我还不知道怎么使用真机测试,有空了也可以去试试看看怎么用真机来显示页面,哈哈哈哈。
温馨提示:我做的页面的图都是在携程网上自己扒的图。要是有想做的童鞋可以去扒扒图。
布局分析
顶部导航:使用固定定位做,主要提升层级,它是在最上层显示。
banner部分:这部分就是图片连接吧,很奇特的没有使用轮播图。
局部导航部分:local-nav。这个部分可以使用flex布局做。小图标跟文字都用span标签做。携程原版也是这样的布局。图标部分就是使用二倍精灵图来做的,要注意位置的设置。
导航栏部分:nav-common。 这个部分同样是使用flex布局。有一点麻烦的地方就是他们的背景色是渐变背景色,还有就是子元素的flex属性的设置不同。背景图片同样是使用二倍精灵图的做法。
侧边栏导航部分:subnav-entry。这部分的布局同样使用flex,它与局部导航栏的不同点就是,子元素的flex属性要使用百分比,父元素要设置换行。二倍精灵图的使用。
销售部分:sales-box。这个地方分为头部和主体部分。头部主要是用定位做,主体部分使用flex布局做。
最后底部部分:footer。flex布局搞定。
大概的一个布局就是这样。再仔细的话就有点啰嗦了。整体的思路,搭建的时候,一定要一边分析一边写,不然容易混乱。
核心点
这个案例的核心点,就是如何使用flex布局来布局页面,以及二倍图的使用。需要注意的是,我们用flex布局,不是整个页面都是flex布局,而是以flex局部为主,其他布局为辅进行的。
下一步的目标是:深入理解flex:1。这一句代码的含义。
代码部分
页面结构
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>携程在手,说走就走</title>
<link rel="stylesheet" href="css/normalize.css">
<link rel="stylesheet" href="css/index.css">
</head>
<body>
<!-- 顶部搜索栏部分 固定定位 -->
<div class="short-search">
<!-- 搜索框 其实它并不是一个搜索框 就是形状相似而已 当点击时才会跳转到搜索页面 -->
<div class="search">
<p>搜索:目的地/酒店/景点/航班号</p>
</div>
<div class="user">
<span class="user-icon"> </span>
<span>我 的</span>
</div>
</div>
<!-- banner -->
<div class="banner">
<a href="#">
<img src="upload/banner.jpg">
</a>
</div>
<!-- local-nav -->
<ul class="local-nav">
<li>
<a href="#">
<span class="local-nav-icon-icon1"></span>
<span class="local-nav-iconContent">攻略·景点</span>
</a>
</li>
<li>
<a href="#">
<span class="local-nav-icon-icon2"></span>
<span class="local-nav-iconContent">门票·玩乐</span>
</a>
</li>
<li>
<a href="#">
<span class="local-nav-icon-icon3"></span>
<span class="local-nav-iconContent">美食林</span>
</a>
</li>
<li>
<a href="#">
<span class="local-nav-icon-icon4"></span>
<span class="local-nav-iconContent">周边游</span>
</a>
</li>
<li>
<a href="#">
<span class="local-nav-icon-icon5"></span>
<span class="local-nav-iconContent">一日游</span>
</a>
</li>
</ul>
<!-- system_notice -->
<div class="system_notice">
<p>受新冠疫情影响,各国家及地区入境政策汇总查看</p>
</div>
<!-- nav -->
<nav class="nav-wrap">
<div class="nav-common row1">
<div class="nav-items">
<a href="#">酒店</a>
</div>
<div class="nav-items">
<a href="#">民宿·客栈</a>
</div>
<div class="nav-items">
<span class="specious">方便又便宜</span>
<a href="#">机票/火车票+酒店</a>
</div>
</div>
<div class="nav-common row2">
<div class="nav-items">
<a href="#">飞机</a>
</div>
<div class="nav-items">
<a href="#">火车票</a>
</div>
<div class="nav-items">
<a href="#">汽车·船票</a>
</div>
<div class="nav-items">
<a href="#">专车·租车</a>
</div>
</div>
<div class="nav-common row3">
<div class="nav-items">
<a href="#">旅游</a>
</div>
<div class="nav-items">
<a href="#">高铁游</a>
</div>
<div class="nav-items">
<a href="#">邮轮游</a>
</div>
<div class="nav-items">
<a href="#">定制游</a>
</div>
</div>
</nav>
<!-- subnav-entry -->
<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>
<!-- sales-box -->
<div class="sales-box">
<div class="sales-hd">
<h2>热门活动</h2>
<p>获取更多福利</p>
</div>
<div class="sales-bd">
<div class="row">
<a href="#">
<img src="upload/pic1.jpg">
</a>
<a href="#">
<img src="upload/pic2.jpg">
</a>
</div>
<div class="row">
<a href="#">
<img src="upload/pic3.png">
</a>
<a href="#">
<img src="upload/pic4.jpg">
</a>
</div>
<div class="row">
<a href="#">
<img src="upload/pic5.jpg">
</a>
<a href="#">
<img src="upload/pic6.jpg">
</a>
</div>
</div>
</div>
<!-- footer -->
<footer>
<div class="tel">
<span class="tel-icon"></span>
<span>电话预约</span>
</div>
<div class="download">
<span class="download-icon"></span>
<span>下载客户端</span>
</div>
<div class="about">
<span class="about-icon"></span>
<span>我的</span>
</div>
</footer>
</body>
</html>
样式部分
body {
/* 不出现水平滚动条 */
overflow-x: hidden;
/* 按钮不显示高亮 */
-webkit-tap-highlight-color: transparent;
-webkit-text-size-adjust: none;
-moz-user-select: none;
max-width: 540px;
min-width: 320px;
margin: 0 auto;
background: #fafafc;
font-size: 12px;
/* 一会回来删 */
/* height: 3000px; */
}
div {
box-sizing: border-box;
}
p {
margin: 0;
}
ul {
list-style: none;
margin: 0;
padding: 0;
}
a {
text-decoration: none;
}
/* 顶部快捷导航 */
.short-search {
position: fixed;
z-index: 50;
top: 0;
width: 100%;
max-width: 540px;
height: 44px;
/* background-color: pink; */
/* 当下面得图片没有时,会有背景色 */
/* background: -webkit-linear-gradient(top, rgba(0, 0, 0, .2), rgba(255, 255, 255, .4)); */
}
/* user */
.user {
display: flex;
/* 上下排列 设置主轴为y轴 */
flex-direction: column;
/* 沿着侧轴 水平居中 */
align-items: center;
position: absolute;
top: 0;
right: 0;
width: 51px;
height: 44px;
/* background-color: purple; */
}
.user-icon {
width: 22px;
height: 22px;
background: url(../images/short-search-sprite2x.png) no-repeat 1px -36px;
/* 手动更改精灵图得大小 二倍图 缩小一半 */
background-size: 21px auto;
margin: 3px 0;
}
.user span {
flex: 1;
color: #eee;
}
/* search */
.search {
position: absolute;
left: 5px;
width: 85%;
height: 28px;
background-color: #fff;
border-radius: 20px;
margin: 8px;
}
.search p {
line-height: 28px;
padding-left: 36px;
color: #aaa;
font-size: 14px;
}
.search p::before {
content: "";
position: absolute;
top: 0;
left: 0;
width: 35px;
height: 28px;
background: url(../images/short-search-sprite2x.png) no-repeat 15px 7px;
background-size: 21px auto;
}
/* banner */
.banner {
position: relative;
width: 100%;
overflow: hidden;
/* 降低层级 */
z-index: -1;
}
.banner img {
width: 100%;
height: 50%;
/* border-radius: 0 0 80px 80px; */
margin-top: -50px;
vertical-align: top;
}
/* local-nav */
.local-nav {
display: flex;
height: 64px;
margin: -70px 12px 10px;
background-color: #fff;
border-radius: 10px;
padding: 8px;
}
.local-nav li {
/* 作为子元素 占份数1 */
flex: 1;
}
.local-nav a {
/* 作为子元素 占1份 */
flex: 1;
/* 作为父元素 flex布局 */
display: flex;
/* 设置主轴为Y轴 垂直排列 */
flex-direction: column;
/* 子元素在侧轴中居中 a中的span元素*/
align-items: center;
}
.local-nav a [class^="local-nav-icon-"] {
width: 40px;
height: 40px;
background-color: pink;
background: url(../images/home-fivemain-sprite2x.png) no-repeat 0 0;
background-size: 40px auto;
margin-bottom: 3px;
}
.local-nav a .local-nav-icon-icon2 {
background-position: 0 -40px;
}
.local-nav a .local-nav-icon-icon3 {
background-position: 0 -80px;
}
.local-nav a .local-nav-icon-icon4 {
background-position: 0 -120px;
}
.local-nav a .local-nav-icon-icon5 {
background-position: 0 -160px;
}
.local-nav li .local-nav-iconContent {
color: #222;
line-height: 1;
}
.system_notice {
position: relative;
height: 45px;
margin: 12px;
background-color: #ffecdc;
border-radius: 20px;
line-height: 45px;
}
.system_notice::before {
position: absolute;
top: 0;
left: 10px;
content: '\f504';
width: 10px;
height: 10px;
color: #fc8c6f;
}
.system_notice::after {
position: absolute;
top: 0;
right: 10px;
content: '\e944';
width: 10px;
height: 10px;
color: #666;
}
.system_notice p {
padding-left: 30px;
}
/* nav */
.nav-wrap {
border-radius: 8px;
margin: 0 12px;
overflow: hidden;
}
.nav-common {
display: flex;
height: 88px;
background-color: pink;
justify-content: center;
align-items: center;
}
.nav-items a {
display: block;
color: #fff;
font-size: 14px;
height: 88px;
line-height: 88px;
}
/* 从第二个元素开始 */
.nav-items:nth-child(n+1) a {
text-align: center;
}
.nav-items:first-child a {
margin-left: 10px;
text-align: left;
}
.row1 .nav-items:nth-child(1) {
flex: 1.5;
background: linear-gradient(to right, #fa5a56, #fa7252);
}
.row1 .nav-items:nth-child(1) a {
background: url(../images/nav-items-hotel.png) no-repeat bottom right;
background-size: 108px auto;
}
.row1 .nav-items:nth-child(2) {
flex: 1;
background: linear-gradient(to right, #fa7252, #fb8550);
}
.row1 .nav-items:nth-child(2) a {
background: url(../images/nav-items-minsu.png) no-repeat bottom left;
background-size: 53px auto;
}
/* 前两个元素添加右边框 */
.row1 .nav-items:nth-child(-n+2) {
border-right: 1px solid #fff;
}
.row1 .nav-items:nth-child(3) {
flex: 2;
position: relative;
/* 第一行的三个元素渐变色 覆盖掉上面的那个渐变色 */
background: linear-gradient(to right, #ffbc49, #ffd252);
}
.row1 .nav-items:nth-child(3) a {
background: url(../images/nav-items-jhj.png) no-repeat bottom right;
background-size: 87px auto;
}
.row1 .nav-items .specious {
position: absolute;
top: 20px;
right: 48px;
background-color: red;
border-radius: 20px 20px 20px 0;
color: #fff;
padding: 2px 5px;
font-size: 10px;
}
.row2 {
border-top: 1px solid #fff;
border-bottom: 1px solid #fff;
background: linear-gradient(to right, #4b8fed, #53bced);
}
/* 前三个元素添加边框 */
.row2 .nav-items:nth-child(-n+3),
.row3 .nav-items:nth-child(-n+3) {
border-right: 1px solid #fff;
}
.row2 .nav-items:first-child {
flex: 1.5;
background: url(../images/nav-items-flight.png) no-repeat bottom right;
background-size: 120px auto;
}
.row2 .nav-items,
.row3 .nav-items {
flex: 1;
}
.row2 .nav-items:nth-child(2) {
background: url(../images/nav-items-train.png) no-repeat bottom left;
background-size: 56px auto;
}
.row3 {
background: linear-gradient(to right, #34c2a9, #6cd558);
}
.row3 .nav-items:first-child {
flex: 1.5;
background: url(../images/nav-items-travel.png) no-repeat bottom right;
background-size: 140px auto;
}
.row3 .nav-items:nth-child(2) {
background: url(../images/nav-items-dingzhi.png) no-repeat bottom left;
background-size: 92px auto;
}
/* subnav-entry */
.subnav-entry {
display: flex;
/* 里面的li要换行 */
flex-wrap: wrap;
padding: 10px 0 8px;
border-bottom: 1px solid #eee;
margin-bottom: 3px;
}
.subnav-entry li {
/* 每个li占20% 可以是百分比 */
flex: 20%;
}
/* li里面的a flex布局 控制span */
.subnav-entry li a {
display: flex;
flex-direction: column;
align-items: center;
color: #222;
font-size: 8px;
}
.subnav-entry li a span:nth-child(2) {
margin: 5px 0;
}
.subnav-entry [class^='subnav-entry-icon'] {
width: 28px;
height: 28px;
background-color: pink;
background: url(../images/ico_subnav2x.png) no-repeat 0 0;
background-size: 28px auto;
}
.subnav-entry .subnav-entry-icon-icon2 {
background-position: 0 -28px;
}
.subnav-entry .subnav-entry-icon-icon3 {
background-position: 0 -56px;
}
.subnav-entry .subnav-entry-icon-icon4 {
background-position: 0 -84px;
}
.subnav-entry .subnav-entry-icon-icon5 {
background-position: 0 -112px;
}
.subnav-entry .subnav-entry-icon-icon6 {
background-position: 0 -140px;
}
.subnav-entry .subnav-entry-icon-icon7 {
background-position: 0 -168px;
}
.subnav-entry .subnav-entry-icon-icon8 {
background-position: 0 -196px;
}
.subnav-entry .subnav-entry-icon-icon9 {
background-position: 0 -224px;
}
.subnav-entry .subnav-entry-icon-icon10 {
background-position: 0 -252px;
}
/* sales-box */
.sales-hd {
position: relative;
border-bottom: 1px solid #eee;
border-top: 1px solid #eee;
padding: 10px 0;
}
.sales-hd h2 {
text-indent: -9999px;
overflow: hidden;
padding: 0;
margin: 0;
}
.sales-hd h2::before {
content: "";
position: absolute;
top: 13px;
left: 15px;
width: 79px;
height: 15px;
background-color: pink;
background: url(../images/hot.png) no-repeat 0 -20px;
background-size: 79px auto;
}
.sales-hd p {
position: absolute;
top: 7px;
right: 8px;
height: 20px;
border-radius: 15px;
background: linear-gradient(to right, #FF506C, #FF6BC6);
padding: 3px 20px 2px 7px;
line-height: 20px;
color: #fff;
}
.sales-hd p::after {
content: "";
position: absolute;
top: 8px;
right: 9px;
width: 7px;
height: 7px;
border-right: 2px solid #fff;
border-top: 2px solid #fff;
transform: rotate(45deg);
}
.sales-hd p:hover {
cursor: pointer;
}
/* sales-bd */
.row {
display: flex;
}
.row a {
flex: 1;
border-bottom: 1px solid #eee;
}
.row a:first-child {
border-right: 1px solid #eee;
}
.row a img {
width: 100%;
vertical-align: top;
}
/* footer */
footer {
display: flex;
border-top: 1px solid #ccc;
margin: 8px 0;
background-color: #fff;
padding-bottom: 10px;
}
footer div {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
}
footer div span:first-child {
width: 20px;
height: 20px;
background-color: pink;
margin: 15px 0 5px 0;
background: url(../images/bottom-bg.png) no-repeat;
background-size: 104px auto;
}
footer .tel .tel-icon {
background-position: -59px -154px;
}
footer .download .download-icon {
background-position: -59px -174px;
}
footer .about .about-icon {
background-position: -59px -309px;
}
孤江独钓,江湖路人: 这种水平属于什么级别,我是小白,啥时候能做到这样
错赴旧梦: 黑马程序员
AAS48: 不错呀
苍岚王: 我想了想在右上角的按钮可以加上一个小功能,监听键盘点击后,按钮active变色,感觉还是比较nice的
苍岚王: 确实很赞,这个小游戏里面很充分的利用了数学里面等量代换的思想,因为要实现移动所以要定帧,所以,是必定要定时器的,而这个时候用flag去改变路径是很巧妙的思想,我个人觉得比较难的地方是怎么合理且优雅的写出监听和路径的改变,这些代码都能满足,只能说一句博主nb