整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

HTML+CSS:css元素浮动详解,使用浮动制作导航栏菜单

天这篇文章我们来说一下css的浮动属性(float),给块状元素添加float属性可以使其转变为行内元素,也就是我们所说标签对象浮动居左靠左(float:left)和浮动居右靠右(float:right)。

(1)float使用语法

css的float主要有3个属性值none、left、right,默认为none;具体的使用如下所示:

float:none; (不使用浮动)

float:left; (靠左浮动)

float:right; (靠右浮动)

(2)float使用案例

我们通过案例来实际演练一下float元素的使用技巧。

1、float:left的使用练习

我们这里创建一个导航条,导航条包含首页、关于我们、新闻中心、案例展示等栏目名称。具体的网页代码以及显示效果就如下图所示:

由上图可以看出默认的样式是竖排显示的,但是我们常见的网页导航条都是横排显示的,这时候我们就可以使用float属性来使块状元素转变为行内元素,并让居左显示。

这里我们创建一个宽度为980px的导航条,给子元素(li)添加float的属性并对齐进行填充(padding)以及外间距(margin)的润色。具体的网页代码以及显示效果就如下图所示:

网页中的显示效果:

2、float:right的使用练习

float:right顾名思义用于元素靠右对齐,我们来看下面的一个例子,我们随意写一篇文字,然后文字中插入一张图片并使图片右对齐。

我们再网页中可以看到图片已经浮动到网页的右侧中去了。

好了,本篇文章就给大家说到这里,大家可以注意看下我们使用float之后会出现什么问题,下边文章我们会给大家讲解如何清除float带来的负面影响。


每日金句:你不能拼爹的时候,你就只能去拼命!喜欢我的文章的小伙伴记得关注一下哦,每天将为你更新最新知识。

实文章原名叫做 “碰到不支持 flex 的项目怎么办?”

现在差不多已经是 flex 的天下了,简单灵活,但有时还是不可避免地会接触到 IE 浏览器,比如我最近接触的 阅文作家专区 (qq.com)[1],这个就是需要兼容 IE9, 也自然不能使用 flex 布局了。不能使用 flex 怎么办(这个项目怎么这么XX,都 2021 年了还要兼容 IE)?那只能回归传统布局方式了,也就是浮动布局。

浮动 float 可以说是 CSS 布局里最为灵活的布局之一了,千万不要小瞧了浮动,有些布局只有浮动才能实现呢。下面将介绍几种常见的布局,一起看看吧

一、文本环绕布局

这类布局应该就是浮动最初的用意了,比如这样的

设置一个左浮动就可以了,实现如下

<div>
  <strong class="float">浮</strong>
  <p>动属性指定一个元素应沿其容器的左侧或右侧放置,允许文本和内联元素环绕它。该元素从网页的正常流动(文档流)中移除,尽管仍然保持部分的流动性。</p>
</div>
.float{
  float: left;
  /*其他样式*/
}

完整代码可访问 float-layout (codepen.io)[2]

需要注意的是,浮动元素必须放在文本的前面( HTML 结构),如果放在文本后面

<div>
  <p>动属性指定一个元素应沿其容器的左侧或右侧放置,允许文本和内联元素环绕它。该元素从网页的正常流动(文档流)中移除,尽管仍然保持部分的流动性。</p>
  <strong class="float">浮</strong>
</div>

那么就会变成这样

也就是说,浮动的影响范围是由浮动元素在 HTML 中的结构决定的,这一点非常重要

不过,现在很少会见到这种环绕布局了,但有些时候这种思路还是挺有用的,比如在这篇文章 CSS 实现多行文本“展开收起” (juejin.cn)[3],里面就用到了浮动的特性,实现了右下角文本环绕的效果,有兴趣的可以看看

二、两栏布局

两栏布局的特点是左边是固定尺寸,右边自动撑满剩余空间,例如

结构如下

<div class="crad">
  <img class="head" src="xxx.jpg">
  <p class="info">浮动属性指定一个元素应沿其容器的左侧或右侧放置,允许文本和内联元素环绕它。该元素从网页的正常流动(文档流)中移除,尽管仍然保持部分的流动性。</p>
</div>

