们前端开发过程中,写css(包括sass, less, stylus这样的预处理器)进行设计稿的样式还原是一项重要的工作,而其中,关于页面布局的部分,又是书写样式代码时候的重点和难点,这篇文章就尽可能的去总结常见的一些页面布局实现方案(并不是全部,布局实现方法太多了),希望能够对大家有所帮助。
在开始正题之前,有一点要说明:css布局中遇到的一个绕不开的问题就是浏览器兼容性,下面方案会遇到类似transform, flex等的兼容性问题,且由于grid布局兼容性问题,暂不涉及grid布局内容,在不同场景,大家选择合适的布局实现方案即可。
1.1 水平居中布局
效果图如下:
分析:display设置为inline-block的元素,具有文本元素的性质,其父元素可以通过设置文本对齐属性text-align来控制其在行内的对齐方式,text-align: center即为水平对齐
注意:text-align属性是具有继承性的,会导致自己元素内部的文本也是居中显示的,需要自身设置text-align覆盖
<style>
.wrap {
width: 100%;
height: 200px;
background-color: aqua;
text-align: center;
}
.content {
width: 200px;
height: 200px;
background-color: blueviolet;
display: inline-block;
}
</style>
<body>
<div class="wrap">
<div class="content"></div>
</div>
</body>
分析:父元素开启定位(relative,absolute,fixed都可以)后,子元素设置绝对定位absolute后,left设置为50%,再使用transform: translateX(-50%)将子元素往反方向移动自身宽度的50%,便完成水平居中。
注意:父级元素是否脱离文档流,不影响子元素水平居中效果,但是transform是css3属性,存在浏览器兼容问题
<style>
.wrap {
position: relative;
width: 100%;
height: 200px;
background-color: aqua;
}
.content {
position: absolute;
left: 50%;
transform: translateX(-50%);
width: 200px;
height: 200px;
background-color: blueviolet;
}
</style>
<body>
<div class="wrap">
<div class="content"></div>
</div>
</body>
分析:这个方法只需要对子元素进行设置就可以实现水平居中,margin设置auto表示浏览器会自动分配,实现来外边距等分效果。
注意:这里子元素设置display为block或者table都是可以的,如果子元素脱离文档流(浮动,定位),会导致margin属性的值无效。
<style>
.wrap {
width: 100%;
height: 200px;
background-color: aqua;
}
.content {
width: 200px;
height: 200px;
background-color: blueviolet;
display: table;
margin: 0 auto;
}
</style>
<body>
<div class="wrap">
<div class="content"></div>
</div>
</body>
效果图如下:
这种方案和之前水平居中布局的方案二是同样的原理,不在赘述
<style>
.wrap {
position: relative;
width: 200px;
height: 600px;
background-color: aqua;
}
.content {
position: absolute;
top: 50%;
transform: translateY(-50%);
width: 200px;
height: 200px;
background-color: blueviolet;
}
</style>
<body>
<div class="wrap">
<div class="content"></div>
</div>
</body>
分析:设置display: table-cell的元素具有td元素的行为,它的子元素布局方式类似文本元素,可以在父元素使用vertical-align: middle;实现子元素的垂直居中。
注意:vertical-align属性具有继承性,导致父元素内文本也是垂直居中显示的。
<style>
.wrap {
display: table-cell;
vertical-align: middle;
width: 200px;
height: 600px;
background-color: aqua;
}
.content {
width: 200px;
height: 200px;
background-color: blueviolet;
}
</style>
<body>
<div class="wrap">
<div class="content"></div>
</div>
</body>
效果图如下:
前面分别总结了一些水平居中和垂直居中的布局方式,那么进行水平垂直居中的布局,也就没什么特别要说的了,直接上代码:
方案一.定位 + transform
<style>
.wrap {
position: relative;
width: 1200px;
height: 800px;
background-color: aqua;
}
.content {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 200px;
height: 200px;
background-color: blueviolet;
}
</style>
<body>
<div class="wrap">
<div class="content"></div>
</div>
</body>
方案二. 结合水平布局方案三,垂直布局方案二
<style>
.wrap {
display: table-cell;
vertical-align: middle;
width: 1200px;
height: 800px;
background-color: aqua;
}
.content {
margin: 0 auto;
width: 200px;
height: 200px;
background-color: blueviolet;
}
</style>
<body>
<div class="wrap">
<div class="content"></div>
</div>
</body>
分析:使用flex,水平垂直居中会变得非常容易,默认情况下,align-items: center垂直居中(交叉轴排列方式),justify-content: center水平居中(主轴排列方式) 注意:需要考虑浏览器兼容性问题。
<style>
.wrap {
display: flex;
align-items: center;
justify-content: center;
width: 1200px;
height: 800px;
background-color: aqua;
}
.content {
width: 200px;
height: 200px;
background-color: blueviolet;
}
</style>
<body>
<div class="wrap">
<div class="content"></div>
</div>
</body>
2.1 两列布局
这里的两列布局指的是,其中一列是定宽元素,另一列元素宽度自适应。比如,我们实现左列定宽,右列自适应的布局。
效果图如下:
分析:一个最简单的做法,左边元素设置浮动,定宽,右边元素的margin-left设置为左边元素宽度大小,可以实现效果。
注意:我们左边元素使用了浮动,但是右边元素没有浮动
<style>
.l, .r {
height: 600px;
}
.l {
width: 400px;
background-color: aqua;
float: left;
}
.r {
background-color: blueviolet;
margin-left: 400px;
}
</style>
<body>
<div class="l">定宽</div>
<div class="r">自适应</div>
</body>
分析:右边元素由于设置overflow:hidden开启BFC,与外界隔离,所以能实现效果
注意:overflow:hidden的设置也使得右边元素内容超出隐藏。这里如果不设置overflow:hidden,右边元素的宽度是100%,有一部分被左边浮动元素盖住,不是我们要的结果,虽然看起来没什么区别。
<style>
.l, .r {
height: 600px;
}
.l {
width: 400px;
background-color: aqua;
float: left;
}
.r {
background-color: blueviolet;
overflow: hidden;
}
</style>
<body>
<div class="l">定宽</div>
<div class="r">自适应</div>
</body>
分析:这里主要是基于表格元素,在没有设置宽度时,会自动分配宽度来实现布局的。
注意:设置为表格后,在某些浏览器可能会受到表格本身特有行为的影响,比如表格边框等等。
<style>
.w {
display: table;
table-layout: fixed;
width: 100%;
}
.l, .r {
display: table-cell;
height: 600px;
}
.l {
width: 400px;
background-color: aqua;
}
.r {
background-color: blueviolet;
}
</style>
<body>
<div class="w">
<div class="l">定宽</div>
<div class="r">自适应</div>
</div>
</body>
分析:父容器采用flex布局,左边元素定宽之后,右边元素,因为只有一个,所以flex属性设置为不是0的正值(也就是设置flex-grow),都会占满剩余空间。
注意:依然是,注意兼容性问题。
2.2 三列布局
这里的三列布局,主要分三种情况介绍,第一种是普通三列布局,还有两种是比较有名的圣杯布局和双飞翼布局(两者都是实现一个两侧宽度固定,中间宽度自适应的三列布局,区别在于双飞翼布局比起圣杯布局,中间元素会多一个子元素,而左右元素需要定位relative)
2.2.1. 普通三列布局
我们这里实现的是,左中两列定宽,右边一列自适应的布局,这个实际上和前面的两列布局是类似的。
效果图如下:<style>
.p {
display: flex;
height: 600px;
}
.l {
background-color: aqua;
width: 400px;
}
.r {
flex: 1;
background-color: blueviolet;
}
</style>
<body>
<div class="p">
<div class="l">定宽</div>
<div class="r">自适应</div>
</div>
</body>
这里的三列布局,主要分三种情况介绍,第一种是普通三列布局,还有两种是比较有名的圣杯布局和双飞翼布局(两者都是实现一个两侧宽度固定,中间宽度自适应的三列布局,区别在于双飞翼布局比起圣杯布局,中间元素会多一个子元素,而左右元素需要定位relative)
我们这里实现的是,左中两列定宽,右边一列自适应的布局,这个实际上和前面的两列布局是类似的。
效果图如下:
分析:这个方案和两列布局方案二是相同的。
<style>
.l, .c, .r {
height: 600px;
}
.l {
width: 400px;
background-color: aqua;
float: left;
}
.c {
width: 400px;
background-color: blueviolet;
float: left;
}
.r {
background-color: brown;
overflow: hidden;
}
</style>
<body>
<div class="l">定宽</div>
<div class="c">定宽</div>
<div class="r">自适应</div>
</body>
分析:这里布局原理和两列布局中flex布局方式是相同的。
<style>
.w {
display: flex;
height: 600px;
}
.l {
width: 400px;
background-color: aqua;
}
.c {
width: 400px;
background-color: blueviolet;
}
.r {
flex: 1;
background-color: brown;
}
</style>
<body>
<div class="w">
<div class="l">定宽</div>
<div class="c">定宽</div>
<div class="r">自适应</div>
</div>
</body>
两侧宽度固定,中间宽度自适应的三列布局(中间元素不需要嵌套子元素)
效果图如下:
分析:这种方法就是左右两边浮动,给定宽度,中间元素使用margin空出左右两边元素的位置,实现比较简单。
注意:这种方式,需要在书写html结构时,将右侧元素写在中间元素的前面,因为如果右侧元素在中间元素后面,由于浮动元素位置上不能高于(或平级)前面的非浮动元素,导致右侧元素会下沉。但是,中间元素一般都是页面的核心部分,放在比较后面的位置,不利于SEO。
<style>
.l, .c, .r {
height: 600px;
}
.l {
width: 400px;
background-color: aqua;
float: left;
}
.c {
background-color: blueviolet;
margin-left: 400px;
margin-right: 400px;
}
.r {
width: 400px;
background-color: brown;
float: right;
}
</style>
<body>
<div class="l">定宽</div>
<div class="r">定宽</div>
<div class="c">自适应</div>
</body>
分析:这种方法将中间元素c放置在最前面,有利于SEO。
注意:实现细节在参考下面代码中的注释。
<style>
.w {
/* margin-left对应左边元素l的宽度,margin-right对应右边元素r的宽度 */
margin-left: 400px;
margin-right: 400px;
}
.l, .c, .r {
height: 600px;
float: left;
}
.l {
width: 400px;
background-color: aqua;
position: relative;
/* 为了让l元素从当前行移动到第一行同一位置*/
margin-left: -100%;
/* 移动到中间元素左侧正确位置 */
left: -400px;
}
.c {
width: 100%;
background-color: blueviolet;
}
.r {
width: 400px;
background-color: brown;
position: relative;
/* 为了让l元素从当前行移动到上一行*/
margin-left: -400px;
right: -400px;
}
</style>
<body>
<div class="w">
<div class="c">自适应</div>
<div class="l">定宽</div>
<div class="r">定宽</div>
</div>
</body>
两侧宽度固定,中间宽度自适应的三列布局(中间元素内部增加子元素用于放置内容)
效果图如下:
分析:这种方法为中间元素增加子元素作为内容区域,通过子元素设置margin完成。
注意:和圣杯布局对照,有相似处,也有不同,实现的结果是一样的。
<style>
.l, .c, .r {
height: 600px;
float: left;
}
.l {
width: 400px;
background-color: aqua;
/* 为了让l元素从当前行移动到第一行同一位置*/
margin-left: -100%;
}
.c {
width: 100%;
background-color: blue;
}
.i {
height: 600px;
background-color: blueviolet;
margin-left: 400px;
margin-right: 400px;
}
.r {
width: 400px;
background-color: brown;
/* 为了让r元素移动到第一行*/
margin-left: -400px;
}
</style>
<body>
<div class="c">
<div class="i">自适应</div>
</div>
<div class="l">定宽</div>
<div class="r">定宽</div>
</body>
分析:flex实现就很简单了,可以参照普通三列布局flex实现。
注意:还是要注意浏览器兼容性问题。
<style>
.w {
display: flex;
height: 600px;
}
.l {
width: 400px;
background-color: aqua;
}
.c {
flex: 1;
background-color: blueviolet;
}
.r {
width: 400px;
background-color: brown;
}
</style>
<body>
<div class="w">
<div class="l">定宽</div>
<div class="c">自适应</div>
<div class="r">定宽</div>
</div>
</body>
所谓多列等分布局,就是若干列在容器中自适应等分宽度,我们以五列等分布局为例。
效果图如下:
分析:这种方案就是每一列浮动,之后按照百分比平分宽度,实现简单。
<style>
.col {
float: left;
width: 20%;
height: 300px;
}
.col1 {
background-color: blue;
}
.col2 {
background-color: blueviolet;
}
.col3 {
background-color: aqua;
}
.col4 {
background-color: beige;
}
.col5 {
background-color: salmon;
}
</style>
<body>
<div class="w">
<div class="col col1"></div>
<div class="col col2"></div>
<div class="col col3"></div>
<div class="col col4"></div>
<div class="col col5"></div>
</div>
</body>
分析:父容器指定display: table,设置布局行为table-layout: fixed,指定每个表格等宽。
注意:table-layout: fixed是需要设置的,默认情况下,列宽度由单元格内容设定,设置之后,列宽由表格宽度和列宽度设定。
<style>
.w {
display: table;
/* 列宽由表格宽度和列宽度设定 */
table-layout: fixed;
width: 100%;
}
.col {
display: table-cell;
height: 300px;
}
.col1 {
background-color: blue;
}
.col2 {
background-color: blueviolet;
}
.col3 {
background-color: aqua;
}
.col4 {
background-color: beige;
}
.col5 {
background-color: salmon;
}
</style>
<body>
<div class="w">
<div class="col col1"></div>
<div class="col col2"></div>
<div class="col col3"></div>
<div class="col col4"></div>
<div class="col col5"></div>
</div>
</body>
分析:使用column布局,指定内容区域需要分为5列即可。
注意:浏览器兼容性问题。
<style>
.w {
/* 指定列数 */
column-count: 5;
/* 指定列与列之间的间隙,默认1em */
column-gap: 0;
}
.col {
height: 300px;
}
.col1 {
background-color: blue;
}
.col2 {
background-color: blueviolet;
}
.col3 {
background-color: aqua;
}
.col4 {
background-color: beige;
}
.col5 {
background-color: salmon;
}
</style>
<body>
<div class="w">
<div class="col col1"></div>
<div class="col col2"></div>
<div class="col col3"></div>
<div class="col col4"></div>
<div class="col col5"></div>
</div>
</body>
分析:使用flex布局十分简单,指定每一列所占空间相同即可
<style>
.w {
display: flex;
}
.col {
height: 300px;
flex: 1;
}
.col1 {
background-color: blue;
}
.col2 {
background-color: blueviolet;
}
.col3 {
background-color: aqua;
}
.col4 {
background-color: beige;
}
.col5 {
background-color: salmon;
}
</style>
<body>
<div class="w">
<div class="col col1"></div>
<div class="col col2"></div>
<div class="col col3"></div>
<div class="col col4"></div>
<div class="col col5"></div>
</div>
</body>
</html>
所谓多列等高布局,就是多类内容可能不一样,但是保证每一列的高度是相同的,这个高度应该由内容最多的那一列决定。
效果图如下:
分析:父元素设置display: table,子元素设置display: table-cell,这样布局就是按照表格行为布局,表格单元格默认等高。
<style>
.w {
display: table;
}
.col {
display: table-cell;
width: 20%;
}
.col1 {
background-color: blue;
}
.col2 {
background-color: blueviolet;
}
.col3 {
background-color: aqua;
}
.col4 {
background-color: beige;
}
.col5 {
background-color: salmon;
}
</style>
<body>
<div class="w">
<div class="col col1">啊啊啊啊啊啊啊啊啊啊啊啊</div>
<div class="col col2">啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊</div>
<div class="col col3">啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊</div>
<div class="col col4"></div>
<div class="col col5">啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊</div>
</div>
</body>
分析:默认情况下,display: flex的元素align-items属性值为stretch,如果项目未设置高度或设为auto,将占满整个容器的高度。
<style>
.w {
display: flex;
}
.col {
flex: 1;
}
.col1 {
background-color: blue;
}
.col2 {
background-color: blueviolet;
}
.col3 {
background-color: aqua;
}
.col4 {
background-color: beige;
}
.col5 {
background-color: salmon;
}
</style>
<body>
<div class="w">
<div class="col col1">啊啊啊啊啊啊啊啊啊啊啊啊</div>
<div class="col col2">啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊</div>
<div class="col col3">啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊</div>
<div class="col col4"></div>
<div class="col col5">啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊</div>
</div>
</body>
所谓全屏布局,就是实现经典的头部,内容区,底部三大区域占满全屏的布局,这种布局很常见。
实现效果如下:
分析:这里采用的方案是,头部底部使用fixed定位,中间使用之前讲到的两列布局技术。
注意:头部底部可以使用header, footer标签,内容区域结构与布局都是多种多样的。
<style>
html, body {
margin: 0;
overflow: hidden;
}
.header {
position: fixed;
left: 0;
top: 0;
right: 0;
height: 100px;
background-color: salmon;
}
.w {
position: fixed;
left: 0;
right: 0;
top: 100px;
bottom: 100px;
overflow: auto;
background-color: palevioletred;
}
.w .l {
width: 400px;
/* height: 100%; */
position: fixed;
left: 0;
top: 100px;
bottom: 100px;
background-color: greenyellow;
}
.w .r {
position: fixed;
left: 400px;
right: 0;
top: 100px;
bottom: 100px;
background-color: blueviolet;
}
.footer {
position: fixed;
left: 0;
right: 0;
bottom: 0;
height: 100px;
background-color: goldenrod;
}
</style>
<body>
<div class="header"></div>
<div class="w">
<div class="l"></div>
<div class="r"></div>
</div>
<div class="footer"></div>
</body>
本篇文章总结了一些常见布局的实现方案,css布局的实现方案很多,需要我们平时多去积累,选择合适的方案。
最后,希望随着时间的推移,兼容性不再成为我们技术实现的障碍,愿世界越来越美好。
最后送福利了,自己是从事了五年的前端工程师,整理了一份最全面前端学习资料,只要私信:“前端"等3秒后即可获取地址,
里面概括应用网站开发,css,html,JavaScript,jQuery,Ajax,node,angular等。等多个知识点高级进阶干货的相关视频资料,等你来拿
网站的布局是一个网站设计的根本,CSS的Grid布局已经成为了未来网站布局的基本方式。
今天这篇文章我们通过图文,一起看看如何自己实现Grid布局方式。
CSS
首先我们看看最基本的Grid布局是什么样的,HTML页面的代码如下所示。
HTML代码
然后设置其CSS属性,这里主要展示容器的CSS属性,给子元素添加的color属性就不在这里展示了。
CSS属性
在页面上看到的效果如下,目前因为没有对子div元素做任何设置,会自动将子div沿垂直方向排列。
页面效果
为了让外层的div(wrapper)为一个网格容器,需要设置其行数和列数,就像一个表格一样。
此时就需要用到grid-template-columns和grid-template-rows两个属性值。
grid-template-columns
用于设置网格容器的列属性,其实就相当于列的宽度。当我们需要几列展示时,就设置几个值,这个属性可以接收具体数值比如100px,也可以接收百分比值,表示占据容器的宽度。
需要注意的是:当给容器设定了宽度时,grid-template-columns设定的百分比值是以容器的宽度值为基础计算的。如果未设置宽度时,会一直向上追溯到设置了宽度的父容器,直到body元素。
比如我们设置了以下的CSS属性。
CSS属性
可以看出三列宽度加起来的百分比值为120%,而且wrapper容器并未设置宽度,会一直向上追溯到body元素,这样三列的总宽度已经超过了body的宽度,因此会出现滚动条。
页面效果
grid-template-rows
用于设置网格容器的行属性,其实就相当于行的高度,其特性与grid-template-columns属性类似。
下面简单修改grid-template-columns和grid-template-rows两个属性的值。
CSS值
得到的效果图如下所示。
效果图
接下来我们看看别的情况,通过CSS属性设置3*3的网格。
CSS属性
在页面上的呈现方式如下所示。
页面呈现
从页面上看我们看不出有什么问题,但是打开控制台后可以发现,这个网格已经占据了3*3的空间。它后面的元素只能排列在所有的网格后面。
页面实际情况
当我们需要得到特殊的排列方式,比如占满整行,占满整列,二三行合并等等。
这就需要用到grid-column和grid-row属性,表示行网线和列网线的序号。通过设置start和end值,来进行网格的合并。
网线序号
我们重新给wrapper容器内部的div添加class类。
HTML代码
然后添加以下的CSS代码,给不同的网格特定的行号和列号。
CSS代码
最终得到的效果图如下所示。
页面效果图
今天这篇文章介绍了CSS中Grid布局的基础知识,应该可以很快掌握,其他的复杂点的网格布局大家也可以自己去尝试。
载说明:原创不易,未经授权,谢绝任何形式的转载
布局是减少代码重复并创建易于维护和专业外观的应用程序的重要模式。如果您正在使用Nuxt,它提供了一个优雅的解决方案。但不幸的是,在Vue中,官方文档根本没有提到它们。这经常导致对于应该在多个应用程序中相似的问题而言,采用次优和不太正规的解决方案。
经过多次尝试,我总结出了一种既有效又无需烦恼地扩展的架构。让我用一个小的概念验证来演示一下。
首先,让我们确定一些我们的布局架构需要满足的规则:
我们需要在页面之间进行导航,这就是为什么我们要设置vue-router。 Vue-cli 和 vite 脚手架在创建新项目时提供了包含它的选项,但如果你不是从头开始,以下是安装它的步骤。
安装 vue-router 依赖
npm i -D vue-router@4
声明路由
const routes = [
{ path: "/", component: () => import("./pages/HomePage.vue") },
{ path: "/explore", component: () => import("./pages/ExplorePage.vue") },
];
导入项目
import { createApp } from "vue";
import { createRouter, createWebHashHistory } from "vue-router";
import App from "./App.vue";
import routes from "./routes.ts"
const router = createRouter({
history: createWebHashHistory(),
routes,
});
const app = createApp(App);
app.use(router);
app.mount("#app");
最后,更新App.vue文件,只包含一个 router-view 标签。
<template>
<router-view />
</template>
我们现在可以在两个页面之间导航了,但这并不令人兴奋,因为它们目前是空的。让我们改变这种情况。
我们将创建以下页面:首页、Explore、文章和404。还有三种布局:三列、两列和空白。
主页是每个流行社交网络都使用的典型三栏布局。第一栏包含应用程序的标志和导航,这在使用此布局的每个页面上都保持不变。底部右侧的页脚也是如此。主要内容和侧边栏小部件在每个页面上都会有所变化。
让我们从 HomePage.vue 组件开始实施。
<script setup lang="ts">
import ThreeColumnLayout from "../layouts/ThreeColumnLayout.vue";
import ArticleCard from "../components/ArticleCard.vue";
import WidgetFriendSuggestions from "../components/WidgetFriendSuggestions.vue";
import useArticles from "../composables/useArticles";
const articles = useArticles().getArticles();
</script>
<template>
<ThreeColumnLayout>
<h2 class="text-3xl font-bold mb-4">Homepage content</h2>
<ArticleCard v-for="article in articles" :article="article" />
<template #aside>
<WidgetFriendSuggestions />
</template>
</ThreeColumnLayout>
</template>
我们将很快实现一个 ThreeColumnLayout 组件。默认插槽包含一个标题和一系列文章,这些文章是页面的主要内容。此外,我们还有一个名为 aside 的具名插槽,用于声明一个小部件。
按照通常的约定, ThreeColumnLayout 组件被放置在 /layouts 文件夹中。它将使用网格容器,并利用 grid-template-areas 来创建一个三列布局。
布局的实现细节应该是该组件的关注点,而不是页面的关注点。可以使用flexbox、网格系统或任何其他技术来实现。如果使用全宽、盒状或流体布局,同样适用。
这个布局有3列
<script setup>
import AppNavigation from "../components/AppNavigation.vue";
import AppFooter from "../components/AppFooter.vue";
import AppLogo from "../components/AppLogo.vue";
</script>
<template>
<div class="three-column-layout">
<header>
<AppLogo />
<AppNavigation />
</header>
<main>
<slot />
</main>
<aside>
<slot name="aside" />
<AppFooter />
</aside>
</div>
</template>
<style scoped lang="scss">
.three-column-layout {
display: grid;
grid-template-areas:
"header"
"main"
"aside";
header {
grid-area: header;
margin-top: 30px;
}
main {
grid-area: main;
margin-top: 10px;
padding: 20px;
}
aside {
grid-area: aside;
margin-top: 10px;
padding: 20px;
}
@media (min-width: 768px) {
grid-template-columns: 1fr 3fr 1fr;
grid-template-areas: "header main aside";
}
}
</style>
创建一个具有相同布局的新页面将展示出这种方法的简洁性。
文章页面还将在默认插槽中包含独特的内容,并在侧边栏上添加一个额外的小部件:
<script setup>
import ThreeColumnLayout from "../layouts/ThreeColumnLayout.vue";
import WidgetRelatedContent from "../components/WidgetRelatedContent.vue";
import WidgetFriendSuggestions from "../components/WidgetFriendSuggestions.vue";
import { useRoute } from "vue-router";
import useArticles from "../composables/useArticles";
const article = useArticles().getArticle(useRoute().params.id);
</script>
<template>
<ThreeColumnLayout>
<h2 class="text-3xl font-bold mb-4">{{ article.title }}</h2>
<div class="max-w-md" v-html="article.description"></div>
<template #aside>
<WidgetFriendSuggestions />
<WidgetRelatedContent />
</template>
</ThreeColumnLayout>
</template>
对于探索页面(Explore),我们将创建一个两列布局。第一列将与三列布局相同,但主要部分将占据屏幕的其余部分,并在底部放置页脚。
这次的实现看起来与之前的并没有太大的区别。但是这次我们使用 flex 和 flex-basis 只是为了展示一种不同的创建CSS布局的方式。在实际情况中,所有的实现都应该使用相同的技术。
<script setup>
import AppNavigation from "../components/AppNavigation.vue";
import AppLogo from "../components/AppLogo.vue";
import AppFooter from "../components/AppFooter.vue";
</script>
<template>
<div class="two-column-layout">
<header>
<AppLogo />
<AppNavigation />
</header>
<main>
<slot />
<AppFooter />
</main>
</div>
</template>
<style scoped>
.two-column-layout {
display: flex;
@media (max-width: 768px) {
flex-direction: column;
}
}
header {
flex-basis: 20%;
margin-top: 30px;
}
main {
flex-basis: 80%;
margin-top: 10px;
padding: 20px;
}
</style>
使用这种布局的探索页面非常简单
<script setup>
import TwoColumnLayout from "../layouts/TwoColumnLayout.vue";
import ExploreItem from "../components/ExploreItem.vue";
import useArticles from "../composables/useArticles";
const articles = useArticles().getExploreArticles();
</script>
<template>
<TwoColumnLayout>
<h2 class="text-3xl font-bold mb-12">
Latest content on <a target="_blank" href="https://dev.to/">Dev.to</a>
</h2>
<div class="grid lg:grid-cols-3 gap-6">
<ExploreItem v-for="article in articles" :article="article" />
</div>
</TwoColumnLayout>
</template>
最后,让我们创建一个可以用于404页面的空白全页布局。
<template>
<main class="container my-24 px-6 mx-auto">
<slot />
</main>
</template>
即使实现简单,只使用一个居中容器(这次使用tailwind.css),使用布局仍然很重要。
这样我们可以保持页面组件的简洁,并确保使用此布局的多个页面外观和行为一致。
<script setup>
import BlankLayout from "../layouts/BlankLayout.vue";
import PageNotFound from "../components/PageNotFound.vue";
</script>
<template>
<BlankLayout>
<PageNotFound />
</BlankLayout>
</template>
布局是减少样板代码和保持专业外观的重要工具。结合完善的文件夹结构,可以创建一个让每个人都喜欢使用的代码库。
由于文章内容篇幅有限,今天的内容就分享到这里,文章结尾,我想提醒您,文章的创作不易,如果您喜欢我的分享,请别忘了点赞和转发,让更多有需要的人看到。同时,如果您想获取更多前端技术的知识,欢迎关注我,您的支持将是我分享最大的动力。我会持续输出更多内容,敬请期待。
*请认真填写需求信息,我们会在24小时内与您取得联系。