CSS布局、盒模型、浮动、定位

144 阅读20分钟

PC端、移动端的适配原则

1681364852(1).png

大部分网站自适应浏览器分辨率,因此在不同设备下分辨率是不同的,如何让不同设备下的网页看起来一样呢?或者说让不同的设备自适应不同的浏览器呢?

假如要自适应浏览器有可能是要被拉伸,图形发生变形

还有一种方式就是根据不同的分辨率做出等比的缩放,我们可以使用rem单位或者使用vw单位去实现

一套代码实现PC端、移动端

1681365635(1).png

同一套代码在不同设备下使用,响应式布局主要是使用了css中的@media

CSS的发展方向

大体上CSS的学习可以朝着三个方向进行研究,分别是:特效、工程化、布局。比如说特效:可以学习动画、3D、渐变等;工程化:可以学习sass、less、postcss等;布局:可以学习flex、grid、响应式等

相对长度单位

相对长度单位相对于其他一些东西,比如父元素的字体大小,或者视图端口的大小。使用相对单位的好处是,经过一些仔细的规划,您可以使文本或其他元素的大小与页面上的其他内容相对应。以下列出了常见相对单位。

单位名称
em在font-size中使用是相对于父元素的字体大小,在其他属性中使用是相对于自身的字体大小
ex字符“x”的高度
ch数字“0”的宽度
rem根元素的字体大小
lh元素的line-height
vw视窗宽度的1%
vh视窗高度的1%
vmin视窗较小尺寸的1%
vmax视图大尺寸的1%

颜色

RGB颜色

在CSS中,可以使用公式rgb(red, green, blue)将颜色指定为RGB值。每个参数 (red、green 以及 blue) 定义了 0 到 255 之间的颜色强度。

要显示黑色,请将所有颜色参数设置为 0,如下所示:rgb(0, 0, 0);要显示白色,请将所有颜色参数设置为 255

图片描述

HEX

在CSS中,可以使用#rrggbb格式的十六进制值指定颜色。其中 rr(红色)、gg(绿色)和 bb(蓝色)是介于 00 和 ff 之间的十六进制值(与十进制 0-255 相同)。

图片描述

HSL颜色

在CSS中,可以使用色相、饱和度和明度(HSL)来指定颜色,格式如下:hsla(hue, saturation, lightness)

色相(hue)是色轮上从 0 到 360 的度数。0 是红色,120 是绿色,240 是蓝色。饱和度(saturation)是一个百分比值,0% 表示灰色阴影,而 100% 是全色。亮度(lightness)也是百分比,0% 是黑色,50% 是既不明也不暗,100%是白色。
图片描述

设计图源文件

通常我们认知中的JPG、PNG、GIF等图片格式,属于设计图的效果展示类文件,并不属于真正的源文件。源文件是可以查看到图片的所有的图层,通道、参考线、注解和颜色模式等信息,开发人员通过操作源文件,可以更加方便的控制图片,并快速的获取到图片信息。

下面展示一下,PSD源文件在PhotoShop软件中打开的样子:

image.png

常见的源文件格式:

  1. .psd格式源文件,通过PhotoShop工具制作。
  2. .sketch格式源文件,通过Sketch工具制作。
  3. .xd格式源文件,通过Xd工具制作。
  4. .fig格式源文件,通过figma或者masterGo工具制作

设计稿智能生成代码工具

imgcook

CSS 盒模型

1681368955(1).png

在浏览器中查看盒模型的方法:

image.png

盒模型注意点

  • padding不能为负值,而margin可以为负值

  • 背景色会覆盖到非margin区域包括边框区域

  • 嵌套div会出现margin-top传递的现象及解决方案

    例如:下图所示,给小的蓝色区域的div一个margin-top,它不会距离外面粉色div的顶部一个margin-top,而是把margin-top加到它外面的大的粉色div上,也就是把margin-top传递到它的父容器上了

    image.png

    解决方法是使用padding-top替换;或者给父元素加上border;或者使用BFC格式化上下文。但是如果想从根本上决这种bug,还是要使用弹性布局或者使用grid布局

  • 上下相邻div会出现margin上下叠加的现象,如下图所示,如果上下相邻的div,上面的div给了个margin-bottom,下面的div给了个margin-top,那么他们之间的间距不是2个margin的和而是取其中最大的值(只出现在上下相邻的div中)

    image.png