浮动实现如下,主要是文本需要设置 overflow: hidden 。这里就不谈实现原理(BFC)了,有兴趣深究的可以查看这篇文章 CSS深入理解流体特性和BFC特性下多栏自适应布局[4]

.head{
  float: left;
}
.info{
  overflow: hidden;
}

如果右边是固定尺寸,比如这样的

这种情况如何处理呢?很多人可能会想到右浮动,没错,但是要注意,HTML 结构不需要改动,也就是浮动元素仍然在文本的前面

.head{
  float: right;
}

值得注意的是,如果需要设置两栏的间距 margin,需要设置在浮动元素

.head{
  float: left;
  margin-right: 8px;
}

完整代码可访问 float-2-cols[5]

三、三栏布局

三栏布局的特点是左右是固定尺寸,中间自动撑满剩余空间,例如

结构如下

<div>
  <img class="head" src="xxx.jpg">
  <div class="right">编辑</div><!--注意是在文本的前面-->
  <p class="info">浮动属性指定一个元素应沿其容器的左侧或右侧放置,允许文本和内联元素环绕它。该元素从网页的正常流动(文档流)中移除,尽管仍然保持部分的流动性。</p>
</div>

注意,这里位于右侧的按钮在 HTML 结构中仍然是在文本的前方,只需要设置右浮动就行了

.head{  
  float: left;
}
.info{  
  overflow: hidden;
}
.right{  
  float: right;  
  margin-left: 8px;  /*其他样式*/
}

完整代码可访问 float-3-cols (codepen.io)[6]

四、文本省略跟随布局

还有一类比较常见但是有些棘手的布局,是这样的

1.当文本比较多时,超出隐藏,标签文本在最右边2.当文本比较少时,标签文本跟随文本

示意如下

这里如何使用浮动实现呢?仔细观察,其实就是一个两栏布局

<div class="card">    
  <div class="right">编辑</div>  
	<p class="info">浮动属性指定一个元素应沿其容器的左侧或右侧放置,允许文本和内联元素环绕它。该元素从网页的正常流动(文档流)中移除,尽管仍然保持部分的流动性。一直平移直到碰到了所处的容器的边框,或者碰到另外一个浮动的元素。</p>
</div>
.info{  
  overflow: hidden;  
  white-space: nowrap;  
  text-overflow: ellipsis;
}

很明显现在标签文本一直位于右边,那如何实现标签文本跟随的效果呢?其实可以嵌套一个最大宽度为 100% 的容器

<div class="card">  
  <div class="wrap"> <!--添加一个最大宽度为100%的容器-->        
    <div class="right">标签</div>        
		<p class="info">浮动属性指定一个元素应沿其容器的左侧或右侧放置,允许文本和内联元素环绕它。该元素从网页的正常流动(文档流)中移除,尽管仍然保持部分的流动性。一直平移直到碰到了所处的容器的边框,或者碰到另外一个浮动的元素。</p>  
	</div>
</div>
.wrap{  
  display: inline-block;  
  max-width: 100%;
}

完整代码可访问 float-auto-text (codepen.io)[7]

如果不考虑兼容的话,width: fit-content 会是更好的选择,可以使容器保持 block 的特性,并且宽度由文本内容决定,详细可以参考这篇文章: 理解CSS3 max/min-content及fit-content等width值 [8]

.wrap{  
  /*display: inline-block;*/  
  max-width: 100%;  
  width: fit-content;
}

另外,如果多行文本就不适用了,可以用另一种方式实现,详细原理可以查看这篇文章 CSS 实现多行文本“展开收起” (juejin.cn)[9]

完整代码可访问float-mul-tags (codepen.io)[10]

五、其他扩展布局

这一部分相当于以上的扩展了,下面来看一个案例。

有时候标签的后面会有日期,会一直位于最右边,效果如下

有人可能会想到绝对定位,但是这里的日期可能不是固定的,需要自适应宽度,那如何实现呢?其实就是就是两种布局的结合

因此需要再添加一层容器,实现如下

