1、前言
在CSS开发中,很重要的一个工作就是根据UI设计稿,进行元素的布局与定位,使得元素(比如某一段文本、按钮、图片等)显示在页面正确的位置。本文就元素的布局与定位方面,做一些讲解和说明。
2、元素的定位方法
元素有很多布局和定位方法。常见的布局和定位方法有:
- 标准文档流布局
- Flexbox布局
- 绝对定位和相对定位
- Grid布局
- 浮动布局
下面就是上面的布局方式逐一进行举例讲解。
3、标准文档流布局
标准文档流布局是网页布局中一个最基本的概念,指的是元素按照HTML文档中的顺序,从上到下,从左到右排列。标准文档流分为两种类型的元素:块级元素(block-level elements)和内联元素(inline elements)。每种元素在文档流中排列方式略有不同。
块级元素(Block-level elements)
- 占据一整行:块级元素默认的情况下会独占一行,并且其宽度会自动扩展到父容器的宽度(除非)
- 从上到下排列:每个块级元素都会在其前一个块级元素的下面显示。
常见的块级元素有:<div>
、<p>
、<h1>
-<h6>
、<ul>
、<ol>
、<li>
、<section>
、<article>
、<header>
、<footer>
等。
内联元素(inline elements)
- 与文本共同行内:内联元素不会独占一行,多个内联元素可以在同一行中排列。
- 宽度由内容决定:内联元素的宽度通常由其内容决定,内联元素之间的间距由内容的空白符(如空格等)决定。
常见的内联元素有:<span>
、<a>
、<strong>
、<em>
、<img>
、<button>
、<input>
、<label>
等。
注意:本文中所有的举例都是基于react框架来演示。
// app.js
import './App.css';
function App() {
return (
<div className="App">
{/* 块级元素 */}
<div class="block-element">Block Element 1</div>
<div class="block-element">Block Element 2</div>
<div class="block-element">Block Element 3</div>
<p>Here are some <span class="inline-element">inline elements</span> in a paragraph.</p>
<p><span class="inline-element">Inline Element 1</span> <span class="inline-element">Inline Element 2</span> <span class="inline-element">Inline Element 3</span></p>
</div>
);
}
export default App;
/* app.css */
.block-element {
background-color: lightcoral;
margin: 20px 20px; /*上下边距为20px, 左右边距为20px */
}
.inline-element {
background-color: lightblue;
}
显示效果如下:
结果分析 :
- 块级元素独占一整行,每个块级元素都会显示在前一个块级元素的下面
- 块级元素的边距不能叠加。比如块级元素1的下边距为20, 块级元素2的上边距也是20,但是两者之间的距离还是20。即相邻元素的边距会合并,最终边距为两者较大的值
- 多个内联元素可以在同一行显示
4、Flexbox布局
Flexbox是一种强大的CSS布局,用户创建响应式、动态的页面布局。通过flexbox,可以额轻松地排列、对齐和分布页面中的元素。
基本概念:
display: flex;
:将容器设置为 Flex 容器,它的所有直接子元素将成为 Flex 项目。flex-direction
:定义主轴的方向,即子元素在 Flex 容器中的排列方向。常用值有row
(默认,从左到右排列)和column
(从上到下排列)。justify-content
:定义 Flex 容器中子元素在主轴上的对齐方式。常用值有flex-start
、flex-end
、center
、space-between
和space-around
。align-items
:定义 Flex 容器中子元素在交叉轴上的对齐方式。常用值有stretch
(默认,子元素拉伸以适应容器)、flex-start
、flex-end
和center
。
示例说明:
// app.js
import React from 'react';
import './App.css';
function App() {
return (
<div class="container">
<header class="header">Header</header>
<main class="main-content">Main Content</main>
<footer class="footer">Footer</footer>
</div>
);
}
export default App;
/* app.css */
/* 将容器设置为 Flex 容器 */
.container {
display: flex;
flex-direction: column; /* 子元素从上到下排列 */
height: 50vh; /* 让容器占满半个屏幕高度 */
}
/* 子元素的样式 */
.header {
background-color: lightcoral;
padding: 20px; /* 内边距为20px, 元素内容和边框之间保持20px距离 */
text-align: center;
}
.main-content {
background-color: lightblue;
padding: 20px;
flex-grow: 1; /* 让主要内容区占据剩余的可用空间 */
}
.footer {
background-color: lightgreen;
padding: 20px;
text-align: center;
}
显示效果如下:
水平导航栏排列样式:
import React from 'react';
import './App.css';
function App() {
return (
<nav class="nav">
<div class="nav-item">Home</div>
<div class="nav-item">About</div>
<div class="nav-item">Services</div>
<div class="nav-item">Contact</div>
</nav>
);
}
export default App;
/* app.css */
.nav {
display: flex;
justify-content: space-around; /* 在主轴上均匀分布项目 */
background-color: #333;
}
.nav-item {
color: lightblue;
padding: 15px 20px;
}
显示效果如下 :
顺便说明一下,当块级元素没有设置宽度和高度时,宽度默认是充满整个父容器,高度会根据内容来来进行调整。
等高两列布局:
/* app.js*/
import React from 'react';
import './App.css';
function App() {
return (
<div class="two-columns">
<div class="column left">Left Column</div>
<div class="column right">Right Column</div>
</div>
);
}
export default App;
/* app.css */
.two-columns {
display: flex;
}
.column {
flex: 1; /* 每个列都占据相等的空间 */
padding: 20px;
}
.left {
background-color: lightblue;
}
.right {
background-color: lightcoral;
}
显示效果:
5、绝对定位和相对定位
在react中,元素的相对定位是使用CSS的postion:relative属性来实现的。相对定位的元素对于其在正常文档流中的原始位置进行偏移。这意味着即使元素被偏移了,它仍然会占据原来的空间。
相对定位的特点:
- 相对于自身:相对定位是相对于元素在文档流中的原始位置进行的,而不是相对于其它元素或者视口。
- 占保留位:元素会继续占据其原本的位置,其它元素的布局不会因为它的偏移而改变。
- 偏移量:通过top、bottom、right、left等属性设置偏移量,从而调整元素的位置。
示例说明:
// app.js
import React from 'react';
import './App.css';
function App() {
return (
<div className="container">
<div className="relative-box">I'm a relatively positioned box</div>
<div className="sibling-box">I'm a sibling box</div>
</div>
);
}
export default App;
/* app.css */
.container {
width: 400px;
height: 200px;
background-color: #f0f0f0;
position: relative; /* Container itself is relatively positioned */
}
.relative-box {
width: 150px;
height: 100px;
background-color: lightcoral;
position: relative; /* 相对定位 */
top: 20px; /* 向下偏移20px */
left: 30px; /* 向右偏移30px */
}
.sibling-box {
width: 150px;
height: 100px;
background-color: lightblue;
}
显示效果如下:
结果分析:
- 红色块级元素采用了相对定位,相对于它在文档流中的原始位置,向下偏移了20px,向右偏移了20px
- 绿色块级元素采用的默认的文档流定位,虽然红色块级元素进行了位置偏移,但是还是占据原来的位置(文档流中的位位置),因此位置不会受到红色块级元素位置偏移的影响。
顺便说一下,当元素的位置有重叠时,可以通过设置zIndex属性来调整元素显示的层次顺序。
zIndex越大,显示越靠上。但是zIndex属性只有当元素的 position
属性被设置为 relative
、absolute
、fixed
、或 sticky
之一时,z-index
才会生效。
总结:
- 相对定位的基准是相对于元素自身在文档流中的原始位置。
- 相对偏移不会影响到别的元素的位置。
绝对定位
在react中,使用CSS的positon:absolute来设置元素的绝对定位。绝对定位的元素相对于度最近的已经定位的祖先元素进行定位。如果没有找到已经定位的祖先元素,则相对于浏览器视口(窗口)进行定位。
绝对定位的特点:
- 脱离文档流:绝对定位的元素从文档流中完全脱离,不再占据空间,其它元素会像它不存在一样重新排列
- 定位基准:
- 如果祖先元素中有position设置为relative、absolute或fixed的元素,那么这个元素就是绝对定位的基准。
- 如果没有这样的元素,则相对于视口(浏览器窗口)进行定位。
- 通过top、bottom、right、left属性来设置偏移量,以决定元素的位置。
示例说明:
// app.js
import React from 'react';
import './App.css';
function App() {
return (
<div className="outer-container">
<div className="relative-container">
<div className="absolute-box">I'm absolutely positioned</div>
<div className="relative-box">I'm relative positioned</div>
</div>
</div>
);
}
export default App;
/* app.css */
.outer-container {
width: 400px;
height: 200px;
background-color: #f0f0f0;
position: relative; /* 外层容器相对定位 */
top:20px;
}
.relative-container {
width: 200px;
height: 100px;
background-color: lightblue;
position: relative; /* 内层容器相对定位 */
top:20px;
}
.absolute-box {
width: 100px;
height: 50px;
background-color: lightcoral;
position: absolute; /* 绝对定位 */
top: 20px; /* 相对于 .relative-container 的顶部偏移 20px */
left: 30px; /* 相对于 .relative-container 的左侧偏移 30px */
}
.relative-box {
width: 100px;
height: 50px;
background-color: lightskyblue;
position: relative; /* 绝对定位 */
top: 40px; /* 相对于 .relative-container 的顶部偏移 20px */
left: 60px; /* 相对于 .relative-container 的左侧偏移 30px */
}
显示效果如下:
结果分析:
- 可以看到绝对元素定位的基准是最近的已经定位的祖先元素,即这里是内层容器
- 绝对元素的定位不会影响其它元素的布局,比如relative box布局不会受到绝对元素影响
6、Grid布局
Grid布局是一种二维布局系统,允许你在一个容器中以行和列的形式对元素进行排列。它非常强大,适用于复杂的网格布局。
示例说明:
// app.js
import React from 'react';
import './App.css';
function App() {
return (
<div className="grid-container">
<div className="grid-item">1</div>
<div className="grid-item">2</div>
<div className="grid-item">3</div>
<div className="grid-item">4</div>
<div className="grid-item">5</div>
<div className="grid-item">6</div>
<div className="grid-item">7</div>
<div className="grid-item">8</div>
<div className="grid-item">9</div>
</div>
);
}
export default App;
// app.css
.grid-container {
display: grid;
grid-template-columns: repeat(3, 1fr); /* 3 列,每列等宽 */
gap: 10px; /* 每个网格项之间的间距 */
}
.grid-item {
background-color: lightblue;
padding: 20px;
text-align: center;
}
显示效果:
结果分析:
- 容器 (
grid-container
) 被定义为网格布局,grid-template-columns: repeat(3, 1fr)
创建了三个等宽的列。 - 网格项 (
grid-item
) 在网格中自动排列成 3 行 3 列的布局。 - 每个网格项都有
20px
的内边距,背景色为浅蓝色,并且内容居中。
7、浮动布局
浮动是一种传统的布局方式,通过将元素浮动在页面上,使其它内容围绕它们进行布局。通常用于创建简单的多列布局。
实例说明:
import React from 'react';
import './App.css';
function App() {
return (
<div className="container">
<div className="sidebar">Sidebar</div>
<div>This text will wrap around the sidebar. The sidbar is floated to the left, so the text flows to the right of the image and continues below it once the image height is exceeded.</div>
<div className="main-content">Main Content</div>
</div>
);
}
export default App;
.container {
overflow: hidden; /* 清除浮动 */
}
.sidebar {
float: left; /* 左侧浮动 */
width: 30%; /* 宽度为父容器的 30% */
background-color: lightgreen;
padding: 20px;
}
.main-content {
float: left; /* 左侧浮动 */
width: 70%; /* 宽度为父容器的 70% */
background-color: lightcoral;
padding: 20px;
}
显示效果:
结果分析:
-
元素向左侧浮动:
- 当你对一个元素应用
float: left;
时,该元素会从它的正常文档流位置脱离出来,并尽可能向其容器的左侧对齐。 - 其他未浮动的内容(如文本、图片等)会围绕这个浮动元素的右侧排布。
- 当你对一个元素应用
-
相邻元素环绕布局:
- 在浮动元素之后的相邻元素(如果没有设置浮动),通常会环绕浮动元素,填补浮动元素右侧的空白区域。
- 如果多个元素都设置了
float: left;
,它们会依次向左侧排列,并排布在同一行,直到容器的宽度被填满,之后多余的元素会移动到下一行。
-
常见应用:
- 多列布局:使用
float: left;
可以轻松实现多列布局,如左侧导航栏和右侧内容区的布局。 - 文本环绕图片:在网页设计中,经常将图片设置为左浮动,使文本环绕图片的右侧排列。
- 多列布局:使用
注意事项
- 浮动元素脱离文档流:浮动的元素不再占据其原始位置的空间,因此需要注意可能对后续布局的影响。
- 清除浮动:在使用浮动布局时,如果父容器没有正确处理浮动,可能会导致父容器的高度塌陷(因为浮动的元素不占据父容器的空间)。可以使用
clear: both;
或其他清除浮动的方法来解决这一问题。
总结
float: left;
的主要作用是将元素从正常文档流中脱离出来,使其浮动到父容器的左侧,并让其他内容在其右侧进行环绕布局。- 它被广泛用于实现多列布局和图文混排等场景,但现代布局通常更倾向于使用 Flexbox 或 Grid 替代浮动布局。