2017年8月

估计大多数人误解了float的原本设计初衷,但是这里的“误用”是要加引号的,因为这是一种无心插柳的应用。即,用float做网页布局是很合情合理的,鼓励同志们继续使用。

这篇文章主要是为了解决一个实际遇到的问题:
左右两列布局,左侧宽度固定,右侧宽度自适应(或左中右三列布局,左侧和中间宽度固定,右侧宽度自适应),当页面宽度变化时,怎样使右侧元素中的内容始终在页面剩余宽度中居中显示,设置了text-align: center;之后,问题其实也就是怎样让右侧元素的宽度占据页面剩余所有宽度。

基础知识:元素float之后的变化

1.原本为inline或原本为block的元素,设置了float: left 或 float: right之后,会变得具有inline-block元素的特性,即:不独占一行,且可以设置宽和高。
2.与position:absolute;的脱离文档流不同的是:float的几个元素,它们在同一个文档流中。
3.float半脱离文档流:两个元素中的前一个设置了float:left;,对于后续元素的元素来说,前一个元素是脱离文档流的,也就是会占据元素的位置;对于后续元素的内容来说,前一个元素又是占据文档流的,也就是不会覆盖前一个元素的内容。如图所示:
合理使用float布局网页
合理使用float布局网页

方法一: float + calc()

html:

<div class="wrap">
    <div class="left">left</div>
    <div class="right"><p>我要居中</p><p>center</p></div>
</div>

css:

.wrap {
  width: 500px;
  background: yellow;
  overflow: hidden;
}
.left {
  float:left;
  width: 100px;
  background: blue;
}
.right{
  float:left;
  background: red;
  text-align:center;
}

如果我们仅仅这样写,那么效果会像下图这样:
合理使用float布局网页
可以看到右侧元素的宽度并不是页面剩余宽度。原因是:右侧元素float之后具有了行内块级元素的特性,即宽度为auto。所以无法占满剩余宽度。
这不是我们想要的结果,所以我们要自己设置右侧元素的宽度:

.right {
    width: calc(100% - 100px);
}

就符合我们的要求了:
合理使用float布局网页
方法二:position / float + margin-left

html部分同上:

<div class="wrap">
    <div class="left">left</div>
    <div class="right"><p>我要居中</p><p>center</p></div>
</div>

css:

.left {
  position:absolute;left: 0; /*或 float:left; */
  width: 100px;
  background: blue;
}
.right{
  margin-left: 100px;
  background: red;
  text-align:center;
}

原理是:左侧元素float: left或者设置position: absolute 之后脱离了文档流,右侧其实依然是一个霸道的独占一行的块级元素(block),设置margin-left为左侧元素宽度之后,看起来就像是两个元素在同一行,且右侧元素宽度自适应啦:
合理使用float布局网页
参考:imooc

对于所有的web前端开发人员,float是或者曾经一度是你最熟悉的陌生人——你离不开它,却整天承受着它所带给你的各种痛苦,你以为它很简单就那么一点知识,但却驾驭不了它各种奇怪的现象。
这就是我们又爱又恨的——float。所以,系统的学一学float是非常非常有必要的。视频学习可参考张鑫旭的《CSS深入理解之float浮动》,讲的很好很透彻。

重新认识float

1 误解和“误用”

这里说的“误用”并不是真正的误用,而是误打误撞使用之后,带来了真正的效果。
绝大多数人用float都是为了——横向排版或者多列布局。这样的使用是正确的,大部分人都这样使用,bootstrap的栅格系统也是使用了float来实现的,并且在css3被普及之前,多列布局的最佳解决方案也是使用float——要不然你就用table,或display:table-cell。
但是,这样使用确实是对float的一种误解和“误用”,因为float被设计出来的初衷是用于——文字环绕效果。即,一个图片一段文字,图片float:left之后,文字会环绕图片。
css3教程:float
但是,当时的多列布局和横向排版主要是依靠table实现,后来人们见见的发现,使用table将导致代码量大、混乱、不利于SEO,然后发现float+div是一个很不错的排版解决方案,于是乎——过去几年“css+div”页面排版一直是一个热门话题,也是各种高大上的面试题必考的一项。

如果你只知道float是用来排版,却不知道float的许多特性,就会导致你在使用float时遇到许多问题。不信请看下文。

2 破坏性

首先大家来看两个demo,如下图。第一个demo是一个简单不过的例子,显示效果也很正常。第二个demo,唯一的区别就在于加了float:left,上层的

