本文适用读者范围
适用前端初学者,尤其是移动端转大前端,平时工作weex和rn 为主,但迟迟找不到css布局感觉的。读了这篇文章应该很快就能上手工作了。介绍的东西都是平时移动端开发中常见的。有兴趣的可以再根据文中的内容自行拓展。
w3cSchool真的是垃圾,你看那个css字典,看完了也是找不到任何布局感觉的。 不如看这篇快速入门以后先上手快速开发,然后以点到面再拓展细节。
快速理解css中的布局重要概念
如何快速理解盒模型
<div class="box"></div>
.box {
width: 100px;
height: 100px;
border: 10px solid blue;
padding: 30px;
margin: 40px;
background: yellow;
}

效果如下;

默认情况下width属性定义的是内容的宽度,不包含边距、边框
width的计算方式是由box-sizing属性来定义的,如果设置一个元素为box-sizing: border-box; ,元素的内边距和边框就会包含在width宽度内。
这里与android 其实是不一样的,android中一个view的宽度高度 其实是包含了padding 但是不包含margin的
块元素和行内元素
有android基础的 理解这个就很快了。 块元素 就是 一个vertical属性的linearylayout 而行内元素 则是一个hor 属性的LinearLayout 无非就是 一个子元素 垂直排列 另外一个水平排列罢了。
块元素的特点
-
每个块元素都从新的一行开始,独占一行
-
元素的高度、宽度、行高以及顶和底边距等属性都可设置
-
默认的高度与父元素的宽度一致,即width默认为100%
-
可以容纳行内元素和其他块元素
行内元素的特点:
-
和其他行内元素都在一行上
-
元素的高度、宽度、行高及顶部和底部边距等属性不可设置
-
元素不能设置高度,宽度就是它包含的文字或图片的宽度
-
行内元素只能容纳文本或者其他行内元素
在CSS中将行内元素可以通过display: block设置为以块元素的方式显示,我们还可以继续设置该元素的长宽等原本不能设置的属性。同样,我们也可以设置块元素的display属性为display: inline,这样块元素就可以再同一行显示了
android中的visiable 以及 gone 属性 在css中也有对应
当一个元素的display属性被设为none时,该元素不会被渲染,也不会占位,就像不存在一样。对布局不会产生任何影响。它和visibility属性不一样。把display设置成none不会保留元素本该显示的空间,但是visibility: hidden;还会保留
最后一种重要的display属性
display: inline-block修饰的元素称之为行内块元素,它们会像行内元素一样在同一行显示,又可以像块元素一样设置高、宽、行高、边距。
叠加布局
所谓叠加布局,在移动端就是简单的两个view 叠加在一起,有重合的部分。在android中 我们经常在framelayout或者相对布局layout中 实现这种效果。
如图所示:

源码如下,我们只要谨记 关键字是 position: relative 即可。
<div>
<div class="r1"></div>
<div class="r2"></div>
</div>
.r1{
height: 200px;
width: 50%;
position: relative;
background: red;
}
.r2{
height: 200px;
width: 70%;
position: relative;
background: blue;
top:-50px;
left:20px;
}
固定位置的布局
类似在android中,我们往往需要 单独写一个window ,不跟随主xml文件。这样不管我的主界面怎么滑动,我这个单独的窗口都是固定在屏幕的一个位置。

代码:
.t1 {
width: 100%;
height: 2000px;
background: red;
}
.t2 {
/* 就是这个fixed起到作用而已 */
position: fixed;
bottom: 50%;
right: 0;
width: 200px;
background-color: white;
}
跟随父布局移动的相对布局。

<div class="t1">
<div class="t2">随便你怎么滑动,我都在我父元素的内部保持不动</div>
</div>
.t1 {
width: 100%;
height: 200px;
background: red;
/* 前面不要遗漏这个 否则你子布局的那些位置属性就是相对于整个窗口而言了 */
position: relative;
}
.t2 {
/* 就是这个absolute起到作用而已 但是他需要他的父元素 position 为 非static的 也就是说
父元素的position不能为默认值 */
position: absolute;
bottom: 20px;
left: 10px;
width: 200px;
background-color: green;
}
如果把父布局的position删除以后 就变成

