CSS相当于网页的血肉,如果没有CSS,网页只能显示内容,但是不够美观,但是要想显示一个足够美观和直观的网页,学会布局是必要的。今天介绍一下浮动、定位、弹性盒子布局,其中部分就以我自己写的网页作为例子,介绍它们的应用场景和实操实践。
浮动 (float)
说实话,在我初学CSS的时候,我还会用浮动实现一些布局,比如说侧边栏,又比如说导航栏左右两侧的内容。但是在学会
flex
和grid
布局之后就很少用了,因为float布局能实现的这两个都能实现,但是float
又会有一些问题,因为float
之后元素会被移出文档流
float
言归正传,浮动布局是一种经典的CSS布局方式,早期被广泛用于实现多栏布局。元素通过float
属性可以在一行内排列,并通过clear
属性控制下一行的排列方式。
基本使用
值 | 效果 |
---|---|
left | 表明元素必须浮动在其所在的块容器左侧 |
right | 表明元素必须浮动在其所在的块容器右侧 |
none | 不浮动 |
inline-start | 表明元素必须浮动在其所在块容器的开始一侧,在 ltr 脚本中是左侧,在 rtl 脚本中是右侧 |
inline-start | 表明元素必须浮动在其所在块容器的结束一侧,在 ltr 脚本中是右侧,在 rtl 脚本中是左侧 |
说了理论知识,我们来用豆包AI练中学提供的前端环境试一下(父元素无浮动,padding: 10px
)
我们可以发现,第一个元素父元素的高度没了,只剩padding
,这就是最开始提到的float
的问题之一,高度塌陷,如果一个不浮动的元素的所有子元素都是浮动的,那就没有子元素能撑起父元素的高度。第二个就好多了,因为有一个元素没有浮动,可以撑起父元素高度。
同时我们也能发现,即使左侧浮动了,但是右侧元素仍然会给左侧元素留下位置,并不会被覆盖部分文字
完整代码
<head>
<meta charset="utf-8" />
<title>Code Example</title>
<style>
* {
box-sizing: border-box;
}
.container {
width: 100%;
padding: 10px;
background-color: darkgreen;
}
.sidebar {
width: 25%;
background-color: cyan;
float: left;
}
.content {
width: 75%;
background-color: yellow;
float: right;
}
</style>
</head>
<body>
<div class="container">
<div class="sidebar">侧栏(float: left)</div>
<div class="content">内容(float: right)</div>
</div>
<br>
<br>
<div class="container">
<div class="sidebar">浮动左侧</div>
<div class="normal">普通内容</div>
</div>
</body>
clear
说到float
,不得不提的就是clear
,这两个总是一起出现。clear
指定一个元素是否必须移动 (清除浮动后) 到在它之前的浮动元素下面。clear 属性适用于浮动和非浮动元素,光说不太直观,我们现在来尝试给之前的代码加上clear: both
然后我们会发现,当clear: both
加到container
或sidebar
元素上时,不会有视觉上的差异,但是加到第二个子元素上时
我们可以发现,两个容器的第二个子元素都跑到了第一个子元素的下方,这也就是前边说的 clear
CSS属性指定一个元素是否必须移动 (清除浮动后) 到在它之前的浮动元素下面。clear
属性适用于浮动和非浮动元素。
定位 (position)
position
属性用于指定一个元素在文档中的定位方式top
bottom
left
right
属性则决定了该元素的最终位置。
取值
position
可能的取值有:
static
: 该关键字指定元素使用正常的布局行为,即元素在文档常规流中当前的布局位置。此时top
,right
,bottom
,left
和z-index
属性无效。relative
: 该关键字下,元素先放置在未添加定位时的位置,再在不改变页面布局的前提下调整元素位置(因此会在此元素未添加定位时所在位置留下空白)。position:relative
对table-*-group
,table-row
,table-column
,table-cell
,table-caption
元素无效。absolute
: 元素会被移出正常文档流,并不为元素预留空间,通过指定元素相对于最近的非static
定位祖先元素的偏移,来确定元素位置。绝对定位的元素可以设置外边距(margin
),且不会与其他边距合并。fixed
: 元素会被移出正常文档流,并不为元素预留空间,而是通过指定元素相对于屏幕视口(viewport)的位置来指定元素位置。元素的位置在屏幕滚动时不会改变。打印时,元素会出现在的每页的固定位置。fixed
属性会创建新的层叠上下文。当元素祖先的transform
、perspective
、filter
或backdrop-filter
属性非none
时,容器由视口改为该祖先。sticky
: 元素根据正常文档流进行定位,然后相对它的最近滚动祖先(nearest scrolling ancestor)和containing block
(最近块级祖先 nearest block-level ancestor),包括 table-related 元素,基于top
、right
、bottom
和left
的值进行偏移。偏移值不会影响任何其他元素的位置。
基础使用
实际应用
用的最多的就是相对定位和绝对定位了,所以这次拿一个常见的例子做示范,这两个也是相辅相成的,因为绝对定位的元素是以最近的相对定位元素为基准的。
先来看个之前写的模仿Bilibili主页的静态网页
左侧的下载客户端,包括游戏中心等,在鼠标悬浮时都会显示额外的面板,这个面板就是通过绝对定位实现的,也是很常见的一种设计方式。原理就是父元素(以下称
#par
)包括正常的内容(以下称#normal
),以及一个默认隐藏的要悬浮的元素(以下称#panel
),通过设置#par
的hover
事件,来控制#panel
的显示,基本原理如下
/* 仅部分代码 */
#par {position: relative;}
#panel {position: absolute; display: none;}
#par:hover #panel {display: block;}
弹性布局 (flex)
这是很常用的单行/单列布局方式,我们先要了解一下基础的知识。
Flex容器(flex container):定义display: flex
或display: inline-flex
的元素就是Flex容器,其子元素称为Flex子项。
主轴(main axis)和交叉轴(cross axis) :主轴是Flex容器布局的方向,默认是水平的(从左到右),而交叉轴则垂直于主轴。
Flex的常用属性
flex-direction
:定义主轴方向,控制子元素的排列方式(例如:水平或垂直)。justify-content
:控制主轴上的子元素对齐方式(如左对齐、右对齐、居中、分散)。align-items
、align-content
:控制交叉轴上的子元素对齐方式。flex-grow
、flex-shrink
、flex-basis
:控制子元素在容器中的扩展、收缩和初始大小。
实际应用
1. 一个常见的问题
我们在实际应用flex
嵌套时可能会出现子元素过长,导致父元素被撑开显示不正确的问题,原因是flex父元素的最小宽高默认是被内容撑开的,
来看个例子:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Code Example</title>
<style>
* {
box-sizing: border-box;
}
.container {
background-color: green;
display: flex;
padding: 10px;
}
.child {
background-color: cyan;
width: 800px;
}
.main {
display: flex;
padding: 5px;
background-color: peru;
}
.w400 {
width: 400px;
}
.w800 {
width: 600px;
}
</style>
</head>
<body>
<div class="container w800">
<div class="main">
<div class="w400">我是400px宽度</div>
<div class="child">asdasdas</div>
</div>
</div>
</body>
</html>
如果将图中开发者工具的
min-width
启用,那么黄色的main元素就会收到绿色父元素的约束,宽度不会超过绿色的800x
2. 元素居中
在学习布局以前,我们想让一个元素的子元素左右上下都居中,只能通过设置width: auto等复杂的方法,尤其是垂直居中也很困难,但是现在我们只需要
#element {
display: flex;
align-items: center;
justify-content: center;
}
#element
的子元素就完全居中了