却出现了“坍塌”现象。
css3教程:float
这就是float的“破坏性”——float破坏了父标签的原本结构,使得父标签出现了坍塌现象。导致这一现象的最根本原因在于:被设置了float的元素会脱离文档流。
“脱离文档流”可以理解为子元素与父元素间的DOM结构被破坏,父子关系解除。
但是,永远都不要忘记float被设计的初衷——实现文字环绕效果。当div中有文字时,文字还是会环绕在img周围的,“坍塌”现象消失了。如下图:
css3教程:float
那么,float为什么会被设计成具有破坏性,为什么会脱离文档流?这一点非常重要!其实原因非常简单——为了要实现文字的环绕效果!
如果float不让父元素坍塌:
css3教程:float
坍塌并脱离文档流后:
css3教程:float

3 包裹性


css3教程:float
css3教程:float
如上图,普通的div如果没有设置宽度,它会撑满整个屏幕。而如果给div增加float:left之后,它突然变得紧凑了,宽度发生了变化,把内容“Phone”包裹了——这就是包裹性。div设置了float之后,其宽度会自动调整为包裹住内容宽度,而不是撑满整个父容器。
注意,此时div虽然体现了包裹性,但是它的display样式是没有变化的,还是block。
float为什么要具有包裹性?其实答案还得从float的设计初衷来寻找,float是被设计用于实现文字环绕效果的。文字环绕图片比较好理解,但是如果想要让文字环绕一个div呢?此时div不被“包裹”起来,那么如何去实现环绕效果?

4 清除空格


css3教程:float
上图中。第一个例子,正常的img中间是会有空格的,因为多个标签会有换行,而浏览器识别换行为空格,这也是很正常的。第二个例子中,img增加了float:left的样式,这就使得img之间没有了空格,四个img紧紧挨着。
“清空格”这一特性的根本原因是由于float会导致节点脱离文档流结构。它都不属于文档流结构了,那么它身边的什么换行、空格就都和它没关系的,它就尽量的往一边去靠拢,能靠多近就靠多近,这就是清空格的本质。

清除float(清除浮动)

float具有“破坏性”,它会导致父元素“坍塌”,这不我们所期望的。如何去避免float带来的这种影响呢(也就是我们常说的“清除浮动”) ?方法有很多种,我在这里介绍4中供大家参考,大家可根据实际情况来选择。
两种简单但不常用的方法:

1.为父元素添加overflow:hidden;


css3教程:float
css3教程:float

2.浮动父元素


css3教程:float
css3教程:float

第三种方法clear:borth,不是很常用,但是大家要知道。通过在所有浮动元素下方添加一个clear:both的元素,可以消除float的破坏性。


css3教程:float
注意:也可以添加在父div闭合元素下边,这样即是第四种方法的实现原理。

第四种方法是大家最需要掌握的,也是Bootstrap正在用的——clearfix


css3教程:float
上图中,我们定义一个.clearfix(只是个类名,可以随意定义)类,然后对float元素的父元素应用这一样式即可。究其原理,其实就是通过伪元素选择器,在div后面增加了一个clear:both的元素,跟第三种方法是一个道理。

清除浮动四种方法可概括为:


css3教程:float

前言

百度网盘的下载速度是很感人的,有时很快,有时很慢,而且开了会员也不一定快,所以很多牛人就开发了第三方的百度网盘高速下载工具,这里推荐两款我经常用的 PanDownload 和度盘下载器,它们都是强大的百度网盘下载工具,能够实现无限速高速下载,完全绿色免费, 使用时可以不通过百度网盘下载其中的所有资源。

平时使用 PanDownload 多一点,极力推荐,家里 100M 的网,下载能达到 12M/s,度盘下载器也可以,只是感觉有时不稳定,会提示下载错误。

PanDownload百度网盘高速下载
注:图为PanDownload的下载界面

下载地址

2017 年 8 月 15 日检测两款都能用,暂未失效

PanDownload(已失效)
(推荐)

度盘下载器

CSS 定位机制

CSS 有三种基本的定位机制:

  • 普通流
  • 浮动
  • 绝对定位

一、普通流

除非专门指定,否则所有框都在普通流中定位。普通流中元素框的位置由元素在(X)HTML中的位置决定。块级元素从上到下依次排列,框之间的垂直距离由框的垂直margin计算得到。行内元素在一行中水平布置。

二、定位

1、相对定位

被看作普通流定位模型的一部分,定位元素的位置相对于它在普通流中的位置进行移动。使用相对定位的元素不管它是否进行移动,元素仍要占据它原来的位置。移动元素会导致它覆盖其他的框。

<html>
<head>
<style>
    .box1{
        background-color: red;
        width:100px;
        height:100px;
    }
    .box2{
        background-color: yellow;
        width:100px;
        height:100px;
        position: relative;
        left: 20px;
    }
    .box3{
        background-color: blue;
        width:100px;
        height:100px;
        position: relative;
        right: 20px;
    }
