前言
这里说一个理论上的东西,我们需要结合css的布局方案来完成html的代码结构。
这句话说的是,我们要结合你完成某个模块所使用的css的布局方式来编写html的结果。
常见的css布局方式为:
- 浮动布局(float)
- 定位布局(position)
- 弹性布局(flex)
- 网格布局(grid)
很多人都会忽略一个默认的布局方式:普通流(Normal Flow)。个人习惯性称其为流动布局。至于怎么称呼不重要,重要的是,我们需要根据这个流动布局将网页的整体结构给构建出来。
我们知道,html中元素根据其显示类型可以分为两大类:
- 块级元素(Block-level Elements)
- 行内元素(Inline Elements)
- 行内块元素(Inline-block Elements)
其中块级元素的特点:独占一行,默认宽度为父元素的100%,可以设置宽高(width/height)、内外边距(margin/padding)。
行内元素的特点:不换行,宽度由内容决定,无法设置宽高,上下边距(margin-top/margin-bottom)无效。
行内块元素的特点:兼具行内和块级元素的特性:不换行,但可以设置宽高和边距。
很多人会为了让元素在同一行显示而使用行内块元素,这里我们不推荐使用该类型的元素(或者说,不推荐将块级元素或者行内元素的显示类型设为行内块),应该优先使用css布局实现水平排列。
推荐始终使用布局+块级元素的方式实现内容,而行内元素仅用于需要设置一句话中某个词语的特定样式时使用。
使用流动布局完成首页结构
我们根据PBootCMS的官网首页,得到如下结构。
首页的结构非常简单,并没有涉及到复杂的布局,我们根据上面的结构图,得到如下代码:
<body>
<header></header>
<main></main>
<footer></footer>
</body>
将上述代码写入index.html
中。
头部导航的设计
有了整体的结构,我们需要将这四个部分填充完成。
首先考虑最上方,也就是头部。
这是一个非常常见的左右布局结构:
- 左边是网站的logo
- 右边是导航菜单
那么,我们可以在脑海里想象出html的结构是:
头部导航的html结构
这样一来,我们可以先写出html。
<header>
<div class="container">
<div class="logo">
<img src="./assets/images/logo.png" alt="网站logo">
</div>
<nav>
<ul class="navbar">
<li>首页</li>
<li>系统简介</li>
<li>推荐商家</li>
<li>开发手册</li>
<li>技术交流</li>
<li>更新日志</li>
</ul>
</nav>
</div>
</header>
记得将PBootCMS官网的logo另存为到自己的目录下,这里我放在了assets/images
目录下,因为这个logo可能在其他地方也会用到,不需要放到首页特定的目录。
这里.container
类保证了我们的内容区域限定在了特定的区域中。
头部导航的css样式
固定header
接下来,我们就需要用css实现效果的美化。
首先我们注意一下,这个导航的是不随页面滚动而滚动的。也就是说,这里头部导航是固定的,那我们首先想到的是,使用定位中的“fix绝对定位”,当然你也可以称它为“固定定位”。另外由于绝对定位会失去原来的文档流,导致下方元素重叠,我们需要一个高度,这样方便后面使用padding或者其他方式撑起轮播图,否则轮播图会和头部重叠。
给header元素加上.header
类,这里无须担心与其他页面产生冲突,我们前面说了,每个页面使用单独的样式文件,而且每个页面的头部是一样的,后续可以复用。
<header class="header">
</header>
.header
的样式表为:
.header {
position: fixed;
top: 0;
left: 0;
z-index: 9;
width: 100vw;
height: 3.5rem;
box-shadow: 0 .125rem .25rem rgba(0,0,0,.075);
}
将上面的css代码写入新的css文件common.css
中,表示各页面通用的样式。
由于绝对定位会失去原来的文档流,因此需要明确设置其大小、位置以及层级,防止被后面内容覆盖。
宽度设为100vw
表示始终为浏览器视口宽度,高度3.5rem
相对html的字体大小,转换后为70px
,最后加了一个盒子阴影,视觉上产生层次感。
头部的固定完成。
导航菜单的排列
这里可以参考另一篇文章:如何实现一个好看且可复用的导航菜单?。
我们使用弹性布局(flex)实现相关功能。
另外,由于导航菜单需要跳转,我们还要改造html结构。
<ul class="navbar">
<li>
<a href="#">首页</a>
</li>
<li>
<a href="#">系统简介</a>
</li>
<li>
<a href="#">推荐商家</a>
</li>
<li>
<a href="#">开发手册</a>
</li>
<li>
<a href="#">技术交流</a>
</li>
<li>
<a href="#">更新日志</a>
</li>
</ul>
.navbar {
display: flex;
}
.navbar > li {
padding: 0.2rem 0.5rem;
font-size: 0.7rem;
}
.navbar > li > a {
text-decoration: none;
}
.navbar > li > a:link, .navbar > li > a:visited {
color: rgba(0,0,0,.5);
}
.navbar > li > a:hover {
color: rgba(0,0,0,.8);
}
- 通过
display:flex
让块级元素li
沿着主轴方向排列,实现了水平布局; - 设置
li
标签的内边距使得导航文字间距相同,如果使用width
则文字长度不一样会导致间距不一样,同样使用margin
也能达到相关效果。 - 将超链接
a
标签的相关伪类覆盖,取消下划线。
到此为止,我们可以看一下现在的效果:
下面考虑logo与导航菜单的布局。
logo与导航菜单的布局
这是一个经典的左右布局,因此无须考虑复杂场景,使用弹性布局即可。
那么问题来了,这个弹性布局设置在哪里?
很明显,只能是logo与导航菜单共同的父元素,也就是这个设置了.container
类的div
:
那么,这里是要给其加上新的类还是该如何实现?
我们上面说了,头部是共用的部分,不会产生冲突,既然这样,我们就没有必要再写一个类,直接通过子选择器实现:
.header > .container
样式表如下:
.header > .container {
display: flex;
justify-content: space-between;
align-items: center;
}
这时候应该发现,这个代码与上一节最后写的.flex-row-between
类是一样的,那我们直接用这个类其实也可以,根据你自己需要选择。
这个时候还会产生一个小问题,由于.container
并没有高度,而其父元素.header
设置了3.5rem
的高度,因此.container
的高度完全由其子元素撑起,那如果子元素并不能恰好达到3.5rem
的高度怎么办?
可以看到,此时内容区域是整体偏上的,那怎么让.container
在.header
中垂直居中?
最简单的方法就是给.header
添加弹性布局:
.header {
......
display: flex;
align-items: center;
}
其他
最后注意一下,我们说,header使用了绝对定位,那么其脱离文档流之后会对后面的内容产生影响,我们设置了3.5rem
的高度,且z-index
为9,这个情况就会覆盖后面的banner,我们需要对html进行处理,使其上内边距同样为3.5rem
这样就将覆盖的区域空出来,从而不影响后续内容。
在layout.css
中,修改html的样式表:
html {
font-size: 20px;
padding-top: 3.5rem;
}