<div class="card">    
  <span class="date">6-14</span>    
	<div class="outer-wrap"> 
  	<!--新加一层容器-->        
  	<div class="wrap">            
    	<div class="right">                
      	<button class="btn">标签</button>            
			</div>            
			<p class="info">浮动属性指定一个元素应沿其容器的左侧或右侧放置,允许文本和内联元素环绕它。该元素从网页的正常流动(文档流)中移除,尽管仍然保持部分的流动性。一直平移直到碰到了所处的容器的边框,或者碰到另外一个浮动的元素。</p>    
		</div>  
	</div>
</div>

下面就是两栏布局的写法

.date{  
  float: right;
}
.outer-wrap{ 
  overflow: hidden;
}

提示:如果采用 fit-content 方式,可以省去 .outer-wrap 这一层容器

实时效果如下

完整代码可访问 float-auto-text-fixed (codepen.io)[11]

六、总结和说明

上面介绍了浮动布局的几个常用案例,相信能适用于绝大部分布局,当然并不是推荐大家一定要使用浮动布局,甚至有时候布局混乱(HTML结构与视觉不一致)、实现啰嗦(嵌套层级多)等情况,但是在不兼容 flex 布局的浏览器中还是挺有用的(低于IE10),甚至还有仅仅只能使用浮动才能实现的布局(文本环绕)。这里总结如下

1.通过 BFC 实现自适应弹性布局,float + overflow2.浮动的影响范围是由浮动元素在 HTML 中的结构决定的3.通过设置最大宽度实现文本跟随效果(fit-content也可以)4.其他布局可相互组合实现5.另外这些 float 实现方式全兼容(IE6+),可以放心使用

随着 IE 地逐渐退去,有些布局也会慢慢地淡出,就像早年的 table 布局一样。但浮动布局一直在往新特性上发展,比如 Shapes 布局[12]就需要浮动做支持,另外,浮动布局也在慢慢支持逻辑属性,比如 float: inline-start 。最后,CSS 最重要的是灵活性,多一种思路总是没错的。如果觉得还不错,对你有帮助的话,欢迎点赞、收藏、转发❤❤❤

References

[1] 阅文作家专区 (qq.com): https://write.qq.com/
[2] float-layout (codepen.io):
https://codepen.io/xboxyan/pen/RwpqWvJ
[3] CSS 实现多行文本“展开收起” (juejin.cn):
https://juejin.cn/post/6963904955262435336
[4] CSS深入理解流体特性和BFC特性下多栏自适应布局:
https://www.zhangxinxu.com/wordpress/2015/02/css-deep-understand-flow-bfc-column-two-auto-layout/
[5] float-2-cols:
https://codepen.io/xboxyan/pen/WNpYQLB
[6] float-3-cols (codepen.io):
https://codepen.io/xboxyan/pen/oNZQLWB
[7] float-auto-text (codepen.io):
https://codepen.io/xboxyan/pen/poeQbYo
[8] 理解CSS3 max/min-content及fit-content等width值 :
https://www.zhangxinxu.com/wordpress/2016/05/css3-width-max-contnet-min-content-fit-content/
[9] CSS 实现多行文本“展开收起” (juejin.cn):
https://juejin.cn/post/6963904955262435336
[10] float-mul-tags (codepen.io):
https://codepen.io/xboxyan/pen/PopWVNX
[11] float-auto-text-fixed (codepen.io):
https://codepen.io/xboxyan/pen/WNpYJpN
[12] Shapes 布局:
https://www.zhangxinxu.com/wordpress/2019/02/css-css3-shapes

动是css里面布局用的最多的属性。

一个span标签不需要转成块级元素, 就能够设置宽度、高度了。所以能够证明一件事儿, 就是所有标签已经不区分行内、块了。

也就是说, 一旦一个元素浮动了, 那么, 将能够并排了, 并且能够设置宽高了, 无论它原来是个div还是个span。

浮动的性质:脱标、贴边、字围、收缩。

浮动的元素脱标

<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Document</title>
<style type="text/css">
.box1{
    float: left;
    width: 300px;
    height: 400px;
    background-color: yellowgreen;
}
.box2{
    float: left;
    width: 400px;
    height: 400px;
    background-color: skyblue;
}
</style>
</head>
<body>
<div class="box1"></div>
<div class="box2"></div>
</body>
</html>

