镇楼图

Pixiv:torino



十五、盒子模型——浮动与定位

overflow

visibility

作用:设置盒子是否可见

属性值 说明
visible 默认,可见
hidden 不可见,但依然占位
collapse 专门用于表格元素,若在其他元素使用则视为hidden
可以删除表格某一行/列,但不会影响布局
inherit

position

作用:盒子的定位

属性值 说明
static 默认,正常情况无定位,不会受top、right、bottom、left影响
fixed 固定定位,即使滚动浏览器依然展现在固定位置
relative 相对其原本正常位置定位
absolute 相对上一级父元素定位
initial 浏览器的默认值,比如文字颜色默认为black,可以通过此来设置
任何属性值可以填此关键字,比如此时position的initial为static
inherit

z-index

作用:当使用定位后很可能会发生重叠,此时可以通过z-index属性设定重叠时显示的等级,较低等级的会被较高等级的覆盖

属性值 说明
auto 默认,显示等级与父元素一致
数字 设定显示等级
inherit

top、right、bottom、left

作用:当启用相对定位后,会根据其相对的参考位置进行偏移,比如absolute会参考父元素,fixed会参考自身原本位置

注:在设定时水平方向或垂直方向只能设置一个,比如设置了bottom就不能设置top

属性值 说明
auto 默认
长度单位 略,会向里偏移,比如设定right实际上是从最右边向里偏移多少,其他类似
inherit

cursor

作用:非常有意思的属性,定义当鼠标指针放置于元素范围内时的光标

根据系统指针的命名,大体分为如下

属性值 说明
url(...) 自定义光标,只要指定url
在某些网站可以看到有其特殊光标就是这么做的
auto 默认情况,根据浏览器默认值设定
default 正常选择
crosshair 精确选择
pointer 链接选择
move 移动
e-resize 水平调整大小
w-resize 水平调整大小
n-resize 垂直调整大小
s-resize 垂直调整大小
ne-resize 沿对角线调整大小2
nw-resize 沿对角线调整大小1
se-resize 沿对角线调整大小1
sw-resize 沿对角线调整大小2
text 文本选择
wait
help 帮助选择
progress 后台运行
none 无指针
not-allowed/no-drop 不可用

还有一些并不在操作系统之中,具体可参考MDN

float、clear

作用:当position不为绝对定位时可用,周围一切元素都会尽量(如果空间足够)左右移动且围着float元素

注:clear用于清除从此标签开始之前的浮动,但是之前的浮动效果依然保留。也就是说存在一个顺序问题,之前已发生的float效果不会受到影响,但之后可能会因为float产生的效果会发生变化

float属性值 说明
none 默认,不浮动
left 左浮动
right 右浮动
inherit
clear属性值 说明
none 默认,允许两边浮动
left 禁止左浮动
right 禁止右浮动
both 禁止两边浮动
inherit

浮动布局

要让多个块级元素横向排列,可以通过浮动一次性的解决

浮动的元素会脱离标准流(脱标),会根据父元素在最上面根据float设定来填充(不需要考虑高度且盒子之间无缝隙),若宽度不够会自动换行(包括放大缩小网页导致的宽度变化)

float问题(1)——重叠

浮动的盒子和标准流的盒子需要看成两块内容,浮动会从当前元素开始影响后续的的所有同级的标准流的盒子(不会影响同级的前面的标准流盒子,也不会影响其他级别的,尽管效果上影响了子级的盒子!!!)

一般情况来说,float所处的级别其他一切元素都会设置成float,虽然听上去更像是一个规范,但确实只要同级没有标准流直接从源头遏制问题的发生

还有一种情况,如果本身要求产生重叠的效果,可以z-index设置重叠的顺序

float问题(2)——高度塌陷

高度塌陷问题只会出现父元素无法设定的情况

为什么父元素无法设定?比如我写的blog文章长短不一,故此高度也不同,在这种情况下高度是无法确定的,但无法确定的情况下如果直接用了就有问题了

    <div class="father">
        <div class="son1">1</div>
        <div class="son2">2</div>
    </div>
    <div class="other"></div>

