由于有很多知识非常符合直觉或者和其他语言有通用性,因此个人觉得不需要全部记下来,本篇只记录一些个人觉得需要注意或单独记忆的知识点。
同时为了提高效率和减少对不重要内容的时间投入,会考虑更加精简。
相比上一篇总览,本篇更详细记录了正常布局流、弹性盒子和网格三种布局。
首先,取得元素的内容来放在一个独立的元素盒子中,然后在其周边加上内边距、边框和外边距——就是我们之前看到的盒子模型。
默认的,块级元素内容宽度是父元素的 100%,高度与内容高度一致。
行级元素的高度和宽度与内容一致,无法设置行级元素的这两个值。如果想控制内联元素的尺寸,需要为元素设置display:block
或display:inline-block
块级元素按照基于父元素的书写顺序放置,每个块级元素会在上一个元素下面另起一行,他们会被设置好的 margin 分隔。在比如英语等水平书写自上而下的模式里,块级元素是垂直组织的。
内联元素不会另起一行,只要在其父级块级元素的宽度内有足够的空间,它们与其他内联元素、相邻的文本内容(或者被包裹的)被安排在同一行。如果空间不够,溢出的文本或元素将移到新的一行。
如果两个相邻的元素都设置了 margin 并且两个 margin 有重叠,那么更大的设置会被保留,小的则会消失——这被称为外边距叠加
弹性盒子是一种用于按行或按列布局元素的一维布局方法。元素可以膨胀以填充额外的空间,收缩以适应更小的空间。本节涉及所有的基本原理。
长久以来,CSS 布局中唯一可靠且跨浏览器兼容的创建工具只有 floats 和 positioning。下面的简单需求则难以甚至不可能用这两种工具实现:
首先需要给这些 flexible 元素的父元素设置display:flex
我们给的 display
值为 flex
的元素就像一个块级元素,但是它的子元素布局为 flex 项。
如果你希望该元素的子元素作为 flex 项,你也可以使用 display
值为 inline-flex
,但是该元素的行为类似于行内元素
display: flex
的父元素被称之为 flex 容器(flex container)flex-direction
属性,可以指定主轴的方向,默认值为row
,这使得它们在按你浏览器的默认语言方向排成一排(在英语/中文浏览器中是从左到右)
此外还可以使用row-reverse
和column-reverse
值实现反向排列 flex 项
当你在布局中使用定宽或者定高的时候,可能会出现问题即处于容器中的弹性盒子子元素会溢出,破坏了布局。例如下面这样
在这里我们看到,子代确实超出了它们的容器。解决此问题的一种方法是将以下声明添加到父元素的 css 规则中:
flex-wrap: wrap
同时把下面规则添加到 flex 项元素中
flex:200px
flex:200px
声明意味着每个声明将至少为 200px 宽存在着 flex-direction
和 flex-wrap
——的缩写 flex-flow
比如可以将
flex-direction: row;
flex-wrap: wrap;
替换为
flex-flow: row wrap
在 flex 项的CSS里添加flex:
值
article {
flex: 1;
}
这是一个无单位的比例值,表示每个 flex 项沿主轴的可用空间大小。本例中,我们设置 元素的
flex
值为 1,这表示每个元素占用空间都是相等的,占用的空间是在设置 padding
和 margin
之后剩余的空间。因为它是一个比例,这意味着将每个 flex 项的设置为 400000 的效果和 1 的时候是完全一样的。
如果像下面这样
article:nth-of-type(3) {
flex: 2;
}
你会看到第三个 元素占用了两倍的可用宽度和剩下的一样——现在总共有四个比例单位可用。前两个 flex 项各有一个,因此它们占用每个可用空间的 1/4。第三个有两个单位,所以它占用 2/4 或者说是 1/2 的可用空间。
还可以指定 flex 的最小值:
article {
flex: 1 200px;
}
article:nth-of-type(3) {
flex: 2 200px;
}
这表示“每个 flex 项将首先给出 200px 的可用空间,然后,剩余的可用空间将根据分配的比例共享”
弹性盒子的真正价值可以体现在它的灵活性/响应性,如果你调整浏览器窗口的大小,或者增加一个 元素,这时的布局仍旧是好的
flex
是一个可以指定最多三个不同值的缩写属性:
flex-grow
属性的值flex-shrink
,一般用于溢出容器的 flex 项。这指定了从每个 flex 项中取出多少溢出量,以阻止它们溢出它们的容器flex-basis
属性的值一般不建议使用全写
还可以使用弹性盒子的功能让 flex 项沿主轴或交叉轴对齐。
align-items
属性控制 flex 项在交叉轴上的位置:
stretch
:默认值。使所有 flex 项沿着交叉轴的方向拉伸以填充父容器。如果父容器在交叉轴方向上没有固定宽度(即高度),则所有 flex 项将变得与最长的 flex 项一样长(即高度保持一致)center
:使这些项保持其原有的高度,但是会在交叉轴居中flex-start
或flex-end
等使 flex 项在交叉轴的开始或结束处对齐所有的值可以用align-self
属性覆盖align-items
的行为,例如
button:first-child {
align-self: flex-end;
}
justify-content
属性控制 flex 项在主轴上的位置:
flex-start
:默认值。使所有 flex 项都位于主轴的开始处flex-end
:让 flex 项到结尾处center
:让 flex 项在主轴居中space-around
:使所有 flex 项沿着主轴均匀地分布,在任意一端都会留有一点空间。很有用space-between
:和space-around
相似,但不会在两端留下任何空间弹性盒子也有可以改变 flex 项的布局位置的功能,而不会影响到源顺序(即 dom 树里元素的顺序)。这也是传统布局方式很难做到的一点
在 flex 项的 CSS 里添加order
,例如:
button:first-child {
order: 1;
}
order
值是0order
值越大,显示越靠后order
值的 flex 项按源顺序显示order
可以通过设为负值来比值为 0 的元素排更前面设置一个元素为 flex 项,那么他同样也可以成为一个 flex 容器,它的孩子(直接子节点)也可表现为弹性盒子
例如下面样式
HTML结构如下
首先设置的子节点布局为弹性盒子
section {
display: flex;
}
下面我们给 元素设置
flex
值。特别注意这里的第二条 CSS 规则——我们设置第三个 元素的子节点的布局同样为
flex
,但是属性值为列布局
article {
flex: 1 200px;
}
article:nth-of-type(3) {
flex: 3 200px;
display: flex;
flex-flow: column;
}
接下来,我们选择了第一个 最后,我们给按钮设置大小,有意思的是我们给它一个值为 1 的 现在大多浏览器都兼容弹性盒子,但是仍有老浏览器不支持或只支持非常老版本的弹性盒子。 实际开发时需要注意如果不支持弹性盒子,则可能会导致不可用,需要进行测试,确保尽可能多的浏览器中你的用户体验仍然可以接受 CSS 网格是一个用于 web 的二维布局系统。利用网格,可以把内容按照行与列的格式进行排版。另外,网格还能非常轻松地实现一些复杂的布局。关于使用网格进行页面排版,本节包含了需要的一切知识 格是由一系列水平及垂直的线构成的一种布局模式。一个网格通常具有许多的列(column)与行(row),以及行与行、列与列之间的间隙,这个间隙一般被称为沟槽(gutter) 和弹性盒子一样,更改父容器的 与弹性盒子不同的是,在定义网格后,网页并不会马上发生变化。因为 因此需要再加上一些列来让容器看起来更像表格。比如加三个宽度为200px的列。当然,这里可以用任何长度单位,包括百分比: 除了长度和百分比,我们也可以用 另外, 间隙距离可以用任何长度单位包括百分比来表示,但不能使用 第一个数也可以取值 例如要创建多个等宽轨道,可以用下面的方法: 和之前一样,你仍然得到了 3 个 显式网格是我们用 隐式网格中生成的行/列大小是参数默认是 下面的例子将 简单来说,隐式网格就是为了放显式网格放不下的元素,浏览器根据已经定义的显式网格自动生成的网格部分 例如设定为 例如 现在来试试把学到的关于网格的一切,包括 某些情况下,我们需要让网格自动创建很多列来填满整个容器。通过设置 如下所示 能看到形成了一个包含了许多至少 200 像素宽的列的网格,将容器填满。随着容器宽度的改变,网格会自动根据容器宽度进行调整,每一列的宽度总是大于 200 像素,并且容器总会被列填满 通过以下属性来指定从那条线开始到哪条线结束: 也可以用以下缩写形式来同时指定开始与结束的线,注意开始与结束的线的序号要使用 这些属性的值均为分隔线序号 例如 例如 只记录了 CSS 的部分内容flex: 1 100px;
给它一个最小的高度 100px,然后设置它的子节点( 元素)为
flex
项。在这里我们将它们放在一个包装行(wrap row)中,使它们居中对齐,就像我们在前面看到的单个按钮示例中做的那样
article:nth-of-type(3) div:first-child {
flex: 1 100px;
display: flex;
flex-flow: row wrap;
align-items: center;
justify-content: space-around;
}
flex
属性。如果你调整浏览器窗口宽度,你会看到这是一个非常有趣的效果。按钮将尽可能占用最多的空间,尽可能多的堆在同一条线上,但是当它们不再适合在同一条线上,他们中的一些会到下一行去button {
flex: 1;
margin: 5px;
font-size: 18px;
line-height: 1.5;
}
12、跨浏览器兼容性
三、网格
1、什么是网格布局
2、创建一个网格
(1)定义一个网格
display
属性为grid
,直接子项会变为网格项:.container {
display: grid;
}
display: grid
的声明只创建了一个只有一列的网格,所以子项还是会像正常布局流那样,自上而下、一个接一个的排布。.container {
display: grid;
grid-template-columns: 200px 200px 200px;
}
(2)使用 fr 单位的灵活表格
fr
这个单位来灵活地定义网格的行与列的大小。这个单位代表网格容器中可用空间的一份。很像弹性盒子里 flex 值的比例fr
可以与一般的长度单位混合使用。比如设置 grid-template-columns: 300px 2fr 1fr
,那么第一列宽度是300px,剩下的两列会根据剩余的可用空间按比例分配
fr
单位分配的是可用空间而非所有空间,所以如果某一格包含的内容变多了,那么整个可用空间就会减少,可用空间是不包括那些已经确定被占用的空间的(3)网格间隙
grid-column-gap
属性:定义列间隙
grid-row-gap
属性:定义行间隙
grid-gap
属性:同时设定两者fr
单位
gap
属性曾经有一个grid-
前缀,不过后来的标准进行了修改,目的是让他们能够在不同的布局方法中都能起作用。尽管现在这个前缀不会影响语义,但为了代码的健壮性,你可以把两个属性都写上.container {
display: grid;
grid-template-columns: 2fr 1fr 1fr;
grid-gap: 20px;
gap: 20px;
}
(4)重复构建轨道组
repeat
属性:重复构建具有某些宽带配置的某些列。auto-fill
,它的功能是根据容器的大小,尽可能多地放入指定大小的行或列.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-gap: 20px;
}
1fr
的列。第一个传入 repeat 函数的值(3)
表明了后续列宽的配置要重复多少次,而第二个值1fr
表示需要重复的构建配置,这个配置可以具有多个长度设定。例如repeat(2, 2fr 1fr)
,这相当于填入了 2fr 1fr 2fr 1fr
(5)显式网格与隐式网格
grid-template-columns
或 grid-template-rows
属性创建的。
隐式网格则是当有内容被放到网格外时才会生成的。
显式网格与隐式网格的关系与弹性盒子的 main 和 cross 轴的关系有些类似。auto
,大小会根据放入的内容自动调整。也可以使用grid-auto-rows
和grid-auto-columns
属性手动设定隐式网格轨道的大小grid-auto-rows
设为了100px,然后你可以看到那些隐式网格中的行(因为这个例子里没有设定grid-template-rows
,因此,所有行都位于隐式网格内)现在都是 100px 高了.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 100px;
grid-gap: 20px;
}
(6)minmax() 函数
minmax()
函数为一个行/列的尺寸设置了取值范围。minmax(100px, auto)
,那么尺寸就至少为 100 像素,并且如果内容尺寸大于 100 像素则会根据内容自动调整.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: minmax(100px, auto);
grid-gap: 20px;
}
(7)自动使用多列填充
repeat
与 minmax
函数,组合起来,来实现一个非常有用的功能。grid-template-columns
属性,我们可以实现这个效果,不过这一次我们会用到 repeat()
函数中的一个关键字auto-fill
来替代确定的重复次数。而函数的第二个参数,我们使用minmax()
函数来设定一个行/列的最小值,以及最大值 1fr
.container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
grid-auto-rows: minmax(100px, auto);
grid-gap: 20px;
}
3、基于线的元素放置
/
符号分开:
header {
grid-column: 1 / 3;
grid-row: 1;
}
article {
grid-column: 2;
grid-row: 2;
}
aside {
grid-column: 1;
grid-row: 2;
}
footer {
grid-column: 1 / 3;
grid-row: 3;
}
4、使用 grid-template-areas 属性放置元素
grid-template-areas
属性,命名一些元素并在属性中使用这些名字作为一个区域.container {
display: grid;
grid-template-areas:
"header header"
"sidebar content"
"footer footer";
grid-template-columns: 1fr 3fr;
gap: 20px;
}
header {
grid-area: header;
}
article {
grid-area: content;
}
aside {
grid-area: sidebar;
}
footer {
grid-area: footer;
}
grid-template-areas
属性的使用规则如下:
grid-area
属性定义的区域名字.
符号,让一个格子留空
总结