两个元素并排了, 并且两个元素都能够设置宽度、高度了。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Document</title>
<style type="text/css">
span{
    float: left;
    width: 200px;
    height: 200px;
    background-color: orange;
}
</style>
</head>
<body>
<span>我是span</span>
<span>我是span</span>
<span>我是span</span>
<span>我是span</span>
<span>我是span</span>
</body>
</html>

一个span标签不需要转成块级元素, 就能够设置宽度、高度了。所以能够证明一件事儿, 就是所有标签已经不区分行内、块了。

也就是说, 一旦一个元素浮动了, 那么, 将能够并排了, 并且能够设置宽高了, 无论它原来是个div还是个span。

浮动的元素互相贴靠

<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Document</title>
<style type="text/css">
body{
    font-size: 60px;
}
.box1{
    float: left;
    width: 100px;
    height: 100px;
    background-color: yellowgreen;
}
.box2{
    float: left;
    width: 120px;
    height: 220px;
    background-color: gold;
}
.box3{
    float: left;
    width: 340px;
    height: 300px;
    background-color: skyblue;
}
</style>
</head>
<body>
<div class="box1">1</div>
<div class="box2">2</div>
<div class="box3">3</div>
</body>
</html>

浮动的元素有"字围"效果

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Document</title>
<style type="text/css">
div{
float: left;
width: 344px;
height: 516px;
background-color: orange;
}
</style>
</head>
<body>
<div>
<img src="images/1.jpg" alt="" />
</div>
<p>123文字文字文字文字文字文字字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文字文</p>
</body>
</html>

div挡住了p, 但是p中的文字不会被挡住, 形成"字围"效果。 如果将p标记换成div, 则不会有"字围"效果。

详细案例见:CSS|实例|图文混排

收缩:一个浮动的元素, 如果没有设置width, 那么将自动收缩为文字的宽度(这点非常像行内元素)。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Document</title>
<style type="text/css">
div{
float: left;
background-color: gold;
}
</style>
</head>
<body>
<div>我是文字</div>
</body>
</html>

浮动的清除

实验:现在有两个div, div身上没有任何属性。每个div中都有li, 这些li都是浮动的。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Document</title>
<style type="text/css">
li{
float: left;
width: 90px;
height: 40px;
background-color: gold;
/*文本居中*/
text-align: center;
}
</style>
</head>
<body>
<div>
<ul>
<li>HTML</li>
<li>CSS</li>
<li>JS</li>
<li>HTML5</li>
<li>设计模式</li>
</ul>
</div>
<div>
<ul>
<li>学习方法</li>
<li>英语水平</li>
<li>面试技巧</li>
</ul>
</div>
</body>
</html>

我们本以为这些li, 会分为两排, 但是, 第二组中的第1个li, 去贴靠第一组中的最后一个li了。

第二个div中的li, 去贴第一个div中最后一个li的边了。

原因就是因为div没有高度, 不能给自己浮动的孩子们, 一个容器。

清除浮动方法1:给浮动的元素的祖先元素加高度。缺陷: 只限于父元素高度确定的情况下。

如果一个元素要浮动, 那么它的祖先元素一定要有高度。高度的盒子, 才能关住浮动。

解决方法:

<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Document</title>
<style type="text/css">
*{
margin: 0;
padding:0;
}
div{
height: 50px; /* 为父元素设置高度 */
border: 1px solid #000;
}
li{
float: left;
width: 90px;
height: 40px;
margin-right: 10px;
background-color: gold;
/*文本居中*/
text-align: center;
}
</style>
</head>
<body>
<div>
<ul>
<li>HTML</li>
<li>CSS</li>
<li>JS</li>
<li>HTML5</li>
<li>设计模式</li>
</ul>
</div>
<div>
<ul>
<li>学习方法</li>
<li>英语水平</li>
<li>面试技巧</li>
</ul>
</div>
</body>
</html>

清除浮动方法2:clear:both;

网页制作中, 高度height很少出现。为什么? 因为能被内容撑高! 那也就是说, 刚才我们讲解的方法1, 工作中用的很少。

脑弄大开:能不能不写height, 也把浮动清除了呢? 也让浮动之间, 互不影响呢?

clear:both;

clear就是清除, both指的是左浮动、右浮动都要清除。意思就是:清除别人对我的影响。

