运行结果如下:
0x6、盒子模型
元素被描绘成「矩形盒子」,这些盒子通过一个模型来描绘它的占用空间,即「盒子模型」。
如图,盒子模型通过下述四个边界来描述:
- Margin(外边距)—— 边框外的区域,外边距是透明的。
- Border(边框)—— 围绕在内边距和内容外的边框。
- Padding(内边距)—— 内容周围的区域,内边距是透明的。
- Content(内容)—— 盒子的内容,显示文本和图像。
暂且把这个大盒子称为「元素框」,设置width和height指的是内容部分宽高,设置内外边距和边框不会影响内容区域的尺寸,但是会增加元素框的总尺寸。举个例子,你定义了一个48rpx48rpx的view,但是如果你还设置了margin或padding,那么这个元素的元素框尺寸就不止48rpx48rpx了!
① box-sizing属性
如果你想设置「元素框」的宽高固定,不会因为设置了边距和边框而改变宽高,可以使用「box-sizing」来实现,该属性有下述两个可选值:
- content-box:宽高仅是内容宽高,加上padding和border,模型宽高会变大.
- border-box:以border为边界,宽高是包括边框和内边距的,设置padding模型宽高也不会变。
使用代码示例如下:
<!-- test.wxml --> <view class="view-wrapper"> <view class="view-1">元素1</view> <view class="view-2">元素2</view> </view>
/* test.wxss */ page { background: gray; } view { text-align: center; width: 240rpx; height: 240rpx; line-height: 240rpx; border: 10rpx solid white; } .view-wrapper { width: 75%; background: gold; padding: 50rpx; overflow: hidden; border: none; } .view-1 { background: greenyellow; box-sizing: content-box; float: left; } .view-2 { background: blueviolet; box-sizing: border-box; float: right; }
运行结果如下:
② 外边距合并问题
当两个或更多垂直外边距相遇时,它们将形成一个外边距,合并后的外间距高度等于两个元素中外边距高度中的较大者。
单看概念有点含糊,写个简单的例子来帮助理解(相邻元素):
<!-- test.wxml --> <view class="container"> <view class="view-1">元素1</view> <view class="view-2">元素2</view> </view>
接着设置两个样式
.view-1 { background: gold; } .view-2 { background: red; }
接着按照下述步骤修改样式:
- ① view-1设置:margin-bottom: 50rpx。
- ② 注释掉view-1的样式,view-2设置:margin-top: 10rpx。
- ③ 去掉view-1的注释。
每一步的结果如下:
如图,两个元素最后的边距是50rpx,而不是50rpx + 10rpx = 60rpx;
接着我们再来试试 负值 的情况
.view-1 { background: gold; margin-bottom: -10rpx} .view-2 { background: red; margin-top: 30rpx}
运行结果如下:
不难发现此时的外边距是20rpx,再试试负数比整数大的情况:
.view-1 { background: gold; margin-bottom: 10rpx} .view-2 { background: red; margin-top: -20rpx}
同样不难发现此时的外边距是-10rpx,再试试两个都是负数的情况:
.view-1 { background: gold; margin-bottom: -10rpx} .view-2 { background: red; margin-top: -20rpx}
此时的外边距是-20rpx,分析计算下规律:
- 一正一负,先求绝对值差(绝对值大-绝对值小),再设置正负;
- 同正同负:去绝对值大的那个,在设置正负。
如果不想面对外边距合并问题,有下述几种规避方法:
- ① 下面的元素设置绝对定位:position:absolute;
- ② 下面的元素设置下浮动:float:left;
- ③ 任意一个盒子设置为为行内块元素:dispaly:inline-block;
除了上面这种「相邻元素」会出现外边距合并问题外「父子元素」也可能会,没有内边距和边框隔开。写个简单的测试例子体验下:
<view class="view-1"> <view class="view-2">元素</view> </view>
设置两个样式,灰色背景方便对比,设置一个左边的间距方便看。
page { background: gray; } .view-1 { background: gold; } .view-2 { background: red; margin-left: 50rpx;}
接着按照下述步骤修改样式:
- ① view-2设置:margin-top:20rpx。
- ② 注释掉view-2,view-1设置:margin-top: 50rpx。
- ③ 去掉view-2的注释。
每一步的结果如下:
有下述几种方法可以规避父子元素外边距合并问题:
- ① 父元素设置内边距:padding-top:1rpx;
- ② 父元素设置:overflow: hidden;
- ③ 父元素设置边框:border:1rpx solid transparent;
关于外边距合并就说那么多吧,知道怎么规避就好,具体原因涉及到BFC(Block Formatting Context,块级格式化上下文),目前还不知道具体是啥,后面研究了再另外开一片介绍吧。
0x7、定位
让元素脱离文档流的办法是:定位,浮动或者多列布局,这里先讲解一波定位。
通过一个例子来帮助理解,先定义一个没有使用定位的页面。
<!-- test.wxml --> <view class="view-wrapper"> <view class="view-1">元素1</view> <view class="view-2">元素2</view> <view class="view-3">元素3</view> <view class="view-4">元素4</view> </view>
/* test.wxss */ view { display: inline-block; padding: 10px } .view-wrapper { background: gold; } .view-1 { background: greenyellow; } .view-2 { background: blueviolet; } .view-3 { background: orange; } .view-4 { background: pink; }
运行结果如下:
① 相对定位
相对于它在「文档流中的位置的起始点」进行移动,通过例子来体验下,这里我们为元素2添加下述样式:
position: relative; left: 50rpx; top: 50rpx;
运行结果如下:
可以看到元素2从起始点开始,左边和上面都偏移50rpx,此处有个细节:偏移前的空间依旧存在!另外,另外注意 起始点 这个字眼,元素是基于起始点进行偏移的,比如为外层元素设置一个margin-left: 50rpx; 运行后的效果如下:
② 绝对定位
完全从文档流中抽离出来,可放到页面的任何位置。把上面设置的margin-left:50rpx删掉,接着把relative; 改为 absolute;运行效果如下:
可以看到,偏移前的空间已被删除!绝对布局是这样的定位的:
「相对于它的父元素来定位」,如果父元素没有设置定位,就找父元素的父元素,依次往上,直至遇到设置了定位的父元素未知,如果没找到,就会相对于文档 body进行定位。所以这里是基于body进行定位的,我们可以试下为外层的view设置position: relative,接着运行看下效果:
购物车那种数字小红点一般就是用绝对定位实现的。另外还可以通过 z-index 属性来控制重叠排列顺序,值大的在上面。改下样式:
/* index.wxss */ .view-1 { background: greenyellow; position: absolute; left: 0rpx; } .view-2 { background: blueviolet; position: absolute; left: 108rpx; top: 20rpx; } .view-3 { background: orange; position: absolute; top: 100rpx; left: 20rpx } .view-4 { background: pink; position: absolute; left: 100rpx; top: 80rpx; }
运行结果如下:
加入index-z属性,控制重叠排列顺序:
/* index.wxss */ .view-1 { background: greenyellow; position: absolute; left: 0rpx; z-index: 50; } .view-2 { background: blueviolet; position: absolute; left: 108rpx; top: 20rpx; z-index: 30; } .view-3 { background: orange; position: absolute; top: 100rpx; left: 20rpx; z-index: 20; } .view-4 { background: pink; position: absolute; left: 100rpx; top: 80rpx; z-index: 10; }
运行结果如下:
③ 固定定位
fixed:和absolute类似,超出屏幕的时候也是固定,参考的是窗口,常用于需要悬浮固定的场景。比如商品详情页,有个一直固定在底部的购买按钮,页面内容可以正常滚动;还有基于窗口的悬浮框等。