<style>
        .father {
            background-color: black;
            width: 700px;
            margin-bottom: 20px;
            /* 无法确定father高度需要根据子元素确定 */
        }
        
        .son1,
        .son2 {
            float: left;
            background-color: grey;
            width: 300px;
            height: 200px;
            margin: 10px;
        }
        
        .other {
            background-color: brown;
            width: 100%;
            height: 50px;
            margin-top: 10px;
        }
</style>

比如上述代码,可以清楚地看到other盒子跑上来了,因为father盒子没确定高度的情况下,float不占位导致father盒子高度为0。

在解决这个方法前需要先了解BFC(Block Formatting Context)块格式化上下文的概念。高度塌陷以及之前所述的margin合并本质上是BFC的问题

BFC是什么?

在正常情况下如果一个元素只有浮动元素,由于没有标准流的存在,实际的内容高度为0。设定高度只是在形式上解决问题,并不能改变其下内容因为都是浮动元素高度为0的事实

BFC是block类型盒子布局中发生的区域,也是浮动元素与其他元素交互的区域

BFC对float的影响

float不会影响其他BFC元素的布局,因此可以说明高度塌陷问题的产生来源。父元素不指定height高度的情况下为auto,即与子元素的height有关,但float不会影响BFC元素。因此在内部可以认为根本没有元素,所以auto自然会设定为0px。

在之前提出clear后解决方法便已经有了,只要让浮动效果依然保留,清除后续对父元素产生的影响即可

    <div class="father">
        <div class="son1">1</div>
        <div class="son2">2</div>
        <div style="clear: both;"></div>
        <!-- 清除此级所有float
			但之前的float效果依然保留
			因此视觉效果上解决了问题-->
        <!-- <p style="float: right;">123456</p>
			再添加浮动的标签会发现依然出现高度塌陷问题
			由此证明了clear只会清除之前的float-->
    </div>
    <div class="other"></div>

还有一种解决方法是针对于父元素的,只要父元素其下所有浮动元素也能像正常元素一样被计算在内即可。即要让父元素赋予BFC让其下所有子元素也是BFC的

我在下面说明了所有BFC产生的情况,我认为最好的方案是inside设置为flow-root产生一个没有任何效果的BFC,还有些诸如设定overflow等本质上都是用于生成BFC从而对其子元素产生布局影响

        .father {
            background-color: black;
            width: 700px;
            margin-bottom: 20px;
            display: flow-root;
            /*用于产生无效果的BFC
			 哪怕之后改成flex、grid依然具有BFC*/
        }

BFC产生的方式

这里所述都是BFC本身对其下子元素产生的影响

■html根元素便是一个BFC

■float不为none

■position设为absolute、fixed

■display的inside值设为flow-root或是其他如table、column等

■display定为flex模型或grid模型

■overlow不为visible

■contain设为layout、content、paint

<style>
	/*这里说明float生成BFC对其下float的影响*/
    /*结果显示float产生BFC从而不会出现高度塌陷的问题*/
    .father {
        background-color: black;
        width: 80px;
        float: left;
        /*具有float高度没有说明的父元素*/
    }
    .son {
        background-color: grey;
        float: left;
        height: 20px;
        width: 20px; 
    }
</style>

    <div class="father">
        <div class="son">1</div>
        <div class="son">2</div>
        <div class="son">3</div>
    </div>

BFC与外边距塌陷问题

外边距塌陷问题本质来源于父元素没触发BFC,那么加个flow-root试试?

加BFC是让子元素产生独立的空间,让父元素的空间与子元素空间错开

    <style>
        * {
            margin: 0px;
            padding: 0px;
        }
        
        .father {
            background-color: aqua;
            width: 500px;
            height: 300px;
            /* display: flow-root; */
        }
        
        .first {
            width: 400px;
            height: 200px;
            /* margin-bottom: 50px; */
            background: purple;
        }
        
        .second {
            width: 400px;
            height: 200px;
            /* margin-top: 100px; */
            background: green;
        }
    </style>

<body>
    <div class="father">
        <div class="first"></div>
    </div>
    <div class="father">
        <div class="second"></div>
    </div>
</body>

BFC与外边距合并问题

代码和上面一样,假设不解决外边距塌陷问题,如何解决外边距合并问题?

本质上也是加上BFC,嵌套一个空的只有BFC效果的父元素, 让子元素之间的空间是错开的,从而达到之间的外边距是错开的不会进行合并。