这种方法有一个非常大的、致命的问题, margin失效了。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Document</title>
<style type="text/css">
*{
margin: 0;
padding:0;
}
li{
float: left;
width: 120px;
height: 40px;
text-align: center;
background-color: orange;
}
.box2{
clear: both;
}
</style>
</head>
<body>
<div class="box1">
<ul>
<li>HTML</li>
<li>CSS</li>
<li>JS</li>
<li>HTML5</li>
<li>设计模式</li>
</ul>
</div>
<div class="box2">
<ul>
<li>学习方法</li>
<li>英语水平</li>
<li>面试技巧</li>
</ul>
</div>
</body>
</html>

清除浮动方法3:隔墙法

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Document</title>
<style type="text/css">
*{
margin: 0;
padding:0;
}
.box1{
background-color: gold;
}
li{
float: left;
width: 120px;
height: 40px;
background-color: orange;
text-align: center;
}
.cl{
clear: both;
}
.h8{
height: 8px;
_font-size:0;
}
.h10{
height: 10px;
_font-size:0;
}
.h12{
height: 12px;
_font-size:0;
}
</style>
</head>
<body>
<div class="box1">
<ul>
<li>HTML</li>
<li>CSS</li>
<li>JS</li>
<li>HTML5</li>
<li>设计模式</li>
</ul>
</div>

<div class="cl h8"></div>
<div class="box2">
<ul>
<li>学习方法</li>
<li>英语水平</li>
<li>面试技巧</li>
</ul>
</div>
</body>
</html>

墙! <div class="cl h18"></div>

这个墙, 隔开了两部分浮动, 两部分浮动, 互不影响。

近些年, 有演化出了"内墙法":

<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Document</title>
<style type="text/css">
*{
margin: 0;
padding:0;
}
.box1{
background-color: gold;
}
li{
float: left;
width: 120px;
height: 40px;
background-color: orange;
text-align: center;
}
.cl{
clear: both;
}
.h16{
height: 16px;
}
</style>
</head>
<body>
<div class="box1">
<ul>
<li>HTML</li>
<li>CSS</li>
<li>JS</li>
<li>HTML5</li>
<li>设计模式</li>
</ul>
<div class="cl h16"></div>
</div>
<div class="box2">
<ul>
<li>学习方法</li>
<li>英语水平</li>
<li>面试技巧</li>
</ul>
</div>
</body>
</html>

内墙法本质-给没有高的父亲撑出高

因为一个父元素不可能被浮动的子元素撑出高度, 解决的方法:内墙法

<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Document</title>
<style type="text/css">
*{
margin: 0;
padding: 0;
}
div{
background-color: blue;
}
p{
float: left;
width: 100px;
height: 100px;
background-color: green;
}
.cl{ /* 如果没有清除浮动 , 则父元素的盒子没有高度, <div>盒子只是一条线*/
clear: both;
}
</style>
</head>
<body>
<div>
<p></p>
<div class="cl"></div>
</div>
</body>
</html>

清除浮动方法4:overflow:hidden;

overflow就是"溢出"的意思, hidden就是"隐藏"的意思。

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Document</title>
<style type="text/css">
div{
width: 300px;
height: 300px;
border: 1px solid red;
overflow: hidden;
}
</style>
</head>
<body>
<div>内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容内容</div>
</body>
</html>

本意就是清除溢出到盒子外面的文字。但是, 前端开发工程师又发现了, 能做偏方。

一个父亲不能被自己浮动的儿子,撑出高度。但是, 只要给父亲加上overflow:hidden; 那么, 父亲就能被儿子撑出高了。这是一个偏方。

div{
    width: 400px;
    border: 10px solid black;
    overflow: hidden;
}
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Document</title>
<style type="text/css">
*{
margin: 0;
padding: 0;
}
div{
width: 400px;
overflow: hidden;
border: 10px solid black;
}
.p1{
float: left;
width: 100px;
height: 150px;
background-color: red;
}
.p2{
float: left;
width: 100px;
height: 380px;
background-color: yellow;
}
.p3{
float: left;
width: 100px;
height: 120px;
background-color: blue;
}
</style>
</head>
<body>
<div>
<p class="p1"></p>
<p class="p2"></p>
<p class="p3"></p>
</div>
</body>
</html>

浮动清除方法5: 利用伪元素清除浮动