解决的方法可以只给一个div加margin;或者使用BFC格式化上下文;最好的方法还是使用现代的布局方式:使用Flex弹性布局或者使用grid网格布局

块级盒子和内联盒子

举例

块级盒子:div、p、h1...,内联盒子:span、a、strong...

块级盒子的特性

  • 独占一行
  • 支持所有样式
  • 不写宽度的时候,宽度和父容器的盒子一样
  • 所占区域是一个矩形

内联盒子的特性

  • 盒子不会产生换行
  • 有些样式不支持,例如 width、height、margin、padding等
  • 不写宽度的时候,宽度由内容决定
  • 所占的区域不一定是矩形,如自动换行的时候
  • 内联盒子之间会有缝隙

注意:在布局的时候不要使用内联盒子做布局(内联盒子的问题比较多),多做为文本修饰

如何判断一个盒子是块级盒子还是内联盒子? ==> 在浏览器中通过display就可以判断,inline为内联盒子

image.png

自适应盒模型的特性

自适应盒模型指的是,当盒子不设置宽高时,盒模型相关组成部分的处理方式是如何的

例1:给2个块级元素div宽度和高度

给2个嵌套div都给宽度和高度,当给子div添加padding、border的时候子div的区域就会超出父div,因为子div定了宽高后就相当于固定了盒模型中的content区域,然后再加上padding区域和border区域,它整体的面积就会超出父div(粉色为父div,蓝色为子div)

image.png

例2:不给子div宽度(宽度就会和父容器一样)

给子元素在加上padding,此时子元素并不会超出父元素,说明此时coentent的区域是变小了,而子div整体的盒子大小是不变的(和父容器一样)

image.png

总结:自适应盒模型的特性: 当我们不写宽度时,在添加相关盒模型的值得时候(如padding、margin、border等) cotent的尺寸会进行重新的计算,即整体储存往里收缩

应用场景: 子容器和父容器相同,并且子容器的内容往里面收缩,这时候就不要加宽度了

标准盒模型与怪异盒模型(IE盒模型)

在标准模型中,如果你给盒设置width和height,实际设置的content区域。padding和border再加上设置宽高一起决定整个盒子的大小

image.png

在IE盒模型中,所有宽度都是可见宽度,所以内容宽度是该宽度减去边框和填充部分

image.png

即我们设置宽高时,标准盒模型不包含border和padding,只是cotent区域的尺寸;而IE盒模型是包含border和padding区域整体尺寸作为宽高

设置IE盒模型的方法: box-sizing: border-box;

box-sizing属性

  • content-box: width、height -> content
  • border-box: width、height -> content + padding + bprder

应用

应用1:量取尺寸时不用再计算一些值

应用2:解决一些需要设置百分比和盒模型值(解决既要设置宽度100%又不会因为加padding和border而引起的尺寸超出的问题)

浮动样式

当元素被浮动时,会脱离文档流,根据float的值向左或向右移动,直到它的外边界碰到父元素的内边界或另一个浮动元素的外边界为止,是CSS布局中实现左右布局的一种方式

文档流

文档流是元素在web页面上的一种呈现方式,按照出现的先后顺序进行排列,而脱离文档流就是不按照这种方式排列

不同角度观察浮动样式

image.png

给块2加上浮动后,块2和块1已经不在一个层级,只不过用户在看网页的时候是看不出这种区别的即使块2浮起来,因为我们看的角度是左边的图的效果 image.png

例子:在body中加了2个div(body加了黑边框)

image.png