但我不推荐这样做,不如作为特性不去解决这个问题

    <style>
        * {
            margin: 0px;
            padding: 0px;
        }
        
        .father {
            /* display: flow-root; */
            /* 套一个空的BFC */
        }
        
        .first {
            width: 400px;
            height: 200px;
            margin-bottom: 50px;
            background: purple;
        }
        
        .second {
            width: 400px;
            height: 200px;
            margin-top: 100px;
            background: green;
        }
    </style>

<body>
    <div class="father">
        <div class="first"></div>
    </div>
    <div class="father">
        <div class="second"></div>
    </div>
</body>

十六、盒子模型——Display

盒子模型中还有一个属性,display但因为稍复杂因此单独拎出来说明

display分为六类:outside、inside、listitem、internal、box、legacy

outside

指定外部显示方式,即流式布局的方式

属性值 说明
block 块级元素
inline 行内元素

inside

指定内部显示方式,即如何影响其他元素的布局而不是针对自身元素的布局

属性值 说明
table 可以理解为定义了一个table块级框
flow-root 创建BFC
flex 后续会着重说明
grid 后续会着重说明

listitem

属性值只有listitem,可以简单理解为就是变成列表项的形式

internal

internal是针对于inside中复杂的情况,如table(ruby在此不做说明)

属性值 说明
table-row-group 参考tbody
table-header-group 参考thead
table-footer-group 参考tfoot
table-row 参考tr
table-ceil 参考td
table-column-group 参考colgroup
table-column 参考col
table-caption 参考caption

box

用于定义如何不显示的问题

属性值 说明
none 包括其子元素均不显示
contents 只有此元素不显示,其下的子元素依然可以显示

二值语法与legacy

对于display来说可以采用二值语法,即某一个盒子可以同时设置outside和inside

此外legacy采用了语法糖的形式可以使用单个属性值代替二值语法(因为有相当多的浏览器不支持二值语法),在考虑display时应当更加详细的考虑需要哪一个outside需要哪一个inside

legacy属性值 等价效果
block block flow
flow-root block flow-root
inline inline flow
inline-block inline flow-root
flex block flex
inline-flex inline flex
grid block grid
inline-grid inline grid

补充说明:float本质上是变成inline-block

这里简单说明inline-block,比如这里展示效果就是外部inline,内部由于flow-root会影响浮动的参考

    <style>
        .container {
            margin: 10px;
            width: 200px;
            height: 200px;
            background-color: grey;
            display: inline-block;
            /*等价于inline flow-root*/
        }
        
        .item {
            background-color: bisque;
            margin: 10px;
            float: left;
        }
    </style>

<body>
    <div class="container">
        <div class="item">Floated</div>
        <p>Text following the float.</p>
    </div>
    <div class="container">
        <div class="item">Floated</div>
        <p>Text following the float.</p>
    </div>
    <div class="container">
        <div class="item">Floated</div>
        <p>Text following the float.</p>
    </div>
</body>

二值语法的兼容性

所以推荐legacy


十七、Flex布局

流式布局、浮动布局、定位布局是最基础的三种布局方式,但CSS还提供其他布局方式,首先是Flex也是特别常用的布局方式。因为经常会遇到匀称对齐的布局要求,不管是flex还是grid都是为了对齐。

在display的inside属性中有一felx属性值,这便是弹性盒子,在设定好display: flex;后可以使用felx相关的属性

FlexBox是什么?

Flexible Box模型是CSS提供的一种一维布局模型,其在空间分布、对齐能力上极为出色。之所以是一维布局因为只能处理一行或一列,还有另外一种Grid则是二维布局模型,可以同时处理行列

此外flex特别重要的一点是伸缩性,简单来说就是会根据不同的盒子大小来自动伸缩元素大小

主轴与交叉轴

主轴通过felx-direction定义,是最基本的属性

flex-direction属性值 说明
row 默认,水平左到右
row-reverse 水平右到左
column 垂直上到下
column-reverse 垂直下到上

选择row则会是水平类似于inline的方式布局,column则是垂直类似于block的方式布局。若附带reverse则可以逆向排列

所谓交叉轴则是指垂直于主轴的方向,交叉轴不再分有没有reverse因为不需要