</style>
</head>
<body>
<div class="box1">box1</div>
<div class="box2">box2</div>
<div class="box3">box3</div>
</body>
</html>

效果如下图所示:

2、绝对定位

相对于已定位的最近的祖先元素,如果没有已定位的最近的祖先元素,那么它的位置就相对于最初的包含块(如body)。绝对定位的框可以从它的包含块向上、右、下、左移动。
绝对定位的框脱离普通流,所以它可以覆盖页面上的其他元素,可以通过设置Z-Iindex属性来控制这些框的堆放次序。

<html>
<head>
<style>
    .box1{
        background-color: red;
        width:100px;
        height:100px;
    }
    .box2{
        background-color: yellow;
        width:100px;
        height:100px;
        position: relative;
        left: 20px;
    }
    .box3{
        background-color: blue;
        width:100px;
        height:100px;
        position: relative;
        right: 20px;
    }
</style>
</head>
<body>
<div class="box1">box1</div>
<div class="box2">box2</div>
<div class="box3">box3</div>
</body>
</html>

效果如下图所示:

备注:相对于已相对定位的祖先元素对框进行绝对定位,在大多数现代浏览器中都可以实现的很好。

3、固定定位

相对于浏览器窗口,其余的特点类似于绝对定位。

三、浮动

浮动的框可以在左右移动,直到它的外边框边缘碰到包含框或另一个浮动框的边缘。浮动的框脱离普通流。
如果包含块太窄,无法容纳水平排列的浮动元素,那么其他浮动块向下移动,直到有足够多的空间。如果浮动元素的高度不同,那么当它们向下移动时可能会被其他浮动元素卡住。
行内元素会围绕着浮动框排列。

请看下图,当把框 1 向右浮动时,它脱离文档流并且向右移动,直到它的右边缘碰到包含框的右边缘:

再请看下图,当框 1 向左浮动时,它脱离文档流并且向左移动,直到它的左边缘碰到包含框的左边缘。因为它不再处于文档流中,所以它不占据空间,实际上覆盖住了框 2,使框 2 从视图中消失。

如果把所有三个框都向左移动,那么框 1 向左浮动直到碰到包含框,另外两个框向左浮动直到碰到前一个浮动框。

如下图所示,如果包含框太窄,无法容纳水平排列的三个浮动元素,那么其它浮动块向下移动,直到有足够的空间。如果浮动元素的高度不同,那么当它们向下移动时可能被其它浮动元素“卡住”:

清除浮动

简单介绍下清除浮动的2中方法。

方法一:结合:after选择器清除浮动。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
    .box1 {
        border: 1px solid red;
        background-color: yellow;
    }
    
    .clear:after {
        content: "." ;
        display: block;
        height: 0;
        visibility: hidden;
        clear: both;
    }
    
    .box2 {
        width: 50px;
        height: 50px;
        float: left;
        background-color: orange;
    }
    
    p {
        float: right;
    }
    </style>
</head>
<body>
    <div class="box1 clear">
        <div class="box2">
            box2        </div>
        <p>
            lallalalalalal啦啦啦 lallalalalalal啦啦啦 lallalalalalal啦啦啦 lallalalalalal啦啦啦 lallalalalalal啦啦啦 lallalalalalal啦啦啦 lallalalalalal啦啦啦 lallalalalalal啦啦啦 lallalalalalal啦啦啦 lallalalalalal啦啦啦 lallalalalalal啦啦啦 lallalalalalal啦啦啦        </p>
    </div>
</body>
</html>

方法二,在容器最后添加一个空元素并且清理它。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
    .box1 {
        border: 1px solid red;
        background-color: yellow;
    }
    
    .empty{
        clear: both;
    }
    
    .box2 {
        width: 50px;
        height: 50px;
        float: left;
        background-color: orange;
    }
    
    p {
        float: right;
    }
    </style>
</head>
<body>
    <div class="box1 clear">
        <div class="box2">
            box2        </div>
       
        <p>
            lallalalalalal啦啦啦 lallalalalalal啦啦啦 lallalalalalal啦啦啦 lallalalalalal啦啦啦 lallalalalalal啦啦啦 lallalalalalal啦啦啦 lallalalalalal啦啦啦 lallalalalalal啦啦啦 lallalalalalal啦啦啦 lallalalalalal啦啦啦 lallalalalalal啦啦啦 lallalalalalal啦啦啦        </p>
        <br class="empty" />
    </div>
</body>
</html>

效果均如下所示:

附录:

CSS position 属性总结:

所有主流浏览器都支持 position 属性。position属性规定元素的定位类型,影响元素框生成的方式。
可能的值