给粉色div加上浮动后,此时红色的div就在蓝色div的上面,因为是左浮动所以它就会沿着父容器的最左边进行排列,红色div脱离正常文档流(不占正常文档流的位置),而正常文档流只有蓝色的div,因此body的内容只包含蓝色div

image.png

如果给蓝色的div也加上左浮动,那么蓝色盒子就会浮动到红色盒子的右边,此时正常文档流下已经没有内容了。body就没有高度了(高度塌陷),解决高度塌陷的方法是清除浮动,真正解决高度塌陷问题的方法是使用现代布局即flex布局或者grid布局

image.png

清除浮动的方法

清除浮动解决的是高度塌陷的问题

  • clear属性 => 清除上下关系
  • BFC => 清除嵌套关系
  • 空标签 => 清除嵌套关系
  • .clearfix::after{} => 清除嵌套关系

例1:清除上下关系的浮动

image.png

清除浮动后

.div1{
  float: left;
}

.div2{
   clear: left; 
}

image.png

实际上粉色的盒子还是在高的层级而蓝色的盒子是在比较低的层级上,只不过我们看到时候是俯视的角度

如果一个粉色盒子是右浮动,而蓝色盒子清除左浮动是没有意义的,只能清除右浮动

image.png

如果不想要清除浮动这么麻烦我们可以clear: both它的意思是不管是出现左浮动还是出现右浮动,全部清理了

例2: 清除嵌套关系的浮动

image.png

给粉色div加上左浮动后,外面父div出现高度塌陷

image.png

  • 方法1: BFC
  • 方法2=> 添加空标签 在红色div同级下新增一个空的div,样式设置为clear:both => <div style="clear:both;"></div>.这样所有的div都回到了正常文档流中,缺点就是每次需要清除浮动的时候都要产生额外的多余的空div
  • 方法3 添加样式.clearfix(原理和添加空标签清除浮动一样,只不过改成了使用微元素的方法添加了内容为空,注意微元素添加的内联盒子,而添加空标签方法的元素是块级盒子,因此要加display:block;,内联盒子中添加很多效果是不起作用的)
.clearfix::after{
    content:'';
    clear: both;
    display: block;
}

浮动特性注意点

  • 浮动元素只会影响它后面的元素,如下图所示,蓝色盒子浮动后只会影响大红色盒子,而粉色盒子不会影响

    image.png

  • 文本不会被浮动元素覆盖,如下图所示,蓝色盒子浮动后,大红色盒子里面的文本不会被蓝色盒子挡住(设计的时候就是解决图文混排的问题)

    image.png

  • 浮动使块级盒子具备内联盒子特性:宽度由内容决定

    不加宽度,宽度和父容器一致

    image.png

    加上浮动后就变成内联元素了

    image.png

  • 浮动使内联盒子具备块级盒子特性:支持所有样式

    如: 被内联盒子加上宽高和背景色,宽高是不起作用的

    image.png

    加上浮动后内联盒子上的宽高就起作用了

    image.png

  • 浮动元素当父容器放不下的时候会换行

定位

CSS position 属性用于指定一个元素在文档中的定位方式,其中top、right、bottom和left属性则决定了该元素的最终位置

image.png

相对定位

  • 相对定位的元素是在文档流中的正常位置偏移给定的值
  • 不影响其他元素的布局(相对定位的元素处于正常文档流中,margin会相互影响)
  • 相对自身进行偏移(相对于左上角作为坐标轴)

绝对定位

  • 绝对定位的元素脱离文档流,绝对定位元素不占据空间
  • 使得块级盒子具备内联元素的特性,宽度由内容决定(同浮动类似)
  • 使内联盒子具备块级盒子特性:支持所有样式(同浮动类似)
  • 绝对定位元素相对于最近的非static祖先元素定位。当这样的祖先元素不存在时,则相对于可视区定位(而不是body)
  • 当绝对定位元素的祖先元素是数量大于一的非static元素时,它则相对于最近的祖先元素进行定位