<style>
    div {
        display: flex;
        /*创建flex容器*/
        flex-direction: column-reverse;
        /*如设定了此,则所有元素会从下到上排列*/
    }
</style>

<div id="main">
	<div style="background-color:coral;">A</div>
	<div style="background-color:lightblue;">B</div>
	<div style="background-color:khaki;">C</div>
	<div style="background-color:pink;">D</div>
	<div style="background-color:lightgrey;">E</div>
	<div style="background-color:lightgreen;">F</div>
</div>

display设定为flex,则此区域称为【flex容器】

flex容器中的直系子元素则称为【flex元素】

交叉轴体现在另外一个属性flex-wrap,用于指定是否会换行,换行会根据交叉轴方向换行。如果不换行,即可能在主轴一维发生溢出

但设置为nowrap也是也可能发生溢出的。如果换行发生很多次超出了交叉轴一维的长度,也会溢出

注:溢出的处理参考overflow,flex-wrap只能保证主轴不会溢出(若容器主轴上的长度小于元素在主轴上的长度依然会溢出)

flex-wrap属性值 说明
nowrap 默认,不换行
wrap 换行

当然还提供了复合属性flex-flow用于同时设定flex-direction和flex-wrap

<style>
	div {
        display: flex;
        width: 100px;
        height: 100px;
        flex-flow: column-reverse wrap;
        /*保证主轴方向不会溢出*/
        /*无法保证交叉轴方向不溢出,如本例水平方向会溢出*/
    }
    div div{
        width: 30px;
        height: 30px;
    }
</style>

<div id="main">
	<div style="background-color:coral;">A</div>
	<div style="background-color:lightblue;">B</div>
	<div style="background-color:khaki;">C</div>
	<div style="background-color:pink;">D</div>
	<div style="background-color:lightgrey;">E</div>
	<div style="background-color:lightgreen;">F</div>
	<div style="background-color:coral;">A</div>
	<div style="background-color:lightblue;">B</div>
	<div style="background-color:khaki;">C</div>
	<div style="background-color:pink;">D</div>
	<div style="background-color:lightgrey;">E</div>
	<div style="background-color:lightgreen;">F</div>
	<div style="background-color:coral;">A</div>
	<div style="background-color:lightblue;">B</div>
	<div style="background-color:khaki;">C</div>
	<div style="background-color:pink;">D</div>
	<div style="background-color:lightgrey;">E</div>
	<div style="background-color:lightgreen;">F</div>
	<div style="background-color:coral;">A</div>
	<div style="background-color:lightblue;">B</div>
	<div style="background-color:khaki;">C</div>
	<div style="background-color:pink;">D</div>
	<div style="background-color:lightgrey;">E</div>
	<div style="background-color:lightgreen;">F</div>
</div>

order控制显示顺序

flex-direction、flex-wrap只是宏观地控制维度上的顺序,但并不能具体地控制绘制顺序

<style>
	.box {
		display: flex;
		flex-direction: row;
	}
    .box :nth-child(5) { order: 1; }
	.box :nth-child(3) { order: 1; }
	.box :nth-child(1) { order: 2; }
	.box :nth-child(2) { order: 3; }
	.box :nth-child(4) { order: 3; }
</style>

<div class="box">
	<div>1</div>
	<div>2</div>
	<div>3</div>
	<div>4</div>
	<div>5</div>
</div>

如此例会优先绘制order=1的,与CSS代码顺序无关,只看HTML元素的顺序,即先绘制3再绘制5。然后绘制order=2的,即绘制1,然后再绘制2、4

在某些情况下可以根据需求来强调某一flex元素

order处理的是逻辑顺序,而flex-direction处理的是视觉顺序。虽然在部分情况下两者处理的顺序是重叠的即用两种方法都能处理,但仍有一部分情况逻辑顺序与视觉顺序是分离的,此时order就有必要使用了

主轴居中与交叉轴居中

在flex设定好主轴方向后,比如row那么起始点start就在左侧,终点end在右侧。column-reverse起始点在下侧,终点在上侧

可以通过justify-content设置主轴方向的排列,align-content设置垂直方向的排列

justify-content/align-content属性值 说明
flex-start justify-conteng默认,位于容器起始点
flex-end 位于容器终点
center 位于中央
space-between 对齐,元素之间留白,两侧无留白
space-around 对齐,元素之间,两侧均留白
stretch align-content特有的默认的属性值,交叉轴上元素会自动拉伸以适应flex容器

