等高布局
让两列不同高度的容器一样高,高度不够的部分自己撑起来。
<div class="main">
<div>
<p>测试内容</p>
<p>测试内容</p>
<p>测试内容</p>
<p>测试内容</p>
</div>
<div>
<p>测试内容</p>
<p>测试内容</p>
<p>测试内容</p>
<p>测试内容</p>
<p>测试内容</p>
<p>测试内容</p>
</div>
</div>
可以使用浮动:
.main{
width:500px;
background:skyblue;
overflow: hidden;
}
.main div{
width:100px;
background:pink;
float:left;
}
.main div:nth-of-type(2){
float:right;
}
这里给父元素设置overflow: hidden,是为了触发BFC,来让父元素包裹浮动子元素。关于BFC在这里总结过。
如果用flex就更为简洁了:
.main{
width:500px;
background:skyblue;
display: flex;
justify-content: space-between;
}
.main div{
width:100px;
background:pink;
}
两列与三列布局
这种布局就是两边两列固定宽度,中间一列自适应。
<div class="main">
<div class="col1"></div>
<div class="col2"></div>
<div class="col3"></div>
</div>
用flex非常简单,给中间一列设置flex-grow: 1占满剩余空间即可,关于flex布局详情,可以看阮一峰大佬的博客。
.main{
height:100vh;
background:skyblue;
display: flex;
}
.col1{
width:200px;
background:pink;
}
.col2{
flex-grow: 1;
background:springgreen;
}
.col3{
width:100px;
background: tomato;
}
Sticky Footer布局
粘性页脚布局,当内容区高度不够时,页脚固定在底部,当内容变长时,页脚也会向下移动。
<div class="header"></div>
<div class="content">
<p>测试内容</p>
<p>测试内容</p>
<p>测试内容</p>
<p>测试内容</p>
<p>测试内容</p>
</div>
<div class="footer"></div>
.main{
min-height:100vh;
display: flex;
flex-direction: column;
}
.main .header{
height:100px;
background:pink;
}
.main .content{
flex-grow: 1;
}
.main .footer{
height:100px;
background:skyblue;
}
这也是利用flex布局,给中间的内容区域设置flex-grow: 1。
栅格布局
这里先对grid先做一个简单的总结,详细看阮一峰大佬博客。grid布局和flex类似,都有容器和项目的概念,flex布局是轴线布局,只能指定项目针对轴线的位置,属于一维布局;grid将容器分为行和列,产生单元格,然后指定项目所在的单元格,属于二维布局。
-
容器属性
- grid-template-columns 定义每一列的列宽
- grid-template-rows 定义每一行的行高
- auto-fill关键字 容器尽可能多的容纳项目
- grid-row-gap 设置行与行的间隔
- grid-column-gap 设置列的间隔
- grid-template-areas 定义区域
- justify-content 内容区域水平排列(左中右)
- align-content 内容区域垂直排列(左中右)
-
项目属性
这四个属性主要指定项目的四个边框来确定项目的位置,
- grid-column-start 左边框所在的垂直网格线
-
grid-column-end 右边框所在的垂直网格线
- grid-row-start 上边框所在的垂直网格线
-
grid-row-end 下边框所在的垂直网格线
- grid-area 指定项目在哪一个区域
接下来用上述属性做一个简单的栅格布局:
<div class="row">
<div class="col-6">1</div>
<div class="col-3">2</div>
<div class="col-4">3</div>
<div class="col-5">4</div>
</div>
.row{
background:skyblue;
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: 50px;
grid-auto-rows: 50px;
}
.row div{
background:pink;
border:1px black solid;
}
.row .col-1{
grid-area: auto/auto/auto/span 1;
}
.row .col-2{
grid-area: auto/auto/auto/span 2;
}
.row .col-3{
grid-area: auto/auto/auto/span 3;
}
.row .col-4{
grid-area: auto/auto/auto/span 4;
}
.row .col-5{
grid-area: auto/auto/auto/span 5;
}
.row .col-6{
grid-area: auto/auto/auto/span 6;
}
.row .col-7{
grid-area: auto/auto/auto/span 7;
}
.row .col-8{
grid-area: auto/auto/auto/span 8;
}
.row .col-9{
grid-area: auto/auto/auto/span 9;
}
.row .col-10{
grid-area: auto/auto/auto/span 10;
}
.row .col-11{
grid-area: auto/auto/auto/span 11;
}
.row .col-12{
grid-area: auto/auto/auto/span 12;
}
这里设置了12列,每一行高50px,每一个项目设置不同的类名,占据不同的栅格。
容器自适应行列布局
表格展示时,行或者列自适应展示:
<div class="main">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
</div>
.main{
height:300px;
background:skyblue;
display: inline-grid;
grid-template-rows: repeat(3, 1fr);
grid-auto-flow: column;
grid-auto-columns: 100px;
gap:5px;
}
.main div{
background:pink;
}
接下来利用grid布局做一个小案例,
<div class="main">
<div>a1</div>
<div>a2</div>
<div>a3</div>
<div>a4</div>
<div>a5</div>
<div>a6</div>
<div>a7</div>
</div>
.main{
width:300px;
height: 400px;
margin: 0 auto;
background:skyblue;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: repeat(4, 1fr);
grid-template-areas:
"a1 a3 a3"
"a2 a3 a3"
"a4 a4 a5"
"a6 a7 a7";
gap:5px;
}
.main div{
background:pink;
}
.main div:nth-of-type(1){
grid-area: a1;
}
.main div:nth-of-type(2){
grid-area: a2;
}
.main div:nth-of-type(3){
grid-area: a3;
}
.main div:nth-of-type(4){
grid-area: a4;
}
.main div:nth-of-type(5){
grid-area: a5;
}
.main div:nth-of-type(6){
grid-area: a6;
}
.main div:nth-of-type(7){
grid-area: a7;
}
移动端适配:像素、rem和vw
有这样三个概念要熟悉下:
- 物理像素:设备屏幕实际拥有的像素点。比如iPhone 6的屏幕在宽度方向有750个像素点,高度方向有1334个像素点,所以iPhone 6 总共有750*1334个物理像素
- 逻辑像素: 也叫“设备独立像素”(Device Independent Pixel, DIP),可以理解为反映在CSS/JS代码里的像素点数。
- 设备像素比: 一个设备的物理像素与逻辑像素之比
以常用的iPhone6为例,它的物理像素就是750X1334,而它的逻辑像素就是375X667,它的物理像素比就是2。
在移动端不同的屏幕尺寸时,需要将页面等比方法或者等比缩小,就需要动态的计算像素。em就是根据font-size来设置计算大小的,rem,rem的值就是根据根元素html的font-size来计算的,可以据此来动态的计算body的font-size来,动态计算根节点的font-size,比如设置1rem=100px,有两种,
-
js动态计算
let width = document.documentElement.clientWidth; document.documentElement.style.fontsize = 100 * (width / 640) + 'px' -
vw动态计算
vw就是页面将可视区的宽度和高度分划分为100vw和100vh,如果在375像素的屏幕下(iphone6下),设置成1rem为100px,可以这样计算:100*100/375 = 26.67
同样也可以使用vscode插件,比如px to rem或者px to vw来设置编辑器也可以。
响应式布局
实现响应式布局,就要用到媒体查询。详细的api可以查看mdn。
其常用的就是定位媒体特性,给定user agent输出设备或环境的特定特征,也就是定义一个约束范围,达到条件时就渲染指定的css样式。
@media (max-width: 300px) { ... }
只有当浏览器宽度小于等于300px时,css样式才会生效。
media可以结合栅格布局,很好的实现响应式栅格系统,接下来实现一个简易的栅格系统:
<div class="row">
<div class="col-xxl-3 col-lg-4 col-sm-6">col-1</div>
<div class="col-xxl-3 col-lg-4 col-sm-6">col-2</div>
<div class="col-xxl-3 col-lg-4 col-sm-6">col-3</div>
<div class="col-xxl-3 col-lg-4 col-sm-6">col-4</div>
<div class="col-xxl-3 col-lg-4 col-sm-6">col-5</div>
<div class="col-xxl-3 col-lg-4 col-sm-6">col-6</div>
<div class="col-xxl-3 col-lg-4 col-sm-6">col-7</div>
<div class="col-xxl-3 col-lg-4 col-sm-6">col-8</div>
<div class="col-xxl-3 col-lg-4 col-sm-6">col-9</div>
<div class="col-xxl-3 col-lg-4 col-sm-6">col-10</div>
<div class="col-xxl-3 col-lg-4 col-sm-6">col-11</div>
<div class="col-xxl-3 col-lg-4 col-sm-6">col-12</div>
</div>
.row{
background:skyblue;
display: grid;
grid-template-columns: repeat(12, 1fr);
grid-template-rows: 50px;
grid-auto-rows: 50px;
}
.row div{
background:pink;
border:1px black solid;
grid-area: auto/auto/auto/span 12;
}
.row .col-1{
grid-area: auto/auto/auto/span 1;
}
.row .col-2{
grid-area: auto/auto/auto/span 2;
}
.row .col-3{
grid-area: auto/auto/auto/span 3;
}
.row .col-4{
grid-area: auto/auto/auto/span 4;
}
.row .col-5{
grid-area: auto/auto/auto/span 5;
}
.row .col-6{
grid-area: auto/auto/auto/span 6;
}
.row .col-7{
grid-area: auto/auto/auto/span 7;
}
.row .col-8{
grid-area: auto/auto/auto/span 8;
}
.row .col-9{
grid-area: auto/auto/auto/span 9;
}
.row .col-10{
grid-area: auto/auto/auto/span 10;
}
.row .col-11{
grid-area: auto/auto/auto/span 11;
}
.row .col-12{
grid-area: auto/auto/auto/span 12;
}
@media (min-width: 576px){
.row .col-sm-1{
grid-area: auto/auto/auto/span 1;
}
.row .col-sm-2{
grid-area: auto/auto/auto/span 2;
}
.row .col-sm-3{
grid-area: auto/auto/auto/span 3;
}
.row .col-sm-4{
grid-area: auto/auto/auto/span 4;
}
.row .col-sm-5{
grid-area: auto/auto/auto/span 5;
}
.row .col-sm-6{
grid-area: auto/auto/auto/span 6;
}
.row .col-sm-7{
grid-area: auto/auto/auto/span 7;
}
.row .col-sm-8{
grid-area: auto/auto/auto/span 8;
}
.row .col-sm-9{
grid-area: auto/auto/auto/span 9;
}
.row .col-sm-10{
grid-area: auto/auto/auto/span 10;
}
.row .col-sm-11{
grid-area: auto/auto/auto/span 11;
}
.row .col-sm-12{
grid-area: auto/auto/auto/span 12;
}
}
@media (min-width: 768px){
.row .col-md-1{
grid-area: auto/auto/auto/span 1;
}
.row .col-md-2{
grid-area: auto/auto/auto/span 2;
}
.row .col-md-3{
grid-area: auto/auto/auto/span 3;
}
.row .col-md-4{
grid-area: auto/auto/auto/span 4;
}
.row .col-md-5{
grid-area: auto/auto/auto/span 5;
}
.row .col-md-6{
grid-area: auto/auto/auto/span 6;
}
.row .col-md-7{
grid-area: auto/auto/auto/span 7;
}
.row .col-md-8{
grid-area: auto/auto/auto/span 8;
}
.row .col-md-9{
grid-area: auto/auto/auto/span 9;
}
.row .col-md-10{
grid-area: auto/auto/auto/span 10;
}
.row .col-md-11{
grid-area: auto/auto/auto/span 11;
}
.row .col-md-12{
grid-area: auto/auto/auto/span 12;
}
}
@media (min-width: 992px){
.row .col-lg-1{
grid-area: auto/auto/auto/span 1;
}
.row .col-lg-2{
grid-area: auto/auto/auto/span 2;
}
.row .col-lg-3{
grid-area: auto/auto/auto/span 3;
}
.row .col-lg-4{
grid-area: auto/auto/auto/span 4;
}
.row .col-lg-5{
grid-area: auto/auto/auto/span 5;
}
.row .col-lg-6{
grid-area: auto/auto/auto/span 6;
}
.row .col-lg-7{
grid-area: auto/auto/auto/span 7;
}
.row .col-lg-8{
grid-area: auto/auto/auto/span 8;
}
.row .col-lg-9{
grid-area: auto/auto/auto/span 9;
}
.row .col-lg-10{
grid-area: auto/auto/auto/span 10;
}
.row .col-lg-11{
grid-area: auto/auto/auto/span 11;
}
.row .col-lg-12{
grid-area: auto/auto/auto/span 12;
}
}
瀑布流布局
- 横向瀑布流
使用flex布局来实现:
<div class="main">
<div class="item">
<img src="./imgs/1.jpg" alt="">
</div>
<div class="item">
<img src="./imgs/2.jpg" alt="">
</div>
<div class="item">
<img src="./imgs/3.jpg" alt="">
</div>
<div class="item">
<img src="./imgs/4.jpg" alt="">
</div>
<div class="item">
<img src="./imgs/5.jpg" alt="">
</div>
<div class="item">
<img src="./imgs/6.jpg" alt="">
</div>
</div>
.main{
display: flex;
flex-wrap: wrap;
gap: 10px;
}
.main .item{
flex-grow: 1;
height: 200px;
/* flex-basis: 200px; */
}
.main .item img{
width:100%;
height:100%;
object-fit: cover;
display: block;
}
这里再给每个图片动态设置一个flexBasis:
var items = document.querySelectorAll('.item');
for(var i=0;i<items.length;i++){
items[i].style.flexBasis = Math.random() * 200 + 200 + 'px';
}
-
竖向瀑布流
-
Multi-Columns 多栏布局
**CSS多列布局(CSS Multi-column Layout)**是一种定义了多栏布局的模块,可支持在布局中建立列(column)的数量,以及内容如何在列之间流动(flow)、列之间的间距(gap)大小,以及列的分隔线(column rules)。
详细可以查看MDN,这种比js动态计算要简单的多。
.main{ /* column-count: 4; */ column-width: 300px; column-gap: 20px; column-rule: 1px gray dashed; } h1{ column-span: all; text-align: center; } .main .item img{ width:100%; height:100%; object-fit: cover; display: block; } -
js动态计算
<div class="container"> </div> <button class="more-btn">加载更多</button>.container{ display: flex; gap: 10px; align-items: flex-start; } .item-col{ flex-basis: 300px; flex-grow: 1; } .item-box{ padding-top:10px; break-inside: avoid; } .item-box img{ width:100%; height:100%; object-fit: cover; display: block; } .more-btn{ display: block; margin: 30px auto; padding: 20px; font-size: 30px; }var container = document.querySelector('.container'); var itemBox = document.getElementsByClassName('item-box'); var moreBtn = document.querySelector('.more-btn'); var now = 0; var cols = Math.floor(window.innerWidth / 300); for(var i=0;i<cols;i++){ var itemCol = document.createElement('div'); itemCol.className = 'item-col'; container.append(itemCol); } (function(){ var _arg = arguments; if(now === 15){ return; } now++; var itemBox = document.createElement('div'); var itemImg = document.createElement('img'); itemBox.className = 'item-box'; itemImg.src = `./imgs/${now}.jpg`; itemBox.append(itemImg); itemImg.onload = function(){ minCols().append(itemBox); _arg.callee(); }; })(); function minCols(){ var itemCols = document.querySelectorAll('.item-col'); var arr = [...itemCols]; arr.sort(function(c1,c2){ return c1.offsetHeight - c2.offsetHeight; }); return arr[0]; } window.onresize = function(){ var changeCols = Math.floor(window.innerWidth / 300); if( changeCols === cols ){ return; } cols = changeCols; var itemBoxs = document.querySelectorAll('.item-box'); container.innerHTML = ''; for(var i=0;i<changeCols;i++){ var itemCol = document.createElement('div'); itemCol.className = 'item-col'; container.append(itemCol); } var itemCols = document.querySelectorAll('.item-col'); for(var i=0;i<itemBoxs.length;i++){ minCols().append(itemBoxs[i]); } }; moreBtn.onclick = function(){ var itemCols = document.querySelectorAll('.item-col'); var now = 14; (function(){ var _arg = arguments; if(now === 20){ return; } now++; var itemBox = document.createElement('div'); var itemImg = document.createElement('img'); itemBox.className = 'item-box'; itemImg.src = `./imgs/${now}.jpg`; itemBox.append(itemImg); itemImg.onload = function(){ minCols().append(itemBox); _arg.callee(); }; })(); };这里首先根据屏幕的宽度来动态计算列数,然后计算最高度低的列来放照片。核心代码就是minCols函数,他拿到所有的列,然后用offsetHeight来进行一个排序,然后返回高度最低的一列,将创建的图片放到这一列,然后通过_arg.callee()不断的重复这一过程。
-