固定定位

  • 固定定位与绝对定位相似,但是会固定在可视区中
  • 使得块级盒子具备内联元素的特性,宽度由内容决定(同浮动类似)
  • 使内联盒子具备块级盒子特性:支持所有样式(同浮动类似)
  • 固定定位元素不受祖先元素(是否是定位元素)影响

粘性定位

  • 粘性定位可以被认为是相对定位和固定定位的混合。元素在跨越特定阈值前为相对定位,之后为固定定位position: sticky;top:0;

z-index

注意:如果父容器和子容器都有z-index那么优先同父容器的z-index进行比较,zindex默认值0

display属性

display属性的作用

在CSS中display属性表示“显示框类型”,即不同的盒模型。简单来说,可以把块级盒子转成内联盒子,也可以把内联盒子转成块级盒子。

display属性的分类

image.png

display-outside(外部值)

image.png

外部值就是定义自身元素的外部表现,而不影响其内的子元素。

  • block:表示块级盒子像p、div等标签默认就是块级盒子。
  • inline:表示内联盒子 像span、i等默认就是内联盒子。
  • run-in:实验性质的属性,浏览器支持不好。

display-inside(内部值)

image.png

和外部值相反,内部值就是定义子元素布局的。像flex、grid这些设置都会影响到子元素的布局形式

  • flow-root:一个BFC的块级盒子
  • table:带有内部表格布局的块级盒子
  • flex:带有内部弹性布局的块级盒子
  • grid:带有内部网格布局的块级盒子

display-listitem(列表值)

为元素内容生成一个块型盒,随后再生成一个列表型的行内盒。其效果就和ul中出现项目列表符号一样,目的是为了用div去代替

display-internal(属性值)

display-box(显示值)

image.png

  • contents:只影响其内容的样式生效,比如:字体大小、文字颜色等;但是像背景色、边框是不会生效的。
  • none:从盒子树中移除,包括其所有后代元素。

display-legacy(混合值)

image.png

  • inline-block:对外表现成内联盒子,对内表现成块级盒子
  • inline-table:对外表现成内联盒子,对子元素表现成表格盒子
  • inline-flex:对外表现成内联盒子,对子元素表现成弹性盒子
  • inline-grid:对外表现成内联盒子,对子元素表现成网格盒子
    <style>
        .box{ display:inline-block; width:100px; height:100px; background:gold;}
    </style>

    <div class="box">块1</div>
    <div class="box">块2</div>
    <span class="box">内联1</span>
    <span class="box">内联2</span>

image.png

可以看到,盒子即具备了块级盒子的特性(支持宽高)又具备了内联盒子的特性(横向排列)

global(全局值)

image.png

  • inherit:继承父元素的display属性
  • initial:不管父元素怎么设定,恢复到浏览器最初始时的display属性
  • unset:unset混合了 inherit 和 initial。如果父元素设值了,就用父元素的设定,如果父元素没设值,就用浏览器的缺省设定。

书写模式与逻辑属性

书写模式

  绝大多数国家的阅读方式都是从左到右进行的,但是也有一小部分国家的阅读方式,可能是从右向左或从上到下。比如阿拉伯国家就是从右向左进行阅读的,所以在网页排版的时候,就要考虑到这个情况,尤其是做国际站的同学们。

书写模式即writing-mode属性,可以帮助以上下阅读的国家去展示网页内容。它定义了文本水平或垂直排布以及在块级元素中文本的行进方向。

  可选值有:

  • horizontal-tb 水平方向自上而下的书写方式
  • vertical-rl 垂直方向自右而左的书写方式
  • vertical-lr 垂直方向自左而右的书写方式
  • sideways-rl 内容垂直方向从上到下排列
  • sideways-lr 内容垂直方向从下到上排列

image.png

逻辑属性

解决的问题:一套代码想实现国际化,处理不同国家的排版方式

逻辑属性是从逻辑角度控制布局,而不是从物理、方向或维度来控制