对于flex-start、flex-end、center盒子之间是紧密邻接的,如果设定space-xxx会根据实际窗口大小进行对齐,其中between会某一轴两侧的元素会紧贴,而around会留白

通过这两条属性可以快速地完成元素对齐,而不是设定float和margin来确定对齐方式

控制flex元素

然后考虑容器中的元素,最基本的有三个属性对元素进行具体地设定

【元素空间】是指元素占用的width、height大小,所有元素空间以外的在flex容器中的空间称为【可用空间】

在设定对齐时留白部分会根据可用空间自动设定

其中flex-basis用于设定主轴的占据的空间大小

flex-basis属性值 说明
auto 默认,根据容器自动生成(一般是铺满)
长度单位

设定了元素空间后,还有一个方面可用空间。flex-grow、flex-shrink用于设定如何使用可用空间,尤其是主轴长度不定(在下面章节会说明这种情况)时即可用空间不定时如何处理。

flex-grow说明了在可用空间存在的情况下,如何按比例伸长分配主轴上的空间

flex-shrink说明了在没有可用空间即容器没有足够空间容纳下元素的情况下,即溢出时如何收缩以保证不会溢出

这两个属性均是按照flex-basis按比例伸缩

比如要设定元素大小在主轴上是2:1:1的,在有可用空间的情况可以设定flex-grow分别为2:1:1,在无可用空间的情况可以设定flex-shrink分别为1:1.5:1.5

flex-grow/flex-shrink属性值 说明
长度单位 默认0即不伸缩,略

此外可以使用flex复合属性进行设置,顺序为flex-grow→flex-shrink→flex-basis

flex属性值 说明
none 默认,0 0 auto
auto 1 1 auto
x y z

flex属性体现了flex模型的伸缩特点,可以根据具体不同的情况来进行保持,比如电脑浏览器屏幕和实际屏幕宽度就不同,这时候可以使用flex来自适应屏幕大小

此外还比如隐藏一些flex元素,浏览器会因此而重新排列以保证其布局的结构

其他小细节

align-content设定的是总体的关于交叉轴的排列方式,此外还有两个设置交叉轴的排列方式的属性

align-items设定的是交叉轴的排列方式,与align-content的区别是align-content针对是总体的排列,而align-items针对的是多个不同交叉轴的排列

在具体处理上也稍有不同,比如元素在交叉轴上的长度并不一定相等。align-content会视为同一高度,而align-items则不会

align-self则会具体的详细到哪一个flex元素,align-self可以覆盖align-items

通过这些可以为布局提供更高的灵活性

align-items/align-self属性值 说明
auto 默认,继承父元素,若父元素未指定则为stretch
stretch 拉伸自适应flex容器
center
flex-start
flex-end
baseline 位于容器基线上

十八、Grid布局

Grid类似于html的表格,能够按行/列对齐元素,但网格比表格要更加简单

Flex可以完成的Grid当然也能完成,可以解决大部分的布局问题。功能丰富也意味着更加复杂,学习起来要更麻烦

案例——可以查看这个网站上关于grid布局的案例,可以实现很多以往布局包括flex很难实现的不可思议的效果

小游戏——像另外一个玩选择器游戏的网站通过游戏来学习grid

A Complete Guide to Grid

CSS Grid Starter Layouts

Getting Started with CSS Grid

基本术语

网格(Grid)

网格轴(Grid Axis):网格是二维布局方法,分为横轴和纵轴

网格单元格(Grid Cell):是网格的最小单元

网格线(Grid Lines):区分网格的辅助线

网格轨道(Grid Tracks):是指相邻网格线之间的空间

网格行(Grid Row):网格的水平轨道

网格列(Grid Column):网格的垂直轨道

网格区域(Grid Areas):由网格单元格构成的矩形区域

网格间距(Gutters):网格轨道之间的间距

创建轨道和网格线

在此灵活运用网格之前,需要创建网格

CSS提供了这些属性创建

grid-template-rows、grid-template-columns

用来创建轨道和网格线

其中参数数量是不限定的,有几个数量就代表创建几行几列,比如下面的例子创建了4行3列的网格

