块级元素和内联元素
块级元素 | 行内元素 |
---|---|
块级元素是指在页面上以块的形式显示的元素,它们会独占一行,并且默认情况下会占满其父元素的宽度。 | 内联元素(又称行内元素)以行的形式显示,不独占一行 |
<div> 、<p> 、<h1> 至<h6> 、<ul> 、<li> 、<table> 、<form> 等 |
<span> 、<a> 、<b> 、<i> 、<em> 、<strong> 、<img> 、<input> 、<label> 、<video> 、<audio> 、<canvas> 、<svg> 等 |
块级元素特性
-
多个块级元素(兄弟关系),处于文档流时,从上到下各占一行排列。
-
文档流中的块级元素的 width 的默认值与父元素的 width 相同。
-
文档流中的块级元素的 height 的默认由子元素的高度决定(子元素撑起父元素)。
-
可以设置 width 和 height
内联元素特性
-
多个内联元素在处于文档流时,从左到右依次排开,一行不足时会换行排序。
-
大部分内联元素不能设置 width 和 height,但是 img、video、audio、canvas、svg、input 这些内联元素可以设置 width 和 height
-
对于内联元素来说,其水平方向(即左右方向)的 padding 和 margin 是有效的,垂直方向(即上下方向) padding 和 margin 通常不会影响周围元素的布局。
html<template> <div class="parent"> <span class="children1">haha1</span> <span class="children1">haha2</span> <span class="children1">haha3</span> <div style="background-color: red;">hehehehehehehehehehehehehehe</div> </div> </template> <style lang="scss" scoped> .parent { background-color: yellow; height: 50px; } .children1 { margin: 20px; } .children2 { padding: 20px; } </style>
块级内联元素
通过设置 CSS 的 display: inline-block;
属性可以将元素设置为行内块元素。同时具备行内元素和块级元素的特点。
-
不独占一行,与其他元素在同一行内显示(行内元素特性)。
-
可以设置宽度和高度(块级元素特性)。
-
水平方向和垂直方向的 padding 和 margin 有效(块级元素特性)。
html
<template>
<div class="parent">
<span class="children1">haha1</span>
<span class="children2">haha2</span>
<span class="children3">haha3</span>
<div style="background-color: red;">hehehehehehehehehehehehehehe</div>
</div>
</template>
<style lang="scss" scoped>
.parent {
background-color: yellow;
height: 50px;
}
.children1 {
margin: 20px;
display: inline-block;
}
.children2 {
padding: 20px;
display: inline-block;
}
</style>
这里为什么 haha3 也跟着向下平移了 20px?
因为 inline
和 inline-block
元素默认是基于父元素的基线对齐的。基线对齐意味着这些元素会根据其内部文本的底部对齐,而不是根据元素的顶部或底部边缘对齐。基线的位置受元素内容和边距(padding、margin)的影响。所以当给 .children1 或 .children2 加 margin 或 padding 时,其实是改变了 .parent 的基线,所以 haha3 的垂直方向的位置会发生变化。
display
display 可能的值如下:
值 | 说明 |
---|---|
inline | 以行内元素行为展示 |
block | 以块级元素行为展示 |
inline-block | 行内元素和块级元素特性兼而有之,既不会占满父元素,又可以设置width和height属性 |
table | 以表格的形式展示 |
table-cell | 以表格单元格的形式展示 |
table-row | 以表格行的形式展示 |
table-column | 以表格列的形式展示 |
flex | CSS3 新增,虽然处于CR阶段,但是很多现代浏览器已经支持无前缀的该特性,IE从11开始部分支持。类似块级元素,但是可以用于制作自适应布局 |
inline-flex | 类似行内元素,但是可以用于制作自适应布局 |
grid | CSS3 新增,目前处于"实验阶段(Experimental)",只是得到了IE11和edge的部分支持 |
CSS基本定位机制
CSS中的三种基本定位机制:标准流、浮动流(flot)、定位流(position)。
什么是标准流
又叫文档流,元素会按照从左到右,从上到下的流式排列。
什么是元素脱离文档流
给元素添加定位、浮动即叫做元素脱离文档流。
脱离文档流,也就是将元素在普通布局排版中拿走,不占据位置(悬空了),其他的盒子在定位的时候,会当做脱离文档流的元素不存在而进行定位
注意:
-
使用 float 脱离文档流时,其他的元素盒子会无视这个元素,但其他盒子内的文本依然会为这个元素让出位置,环绕在周围
-
脱离文档流并不等于脱离 DOM 树,依旧包含在 DOM 中。
-
flex 布局的子元素不会脱离文档流,很好地遵从了"流的特性"
html
<template>
<div class="parent">
<div class="children1">haha1</div>
<div class="children2">haha2</div>
<div class="children3">haha3</div>
</div>
</template>
<style lang="scss" scoped>
.parent {
background-color: yellow;
height: 50px;
}
.children2 {
float: left;
}
</style>
可以看到盒子 .children3 无视了 .children2,但是文本 haha3 为 haha2 让出了位置。
元素脱离文档流后的变化
对于块元素:
-
若一个块元素脱离文档流,它下面的处于文档流中的兄弟元素会上移
-
多个元素可以在同一行展示
-
块元素被内容撑开,也就是说,width 不是父元素的 width
对于内联元素:
- 可以设置 width 和 height
浮动的特点
-
浮动元素会脱离标准流,在标准流中不占位置,相当于飘在空中
-
浮动元素比标准流高半个级别,可以覆盖标准流中的元素
-
浮动找浮动,下一个浮动元素会在上一个浮动元素后面左右浮动
-
浮动元素一行可以显示多个,可以设置宽高
-
浮动元素不能设置 text-align: center 和 margin: 0 auto
清除浮动
主流方法:after
伪类加 clear: both;
html
<template>
<div class="test">
<p>With clear: both;</p>
<div class="container myClearfix">
<div class="box">Box 1</div>
<div class="box">Box 2</div>
<div class="box">Box 3</div>
</div>
<p>Without clear: both;</p>
<div class="container">
<div class="box">Box 1</div>
<div class="box">Box 2</div>
<div class="box">Box 3</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.test {
.container {
width: 300px;
border: 2px solid #000;
margin-bottom: 20px;
}
.box {
width: 100px;
height: 100px;
margin: 10px;
background-color: lightblue;
float: left;
}
.myClearfix::after {
content: "";
display: table;
clear: both;
}
}
</style>
盒子模型
盒子模型的组成: 由外向内分别是:外边距(margin),边框(border),内边距(padding),和实际内容(content)
如果把盒子模型看作是一个生活中的快递,那么内容部分等同于你买的实物,内边距等同于快递盒子中的泡沫,边框等同于快递盒子,外边距等同于两个快递盒子之间的距离。
盒子模型分类:
-
标准盒子模型:
盒子总宽度/高度 = width/height + padding + border + margin。
特点,会撑开容器,width/height 的值就是内容区域的宽高。内边距和边框都是往外取延申,内容区域大小不变。
对应
box-sizing: content-box;
默认是该属性 -
IE盒子模型:
盒子总宽度/高度 = width/height + margin。
特点,会压缩容器,内边距和边框都是往内延申,盒子总体容器不变,内容区域大小会被压缩
box-sizing:border-box
开启。 -
弹性盒子模型
就是 flex 布局
scoped 和 deep
scoped 作用:样式隔离,使自身组件样式不会影响到其他组件
scoped 原理:会在组件中为每个标签元素上添加一个唯一的 data-v-hash 属性,组件内的 css 样式都会带着这个属性选择器。
使用 scoped 后,父组件的样式将不会渗透到子组件中。因为子组件中并没有和父组件相同的 data-v-hash 属性。
html
<!--parent-->
<template>
<div class="parent">
<div class="my-class">父组件内容</div>
<Children />
</div>
</template>
<script>
import Children from './Children.vue';
export default {
components: { Children }
}
</script>
<style lang="scss">
.parent {
font-size: 24px;
}
.my-class {
color: red;
}
</style>
html
<!--children-->
<template>
<div class="children">
<div class="my-class">子组件内容</div>
</div>
</template>
<style lang="scss">
</style>
此时父组件中没有使用 scoped,可以看到父组件的样式穿透到了子组件,子组件受到了影响。
如果在父组件中加上 scoped:
scoped 的作用就是让编译器自动给该组件模板内的每个元素添加一个唯一的属性(data-v-xxxxxx),这个属性是一个哈希值,用于确保这些样式只应用于当前组件。这意味着即使你有一个类名为 .my-class 的样式,在 <style scoped>
中定义,它也只会应用于当前组件内具有相同类名的元素,而不会影响其他地方的 .my-class。
这里要注意:在父组件加 scoped 并不意味着父组件的样式会完全与子组件隔离。在这个例子中,font-size: 24px
还是被子组件继承了。
那么如果加上 deep 会发生什么?
html
<style lang="scss" scoped>
.parent {
font-size: 24px;
}
::v-deep .my-class {
color: red;
}
</style>
没加 deep 之前,父组件中 .my-class 是 .my-class[data-v-f3a85fa2]
,加了 deep 后,父组件中 .my-class 是 [data-v-f3a85fa2] .my-class
所以 deep 的原理在于它改变了编译后的 CSS 选择器结构,让原本受限于scoped属性的样式得以跨越组件边界,作用于更深层级的DOM元素。
标题 | |
---|---|
/deep/ | vue2.0 |
::v-deep | vue2.6.0+ |
:deep() | vue3 |
>>> | css 原生 |
px、rpx、em、rem、vh、vw、%
px
像素:即 px,是画面中最小的点(单位色块)。
屏幕分辨率:画面水平方向的像素值 x 画面垂直方向的像素值。比如电脑显示器分辨率 1920 x 1080 ,就是说设备屏幕的水平方向上有 1920 个像素点,垂直方向上有 1080 个像素点。
所以相同尺寸的屏幕,分辨率越高,画面越精细。
图像分辨率:一张图片分辨率是 500 x 200,也就是说这张图片在屏幕上按 1:1 放大时,水平方向有 500 个像素点(色块),垂直方向有 200 个像素点(色块)。
可以理解为图片的像素点和屏幕的像素点是一个一个对应的。
但是,在屏幕上把图片超过 100% 放大时,为什么图片上像素色块也变的越大?其实是设备通过算法对图像进行了像素补足,我们把图片放的很大后看到的一块一块的方格子,虽然理解为一个图像像素,但是其实是已经补充了很多个屏幕像素。
1px 在不同设备上的物理大小并不相同,它会受屏幕尺寸和屏幕分辨率的影响。
rpx
小程序专用。可以根据屏幕宽度进行自适应。规定屏幕宽为 750rpx。
微信小程序官网建议在开发小程序时使用 iPhone6 作为视觉稿的标准。
在 iPhone6 上,屏幕宽度为 375px,共有 750 个物理像素,则 750rpx = 375px = 750 物理像素,1rpx = 0.5px = 1 物理像素。
通过 rpx 设置元素和字体的大小,小程序在不同尺寸的屏幕下,可以实现自动适配。
逻辑像素、物理像素、物理像素比
iphone6 屏幕分辨率是 1334 * 750(物理像素);逻辑像素(css 像素)是 667px * 375px
逻辑像素(css 像素):就是 px。
物理像素(设备像素):pc 端 1px = 1 物理像素,移动端不一定(例如 iPhone6 有 750 个物理像素,有 375 个逻辑像素)。
物理像素比(DPR):1px 逻辑像素能显示的物理像素点的个数,也称为屏幕像素比。
物理像素比(DPR) = 物理像素 / 逻辑像素。
iPhone6 的物理像素比 = 750 / 375px = 2
多倍图
例如一张 100px * 100px 的图片,把这张图片移植到 iphone6 上,DPR 是 2,那么手机屏幕上会用 200 * 200 个物理像素来展示这个图片。想象一下你在使用电脑浏览这张图片时,这时候 1 个逻辑像素对应 1 个物理像素,这时候你把图片放大两倍,就相当于 1 个逻辑像素对应 2 个物理像素。这时候图片放大后在电脑上的效果就等同于这张图片在 iphone6 上的效果,会变得模糊。
那如何解决这个问题呢?很简单,只需要一张 200px * 200px 的图片。你不是觉得放大后的图片模糊么,那我把图片精度提高,200px * 200px 的图片放大后的效果就与 100px * 100px 的图片没放大的效果相同了。
当然你不能直接使用这张 200px * 200px 的图片,你需要把图片缩小为原来的一半。就比如你原本是要把 100px * 100px 的图片塞进一个宽高都是 100px 的 div 中,但是 DPR 是 2,原图片太模糊了,你换成了 200px * 200px 的图片,还是要塞进这个 div,就需要把 200px * 200px 的图片缩小才能放进去。
通常使用的多倍图是二倍图,当然还存在 3 倍图、4 倍图等。
第一个图就是 100px * 100px, 第二个图就是缩小一倍后的 200px * 200px 的二倍图。
实际开发中如何处理多倍图?
-
web 开发中通常使用
<img>
标签的srcset
属性来处理多倍图。html<img src="example-image-1x.png" srcset="example-image-2x.png 2x, example-image-3x.png 3x" alt="Example Image" width="200" height="200">
-
在 iOS 中,多倍图的处理通常是通过命名约定来完成的。
命名约定:
-
@1x
:标准分辨率图片 -
@2x
:2 倍图(用于 Retina 屏幕) -
@3x
:3 倍图(用于更高分辨率的屏幕)
例如:
-
example.png
(标准分辨率) -
example@2x.png
(2 倍图) -
example@3x.png
(3 倍图)
-
-
在 Android 中,多倍图的处理是通过放置在不同的
drawable
文件夹中来完成的。文件夹命名:
-
drawable-mdpi
:中等分辨率(1x) -
drawable-hdpi
:高分辨率(1.5x) -
drawable-xhdpi
:超高分辨率(2x) -
drawable-xxhdpi
:极高分辨率(3x) -
drawable-xxxhdpi
:极高分辨率(4x)
例如:
-
drawable-mdpi/example.png
-
drawable-hdpi/example.png
-
drawable-xhdpi/example.png
-
drawable-xxhdpi/example.png
-
drawable-xxxhdpi/example.png
-
em
相对长度单位。
1em 的实际大小不是固定的,而是相对于其父元素的字体大小。例如,如果父元素的字体大小是 16px,那么子元素中 1em 就等于 16px,而 2em 就等于 32px。
孙子元素不会直接继承 em 值,但会间接地受到 em 单位的影响。因为 em 是根据父元素的 font-size 计算的,除非你重新设置子元素的 font-size,否则孙元素的 1em 代表的实际 px 值和子元素中的相同。
html
<template>
<div class="box">
<div class="div1">1</div>
<div class="div2">
2
<div class="div2-1">3</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.box {
font-size: 16px;
margin: 10px;
div {
height: 100px;
}
}
.div1 {
background-color: red;
width: 10em;
}
.div2 {
// font-size: 32px;
background-color: green;
width: 20em;
}
.div2-1 {
background-color: blue;
width: 10em;
}
</style>
div2 加上 font-size: 32px
:
div2-1 是 320px
rem
rem 是 css3 新增的一个相对长度单位,它的出现是为了解决 em 的缺点,em 是相对于父级元素的字体大小,当父级元素字体大小改变时,又得重新计算。 rem 就可以解决这样的问题,rem 只相对于根目录,即 HTML 元素,它会随HTML元素的属性(font-size)变化而变化。
1rem = html的font-size值(px)。
css
html {
font-size: 20px;
}
div {
font-size: 1rem; // 实际 1 * 20px = 20px
}
html 默认 font-size 是 16px。
Web 应用中根据屏幕宽度动态设置 rem 单位代码:
js
window.addEventListener('DOMContentLoaded', (event) => {
setRemFontSize();
window.addEventListener('resize', setRemFontSize);
});
function setRemFontSize() {
// Define the base font size and the base viewport width
const baseFontSize = 16; // Base font size when viewport width is 750px
const baseViewportWidth = 750;
// Get the current viewport width
const viewportWidth = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
// Calculate the font size based on the viewport width
const fontSize = (viewportWidth / baseViewportWidth) * baseFontSize;
// Ensure the font size doesn't go below a certain threshold
const fontSizeWithThreshold = Math.max(fontSize, baseFontSize);
// Set the font size on the html element
document.documentElement.style.fontSize = fontSizeWithThreshold + 'px';
}
vh
无论视口(视口就是浏览器窗口)高度多少,都将视口高均分为 100 份,每一小份就是 1vh, 1vh 就是当前屏幕可见高度的 1%, 也就是说 height: 100vh == height: 100%; 但是当元素没有内容时候,设置 height:100%,该元素不会被撑开,此时高度为 0, 但是设置 height:100vh,该元素会被撑开屏幕高度一致。
vw
无论视口宽度多少,都将视口宽均分 100 份,每一小份就是 1vw。
%
通常认为子元素的百分比完全相对于直接父元素,但是,不总是相对于父元素的对应属性值。
-
子元素的 top 和 bottom 如果设置百分比,则相对于直接非 static 定位(默认定位)的父元素高度。
-
子元素的 left 和 right 如果设置百分比,则相对于直接非 static 定位父元素的宽度。
-
子元素的 padding/margin 如果设置百分比,不论是垂直方向或者水平方向,都相对于直接父亲元素的 padding/margin,与父元素的 height 有关。
-
因为 % 不总是相对于父元素的宽高或者屏幕大小,所以开发少用。
浏览器内核
一些较新的css3特性,需要添加以上前缀兼容每个浏览器
浏览器 | 内核 | 前缀 |
---|---|---|
IE浏览器 | Trdent(IE 内核) | -ms- |
火狐浏览器 | Gecko(Firefox 内核) | -moz- |
Chrom 和 Safari 浏览器 | Webkit(Safari 内核,Chrom 内核) | -webkit- |
Chrom 浏览器 | Blink 内核 | -webkit- |
360、猎豹浏览器 | IE + Chrom 双内核 | -ms- / -webkit- |
html
<div class="root">
<div class="box"></div>
<div class="box"></div>
</div>
<style>
.root{
display: flex;
}
.box{
flex: 1;
-ms-flex: 1;
-moz-flex:1;
-webkit-flex:1;
}
</style>