float- 变更图层的覆盖关系
<div>
<div class="t1">我本来应该在下面 被覆盖</div>
<div class="t2">我本来应该在上面 覆盖下面</div>
</div>
例如这样的div 因为t2 这个div 是在t1 后面写的,所以理应t2 在t1之上。
.t1 {
width: 50px;
height: 200px;
background: red;
/* float: left; */
}
.t2 {
width: 200px;
height: 200px;
background: yellowgreen;
}

如果我们把上面t1 注释掉的那行代码 打开:
效果马上就变成了 t1 覆盖到t2 上面了。

这里当然还可以用 clear 属性 来清除这种浮动
.t2 {
width: 200px;
height: 200px;
background: yellowgreen;
clear: left
}
用float 来体会下 啥叫 脱离文档流
<div class="parent">
<div class="t1">1</div>
<div class="t2">2</div>
<div class="t3">3</div>
</div>
.parent {
/* display: inline; */
background: red;
/* height: 200px; */
}
.t1 {
width: 200px;
height: 400px;
background: yellowgreen;
float: left;
}
.t2 {
width: 200px;
height: 400px;
background: wheat;
float: left;
}
.t3 {
width: 200px;
height: 400px;
background: green;
float: left;
}

稍微改一下 增加一行代码 即可 让父布局高度正常
<div class="parent">
<div class="t1">1</div>
<div class="t2">2</div>
<div class="t3">3</div>
<!-- 清除浮动 即可让父布局 有高度 -->
<div style="clear:both;"></div>
</div>
文字环绕效果
这可能是css中 为数不多的,实现起来 比android里面要方便多的 效果了。 实现原理为:
如果该元素的下一个兄弟元素中有内联元素(通常是文字),则会围绕该元素显示,形成类似"文字围绕图片"的效果。即虽然浮动会让元素脱离文档流,但是文本内容会受到浮动元素的影响。
<div>
<div class="parent">
<div class="t1"></div>
<div
class="t2"
>23123123123123123131231231231231231231231231312312312312312313123123123123123131231231312312312312312313123123123123123131231231231231231312313131231231231231231231231231231sdasdasdasdasdasda13131231231231231231231231231231sdasdasdasdasdasda</div>
</div>
</div>

.parent {
text-align: center;
width: 300px;
background: blueviolet;
}
.t1 {
width: 100px;
height: 100px;
background: red;
/* 一个float 就解决了所有问题 真是比android的布局dsl方便啊 */
float: left;
}
.t2 {
width: 200px;
height: 200px;
background: yellowgreen;
/* 下面这个保证div中的文字 显示不下就自动换行 */
white-space: normal;
word-break: break-all;
overflow: hidden;
}
img外面包裹div
<div class="test">
<img
src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1583071176313&di=5d94f8d41a598ec2e4a3a2e80de0dd14&imgtype=0&src=http%3A%2F%2Fn.sinaimg.cn%2Fsinacn20107%2F571%2Fw640h731%2F20200229%2Fe016-iqfqmas5577811.jpg"
/>
</div>
.test {
width: 500px;
background: red;
}
img {
width: 150px;
height: 150px;
/* vertical-align: middle; */
}
看看效果

为什么下面有个空白?这是什么鬼?
图片的 baseline 是图片的下缘,它和所在行的 baseline 是对齐的,而所在行的 baseline 离父元素的下边是有距离的(这个涉及到字体知识),这个距离就是你看到的空隙。
这个问题有很多种解法
通常推荐
img {
width: 150px;
height: 150px;
/* 这种解法比较常用 一般行内元素 都可以考虑用这种方式对齐 */
vertical-align: middle;
}
height 与 line-height
实际上line-height 这个东西 在css布局中 是个很麻烦的属性(其实从这里就能看出来css是一门多么愚蠢的dsl语言),这里只说一些平时我们应该注意的地方。
<div>
<div class="test1">
test1
<br />test1
</div>
<br />
<br />
<div class="test2">
test2
<br />test2
</div>
</div>
.test1 {
line-height: 20px;
background-color: red;
}
.test2 {
height: 20px;
background-color: green;
}