div{
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
    grid-template-rows: 1fr 1fr 1fr 1fr;
    /*fr是CSS的长度单位,grid经常用到*/
}

在创建网格轨道的同时也同时创建了网格线,网格线可以用F12看到。如此例创建了5个水平4个垂直的网格线,网格线默认是从1开始的

属性值 说明
none 默认,由隐式属性grid-auto-rows/columns生成
长度单位
备注:fr是flex类型的长度单位即具有伸缩性

根据上图可以看到网格线

/*@font-face {
	font-family: font1;
	src: url("华康少女文字 - Kelvin.ttf");
}* {font: 18px font1;}*/
#grid {
	display: grid;
	width: 100%;
	height: 300px;
	grid-template-columns: 1fr 1fr;
	grid-template-rows: 1fr 1fr 1fr 1fr;
    /*生成4行2列的网格*/
}
.c1 {
	background: red;
}
.c2 {
	background: palegreen;
}
.c3 {
	background: skyblue;
}
.c4 {
	background: plum;
}

命名轨道

上述属性除了基本的创建网格轨道、网格线还可以对网格轨道进行命名

1.不同轨道的名字是可以相同的,没有硬性规定

2.同一轨道可以有多个名字

3.对于重复部分,可以简单用repeat()函数

#grid {
	display: grid;
	width: 100%;
	height: 300px;
	grid-template-columns: repeat(2,1fr [c]);
    /*创建2条名字都是c的轨道*/
	grid-template-rows: [r1 r2] 1fr [r2] 1fr [r3] 1fr [r4] 1fr;
    /*第一条轨道名字有r1和r2*/
}

创建网格区域

通过grid-template-areas和grid-area可以创建网格区域,用于合并多个单元格以完成更加灵活的布局

需要先使用grid-area设定网格区域

然后使用grid-template-areas设定布局方式

其中grid-template-areas用一组字符串来表示结构,其中在某一字符串上的元素必须相连,否则会出bug

可以用.表示空的单元格即无内容

<style>
    .grid {
        display: grid;
        grid-template-columns: 1fr 2fr 1fr;
        grid-template-rows: repeat(3, 1fr);
        grid-template-areas: 
            "a1 a1 a1"
            "a2 a3 a4"
            "a5 a5 a5";
        /*可以尝试这一组"a1 a1 ." ". . a5" "a2 a3 a4"*/
        /*这种布局像填表游戏一样,但效果确是非常强大的*/
        grid-gap: 1em;
    }
    
    header,
    aside,
    article,
    footer {
        background: grey;
        height: 100px;
        text-align: center;
    }
    
    header {
        grid-area: a1;
    }
    
    .sidebar-left {
        grid-area: a2;
    }
    
    article {
        grid-area: a3;
    }
    
    .sidebar-right {
        grid-area: a4;
    }
    
    footer {
        grid-area: a5;
    }
</style>

<div class="grid">
    <header>Header</header>
    <aside class="sidebar-left">Left Sidebar</aside>
    <article>Article</article>
    <aside class="sidebar-right">Right Sidebar</aside>
    <footer>Footer</footer>
</div>

grid-template

复合属性,顺序:

grid-template-rows→grid-template-columns

其中子属性之间用/隔开,如

.grid {
	display: grid;
    grid-template 1fr 2fr 1fr / repeat(3,1fr);
}

间隙

此外网格与网格之间可以设置间距

总共有两个属性:

row-gap、column-gap

grid-row-gap、grid-column-gap

带有grid前缀的功能一样,但为了保证兼容性有时可能仍然需要带前缀的

row-gap: 10px;
/*设置网格水平方向上间距10px*/
column-gap: 50px;
/*设置网格垂直方向上间距50px*/

备注:需要注意的是不会在外边缘创建,只会定义内部的间隙(参考flex中space-between和space-around的区别)

grid-gap(gap)

复合属性,顺序:

row-gap、column-gap

备注:grid


十九、图像拼合(精灵图)


二十、响应式布局



参考网站

w3cschool

MDN CSS

HTML.net CSS

CSS specifishity

grid布局案例

grid小游戏

A Complete Guide to Grid

CSS Grid Starter Layouts

Getting Started with CSS Grid

posted on 2022-04-06 23:52  摸鱼鱼的尛善  阅读(211)  评论(0编辑  收藏  举报