描述
absolute 生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位,如果不存在这样的父元素,则依据最初的包含快。根据用户代理的不同,最初的包含块可能是画布或 HTML 元素。

元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定,也可以通过z-index进行层次分级。

(元素框从文档流完全删除,并相对于其包含块定位。包含块可能是文档中的另一个元素或者是初始包含块。元素原先在正常文档流中所占的空间会关闭,就好像元素原来不存在一样。元素定位后生成一个块级框,而不论原来它在正常流中生成何种类型的框。)
fixed 生成固定/绝对定位的元素,相对于浏览器窗口进行定位。

元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定。

(元素框的表现类似于将 position 设置为 absolute,不过其包含块是视窗本身。)
relative 生成相对定位的元素,相对于其正常位置进行定位。

因此,"left:20" 会向元素的 LEFT 位置添加 20 像素。

(相对定位实际上被看作普通流定位模型的一部分,因为元素的位置相对于它在普通流中的位置。元素框偏移某个距离。元素仍保持其未定位前的形状,仍保留原本所占的空间。
static 默认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声明,即上述声明无效)。

(元素框正常生成。块级元素生成一个矩形框,作为文档流的一部分,行内元素则会创建一个或多个行框,置于其父元素中。)
inherit 规定应该从父元素继承 position 属性的值。


CSS 定位属性
CSS 定位属性允许你对元素进行定位。

描述
position 把元素放置到一个静态的、相对的、绝对的、或固定的位置中。
top 定义了一个定位元素的上外边距边界与其包含块上边界之间的偏移。
right 定义了定位元素右外边距边界与其包含块右边界之间的偏移。
bottom 定义了定位元素下外边距边界与其包含块下边界之间的偏移。
left 定义了定位元素左外边距边界与其包含块左边界之间的偏移。
overflow 设置当元素的内容溢出其区域时发生的事情。
clip 设置元素的形状。元素被剪入这个形状之中,然后显示出来。
vertical-align 设置元素的垂直对齐方式。
z-index 设置元素的堆叠顺序。

CSS 框模型(Box Model)

所有HTML元素可以看作盒子,在CSS中,"box model"这一术语是用来设计和布局时使用。

CSS盒模型本质上是一个盒子,封装周围的HTML元素,它包括:边距,边框,填充,和实际内容。

盒模型允许我们在其它元素和周围元素边框之间的空间放置元素。

下面的图片说明了框模型(Box Model):

CSS 框模型的介绍

术语翻译:

Margin - 清除边框区域。Margin没有背景颜色,它是完全透明

Border - 边框周围的填充和内容。边框是受到盒子的背景颜色影响

Padding - 清除内容周围的区域。会受到框中填充的背景颜色影响

Content - 盒子的内容,显示文本和图像

为了在所有浏览器中的元素的宽度和高度设置正确的话,你需要知道的盒模型是如何工作的。

元素的宽度和高度

重要: 当您指定一个CSS元素的宽度和高度属性时,你只是设置内容区域的宽度和高度。要知道,完全大小的元素,你还必须添加填充,边框和边距。.

下面的例子中的元素的总宽度为300px:


width:250px;padding:10px;border:5px solid gray;margin:10px;

让我们自己算算:

250px (宽)
+ 20px (left + 右填充)
+ 10px (left + 右边框)
+ 20px (left + 右边距)
= 300px

试想一下,你只有250像素的空间。让我们设置总宽度为250像素的元素:

实例


width:220px;padding:10px;border:5px solid gray;margin:0px;

最终元素的总宽度计算公式是这样的:

总元素的宽度=宽度+左填充+右填充+左边框+右边框+左边距+右边距

元素的总高度最终计算公式是这样的:

总元素的高度=高度+顶部填充+底部填充+上边框+下边框+上边距+下边距

浏览器的兼容性问题

一旦为页面设置了恰当的 DTD,大多数浏览器都会按照上面的图示来呈现内容。然而 IE 5 和 6 的呈现却是不正确的。根据 W3C 的规范,元素内容占据的空间是由 width 属性设置的,而内容周围的 padding 和 border 值是另外计算的。不幸的是,IE5.X 和 6 在怪异模式中使用自己的非标准模型。这些浏览器的 width 属性不是内容的宽度,而是内容、内边距和边框的宽度的总和。

虽然有方法解决这个问题。但是目前最好的解决方案是回避这个问题。也就是,不要给元素添加具有指定宽度的内边距,而是尝试将内边距或外边距添加到元素的父元素和子元素。

IE8 及更早IE版本不支持 填充的宽度和边框的宽度属性设。

解决IE8及更早版本不兼容问题可以在HTML页面声明 即可。