dir属性可以设置元素的显示方向,是从左往右(ltr),还是从右往左(rtl),当设置auto时会自动根据当前语言决定排列方向,dir属性非常适合那些从右向左进行阅读的国家,例如:阿拉伯语,波斯语,希伯来语等。

BFC块级格式化上下文

BFC概念

BFC即Block Formatting Contexts(块级格式化上下文),它是W3C CSS2.1 规范中的一个概念。它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。

具有BFC特性的元素可以看作是隔离了的独立容器(不会乱变,是绝对意义上的纯粹的容器),容器里面的元素不会在布局上影响到外面的元素,并且BFC具有普通容器所没有的一些特性。

通俗一点来讲,可以把BFC理解为一个封闭的大箱子,箱子内部的元素无论如何翻江倒海,都不会影响到外部。

BFC触发条件

满足以下条件之一,即可触发BFC:

  • float的值不是none
  • position的值不是static或者relative
  • display的值是inline-block、table-cell、flex、table-caption或者inline-flex
  • overflow的值不是visible

  下面的box盒子就是一个BFC独立容器:

.box{
    width: 100px;
    height: 100px;
    overflow: hidden;   /* 触发了BFC,形成独立盒子 */
}

BFC的应用

  在前面介绍盒模型的margin时,出现了传递和叠加的问题,这里可以采用BFC规范来解决,原理就是让盒子形成一个独立的容器,无论里面的子元素如何折腾,都不影响到外面的元素。

<style>
.box1 {
    width: 200px;
    height: 200px;
    background: pink;
    overflow: hidden;    /* 触发了BFC,形成独立盒子 */
}
.box2{
    width: 100px;
    height: 100px;
    background: skyblue;
    margin-top: 30px;
}
</style>
<div class="box1">
    <div class="box2"></div>
</div>

图片描述

1.BFC解决传递问题(蓝色div的margin-top传递给了粉色div)

<style>
section{
    overflow: hidden;    /* 触发了BFC,形成独立盒子 */
}
.box1 {
    width: 200px;
    height: 200px;
    background: pink;
    margin-bottom: 40px;
}

.box2 {
    width: 100px;
    height: 100px;
    background: skyblue;
    margin-top: 30px;
}
</style>
<section>
    <div class="box1"></div>
</section>
<section>
    <div class="box2"></div>
</section>

图片描述

2.BFC解决叠加问题(重叠的margin不是取和而是取最大值)

3.BFC还可以解决前面浮动遇到了父容器高度塌陷的问题,也就是不管里面子元素是否浮动,都不会因为脱离文档流对容器高度造成影响。

<style>
.box1 {
    width: 200px;
    border: 1px black solid;
    overflow: hidden;     /* 触发了BFC,形成独立盒子 */
}
.box2 {
    width: 100px;
    height: 100px;
    background: pink;
    float: left;
}
</style>
<div class="box1">
    <div class="box2"></div>
</div>

图片描述

BFC解决浮动高度塌陷

在现代布局flex和grid中,是默认自带BFC规范的,所以可以解决非BFC盒子的一些问题,这就是为什么flex和grid能成为更好的布局方式原因之一。

标签默认样式及清除

标签默认样式

一些HTML标签在浏览器中会有默认样式,例如:body标签会有margin:8px;ul标签会有margin:16px 0;及padding-left:40px。

当我们在切图软件中进行尺寸或位置测量的时候,把测量出来的数值设置到对应的标签上时,可能会受到当前标签默认样式的影响,从而页面显示效果跟设计图效果不符。

清除默认样式

通常在网页开发中,要去掉这些影响尺寸和位置的默认样式及其他影响布局的默认值。可以参考CSS Tools: Reset CSS方案

由于Reset CSS相对“暴力”,不管你有没有用,统统重置成一样的效果,且影响的范围很大,所以更加“平和”的一种方式Normalize CSS诞生了。