div标签中直接写文字要注意什么?
<div>
<div class="test1">test1</div>
<br />
<br />
<div class="test2">test1</div>
</div>
.test1 {
font-size: 0;
line-height: 32px;
border: 1px solid red;
}
.test2 {
font-size: 32px;
line-height: 0;
border: 1px solid yellow;
}

单行文字垂直居中
<div>
<p class="t1">这是一行文字</p>
</div>
.t1 {
line-height: 50px;
border: 1px dashed #cccccc;
padding-left: 5px;
font-size: 12px;
}

父元素高度不固定的多行文字垂直居中

<p class="t1">
<span style="font-size:12px;">
多行文字的第一行
<br />这里是第二行,用来测试多行的显示效果。
</span>
</p>
.t1 {
border: 1px dashed #cccccc;
padding-left: 5px;
}
.t1 span {
display: inline-block;
vertical-align: middle;
}
快速学习weex和RN中常用的布局技巧
这些布局效果,在移动原生开发中非常常见,但是如果用传统的css布局属性来写会比较麻烦,使用比较新潮的flex来布局效果则特别好,且简单.恰好 weex和rn 都对flex的支持比较好.所以这里 重点介绍一下flex布局的实际应用
垂直居中
<div class="dad">
<div class="son"></div>
</div>
.dad {
/* 重点就是要开启这个flex */
display: flex;
/* 然后设置居中对齐 */
justify-content: center;
/* 设置子容器如何沿交叉轴排列 */
align-items: center;
background: red;
width: 100%;
height: 200px;
}
.son {
width: 100px;
height: 100px;
background: green;
}

水平排列
<div class="parent">
<div class="t1"></div>
<div class="t2"></div>
<div class="t3"></div>
</div>
.parent {
/* 重点就是要开启这个flex */
display: flex;
/* 然后设置从左到右 */
justify-content: flex-start;
/* 设置子容器如何沿交叉轴排列 其实就是纵轴排列的顺序 */
align-items: center;
background: red;
width: 100%;
height: 200px;
}
.t1 {
width: 100px;
height: 100px;
background: green;
}
.t2 {
width: 100px;
height: 100px;
background: blueviolet;
}
.t3 {
width: 100px;
height: 100px;
background: chocolate;
}

当然还有flex-end 属性 可以自己看看效果
首尾间距+子元素之间留相等间距
首元素和尾元素 与父元素的间距 是 子元素之间间距的一半

justify-content: space-around;
首尾不留间距

justify-content: space-between;
纵向对齐的几种方式

align-items: flex-start;

align-items: flex-end;
子元素按比例分割布局

.t1 {
flex: 1;
/* width: 100px; */
height: 100px;
background: green;
}
.t2 {
flex: 2;
/* width: 100px; */
height: 200px;
background: blueviolet;
}
.t3 {
flex: 3;
/* width: 100px; */
height: 300px;
background: chocolate;
}
变更主轴方向
前面我们讲的主要是 横向对应 justify-content 纵向对应 align-items ,这其实是默认了横向为主轴, 纵向为交叉轴。 某些情况下 我们可以更改主轴的设定 来达到其他的效果
.parent {
display: flex;
justify-content: center;
align-items: stretch;
// 设置主轴为 列 将白了就是纵向分割
flex-direction: column;
background: red;
width: 100%;
height: 200px;
}
.t1 {
flex: 1;
/* width: 100px; */
/* height: 100px; */
background: green;
}
.t2 {
flex: 2;
/* width: 100px; */
/* height: 200px; */
background: blueviolet;
}
.t3 {
flex: 3;
/* width: 100px; */
/* height: 300px; */
background: chocolate;
}

横扑布局自动换行
如图,第三个展示不下就自动换行展示

.parent {
display: flex;
flex-wrap: wrap;
background: red;
width: 500px;
height: 200px;
}
.t1 {
width: 100px;
height: 100px;
background: green;
}
.t2 {
width: 200px;
height: 100px;
background: black;
}
.t3 {
width: 300px;
height: 100px;
background: chocolate;
}