Normalize CSS可以看成是一种Reset CSS的替代方案。创造Normalize CSS有下面这几个目的:

  • 保护有用的浏览器默认样式而不是完全去掉它们
  • 一般化的样式:为大部分HTML元素提供
  • 修复浏览器自身的bug并保证各浏览器的一致性
  • 优化CSS可用性:用一些小技巧
  • 解释代码:用注释和详细的文档来

然而用Normalize CSS和Reset CSS结合代码,可以形成一个更加强大的方案,文件命名为reset.css,代码如下

body,
h1,
h2,
h3,
h4,
h5,
h6,
hr,
p,
blockquote,
dl,
dt,
dd,
ul,
ol,
li,
button,
input,
textarea,
th,
td {
    margin : 0;
    padding: 0
}

/*设置默认字体*/
body {
    font-size  : 14px;
    font-style : normal;
    font-family: -apple-system, BlinkMacSystemFont, segoe ui, Roboto, helvetica neue, Arial, noto sans, sans-serif, apple color emoji, segoe ui emoji, segoe ui symbol, noto color emoji;
}

/*字体太小用户体检不好,让small恢复12px*/
small {
    font-size: 12px
}

h1 {
    font-size: 18px
}

h2 {
    font-size: 16px
}

h3 {
    font-size: 14px
}

h4,
h5,
h6 {
    font-size: 100%
}

ul,
ol {
    list-style: none
}

a {
    text-decoration : none;
    background-color: transparent
}

a:hover,
a:active {
    outline-width  : 0;
    text-decoration: none
}

/*重置表格*/
table {
    border-collapse: collapse;
    border-spacing : 0
}

/*重置hr*/
hr {
    border: 0;
    height: 1px
}

/*图形图片*/
img {
    border-style: none
}

img:not([src]) {
    display: none
}

svg:not(:root) {
    overflow: hidden
}

/*下面的操作是针对于html5页面布局准备的,不支持ie6~8以及其他低版本的浏览器*/
html {
    /*禁用系统默认菜单*/
    -webkit-touch-callout   : none;
    /*关闭iphone & Android的浏览器纵向和横向模式中自动调整字体大小的功能*/
    -webkit-text-size-adjust: 100%
}

input,
textarea,
button,
a {
    /*表单或者a标签在手机点击时会出现边框或彩色的背景区域,意思是去除点击背景框*/
    -webkit-tap-highlight-color: rgba(0, 0, 0, 0)
}

/*重置html5元素的默认样式*/
article,
aside,
details,
figcaption,
figure,
footer,
header,
main,
menu,
nav,
section,
summary {
    display: block
}

audio,
canvas,
progress,
video {
    display: inline-block
}

audio:not([controls]),
video:not([controls]) {
    display: none;
    height : 0
}

progress {
    vertical-align: baseline
}

mark {
    background-color: #ff0;
    color           : #000
}

sub,
sup {
    position      : relative;
    font-size     : 75%;
    line-height   : 0;
    vertical-align: baseline
}

sub {
    bottom: -0.25em
}

sup {
    top: -0.5em
}

button,
input,
select,
textarea {
    font-size: 100%;
    outline  : 0
}

button,
input {
    overflow: visible
}

button,
select {
    text-transform: none
}

textarea {
    overflow: auto
}

button,
html [type="button"],
[type="reset"],
[type="submit"] {
    -webkit-appearance: button
}

button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
    border-style: none;
    padding     : 0
}

button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
    outline: 1px dotted ButtonText
}

[type="checkbox"],
[type="radio"] {
    box-sizing: border-box;
    padding   : 0
}

[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
    height: auto
}

[type="search"] {
    -webkit-appearance: textfield;
    outline-offset    : -2px
}

[type="search"]::-webkit-search-cancel-button,
[type="search"]::-webkit-search-decoration {
    -webkit-appearance: none
}

::-webkit-input-placeholder {
    color  : inherit;
    opacity: .54
}

::-webkit-file-upload-button {
    -webkit-appearance: button;
    font              : inherit
}