美文网首页网页前端后台技巧(CSS+HTML)让前端飞Web 前端开发
什么叫文档流,为什么清浮动,定位的规则是什么?

什么叫文档流,为什么清浮动,定位的规则是什么?

作者: 默非静语 | 来源:发表于2018-07-10 22:10 被阅读14次

    文档流

    做网页布局的时候,有时候会对网页元素进行浮动,按照自己的需求对网页元素进行排版,元素浮动之后会脱离文档流,造成一些小麻烦,这时候就需要清除浮动,让元素按照自己需求正常排版显示。

    什么叫脱离文档流呢?又为什么一会儿浮动又要清除浮动呢?

    之前在知乎看到一个问题,问的是什么是文档流和文本流到底是什么?问题地址

    我的理解和总结:

    一丶什么是文档流:

    文档流只是我们把国外的标准翻译过来的一种习惯的叫法,英文原文为“normal flow ” 应该叫做正常流。

    正常流是什么呢?

    1.元素在父元素中排序规则,从左上角开始。从左至又,自上而下。

    2.浮动(float)、绝对定位(absolute)、固定定位(fixed)三种方式定位会脱离文档流。 同时上面的两种定位还能让浮动失效。

    3.元素分为三种大的类型 块状 内联 内联块 每一种有自己的特性。

    • 块状:独占一行 在父元素内一行内只有它自己,不能放下其它元素。支持所有css样式 。

      默认继承父元素100%的宽(不设宽)

    • 内联:内容撑开宽度 ,不独占一行。可以设置宽高,但不会有作用,可以设置左右的margin,border,padding。

      注意: 内联元素又叫行内元素,由名字可知,它的属性主要在一行内展示。
      它可以设置margin,但是上下的margin却不会有作用。设置padding和border,可以显示你设置的属性,但是只有左右的属性是被其他浏览器其他元素“正视”的,只有左右的padding和border会占据空间。而上下的却不在文档流内。如果你上下的值设置的足够大,给它一个背景色他会遮盖其它元素。

    • 内联块 :同属性排在一行 不独占一行 支持所有css样式 代码换行被解析,间距取决于父级的文字大小

    脱离文档流会发生什么呢?

    1.会打乱元素的排序规则,设置浮动,定位后会按照自己设置的属性值来摆放

    2.让各类型元素失去原来各自的特性,变成同一种元素。

    ​ 以前看过一个面试题说元素浮动后就会等于 display:block;准确来说并不正确。

    ​ 浮动会让元素有块元素部分性质,如:支持所有css样式,子元素和内容能撑开自身(不设置) 。 但是不会独占一行,不能继承父元素宽高。(给元素只设置高,然后浮动元素,元素会因为没有宽度而无法显示)

    ​ 对于父元素来说,脱离了文档流的子元素不能再撑开父元素了,所以会出现高度塌陷的问题。

    二丶关于浮动

    为什么要浮动?

    主要是为了按照网页的每一板块按照自己的需求来进行排版。

    为什么清除浮动呢?

    个人觉得叫清除浮动不太准确,应该叫清除浮动的弊端和适合。

    那些情况需要清除浮动呢?

    1.父元素高度塌陷

    高度塌陷

    子元素浮动,父元素没有设置高度,子元素就无法撑开父元素 ,父元素高度就为0。

    2.元素浮动后影响到其他同级元素或者父元素元素的内容文字

    前面提到过文档流和文本流,一个元素的内容文字等就是文本流。元素浮动后上升一个高度到文本流,给一个父元素内的子元素浮动后,父元素的文字会对浮动元素进行环绕。


    文字环绕

    浮动元素只能影响写在他后面的元素,两个块状同级元素,给第一个浮动,就会遮盖第二个元素。

    覆盖同级元素

    个人理解:
    如果正常的文档流规定一个高度,那么元素的border,padding,margin 都在第一层,而元素的文本流即文字和内联块元素(内联元素又称置换元素,写在代码里的标签只是空壳。常见内联块如 img input 标签 只有你设置了图片,写了文字,这些东西才算是文本流。 )会在第二层。
    如果浮动了 ,元素就会提高一层,跑到文本流。如果浮动元素比正常元素大的多,就不有文字环绕了,而是完全把文字挤出去。
    那么如果给元素无限嵌套,后代元素设置浮动,岂不是后代元素无限高。其实并不是,对于整个页面来说正常的文本流只有两个高度,且高度都是相对的。

    元素高度
    如图 div2 div3都浮动了,div2 div3的高度只会是2。 如果div1 div3浮动 那么div1会跑到div3上面吗?父元素再怎么浮动都不会对其后代元素造成任何影响。
    个人觉得本质上元素应该都是同级之间才能造成空间上的影响(比如文字与文字,文字与其它块元素。),但是元素浮动后,会对后面正常的元素内容文字内容产生文字环绕。两个正常的同级元素的文字超出了,却只会进行重叠,这就很难理解。暂时可以认为浮动后的元素相当于把所有元素的文本流都拉到了与自己同一个规则层度。

    清除浮动弊端的方法

    1.父元素也浮动 margin:0 auto 失效

    2.父级 dispaly:inline-block 同上

    3.父级加高

    4.br标签

    <br clear = "all">
    

    5.在浮动的元素后面加 div设置样式

    .class{
        clear:both/left/right/none;
    }
    

    6.伪类清除浮动

    .clearfix:after {content:"."; display:block; height:0; visibility:hidden; clear:both; }
    

    7.父级加 overflow:hidden;

    一般常用第6种方法,其他方法都有局限性或者违反了结构样式分离的标准。

    但是第6种只能解决高度塌陷,无法解决同级浮动元素遮盖的效果。

    可以用第7种来解决,overflow:hidden;

    浮动还能解决的问题:

    margin重叠问题:

    同级元素不浮动margin就会重叠,两个元素的距离就等于margin大的那个。

    三丶关于定位

    定位移动的是自己本身和所有后代元素 ,后代在自身里的属性规则还是遵循文档流的 。

    相对定位

    position:relitive;

    还会占据原来位置 ,相当于结构还在原来位置 ,而画面跑到了新的位置 。

    新位置的画面会遮盖正常的文档流 不会对正常的文档流产生影响

    当父元素设置overflow: hidden时,如果元素超出了父元素 超出部分会被隐藏

    绝对定位

    position:absolute;

    针对有定位的父级(或祖先级)定位,会完全脱出文档流。 元素不会占据原来的位置 会把元素提高到另一个层级。

    如果父级没有设置定位,overflow: hidden;不会起作用 只有在定位参照的元素上写才有作用。

    定位会从参照的元素border开始定位

    绝对定位基准

    没有写值的时候,元素已经脱离了文档流,但是显示的画面还是按照原来的排序规则显示 。如果再其上方写一个块元素, 会把他挤下去 。让上方的元素浮动, 画面会盖住浮动元素。

    绝对定位不设值

    只写一边,另一边继续遵守 。

    定位之后显示的画面 都不会遵循正常的文档流 浏览器都是从上之下读取代码,经过渲染后 如果两个元素的画面在一个位置,后写的会覆盖先写的。

    绝对定位的一个导航案例

    导航

    html

    <ul class="nav">
            <li>
                <a href="#">首页</a>
                <ul class="nav_sub">
                    <li>
                        <a href="#">首页1</a>
                    </li>
                    <li>
                        <a href="#">首页1</a>
                    </li>
                    <li>
                        <a href="#">首页1</a>
                    </li>
                    <li>
                        <a href="#">首页1</a>
                    </li>
                </ul>
            </li>
            <li>
                <a href="#">首页</a>
                <ul class="nav_sub">
                    <li>
                        <a href="#">首页1</a>
                    </li>
                    <li>
                        <a href="#">首页1</a>
                    </li>
                    <li>
                        <a href="#">首页1</a>
                    </li>
                    <li>
                        <a href="#">首页1</a>
                    </li>
                </ul>
            </li>
            <li>
                <a href="#">首页</a>
                <ul class="nav_sub">
                    <li>
                        <a href="#">首页1</a>
                    </li>
                    <li>
                        <a href="#">首页1</a>
                    </li>
                    <li>
                        <a href="#">首页1</a>
                    </li>
                    <li>
                        <a href="#">首页1</a>
                    </li>
                </ul>
            </li>
            <li>
                <a href="#">首页</a>
                <ul class="nav_sub">
                    <li>
                        <a href="#">首页1</a>
                    </li>
                    <li>
                        <a href="#">首页1</a>
                    </li>
                    <li>
                        <a href="#">首页1</a>
                    </li>
                    <li>
                        <a href="#">首页1</a>
                    </li>
                </ul>
            </li>
            <li>
                <a href="#">首页</a>
                <ul class="nav_sub">
                    <li>
                        <a href="#">首页1</a>
                    </li>
                    <li>
                        <a href="#">首页1</a>
                    </li>
                    <li>
                        <a href="#">首页1</a>
                    </li>
                    <li>
                        <a href="#">首页1</a>
                    </li>
                </ul>
            </li>
        </ul>
    

    css

        *{
                margin: 0;
                padding: 0;
            }
          
          li{
              list-style: none;
          }
    
           .nav {
                width: 400px;
                height: 50px;
                /* background: steelblue; */
                margin: 150px auto;
            }
    
          
            .nav li {
                float: left;
            }
    
      
            .nav a {
                background: aquamarine;
                display: block;
                width: 50px;
                height: 40px;
                line-height: 40px;
                text-align: center;
                /* background: burlywood; */
            }
    
        
            .nav .nav_sub a {
                display: none;
            }
    
     
            .nav>li:hover .nav_sub a {
                display: block;
            }
    
            .nav li ul {
                position: absolute;
            }
    

    如果没有给子菜单设置绝对定位就会出现这种情况

    image

    给子菜单绝对定位就不会占据原来的宽度。

    总结:浮动会脱离文档流,但其实还是在一个层度。绝对定位,和对于浏览器定位都是完全脱离文档流。从可视的角度来说已经完全脱离了正常的网页结构。

    现在css出了flex布局,比float布局好用多了,但是由于浏览器兼容问题,大部分都是用在手机端。

    水平有限,如有不足请多指教。

    18年7月15补:
    网页中的文档流,浮动,定位都是服务于网页布局的。
    文档流即正常网页元素的排序规则,一些属性继承等等规则。

    定位也只是相对定位和其他两种定位有点区别。相对定位他它本身的元素结构属性位置都不会改变,变的只有它的画面位置。其他两种定位呢,会改变自身原有的一些特性,会从原来位置脱离,相当于父元素没有这个子元素了,画面位置只会针对参考元素来改变。

    至于浮动呢,个人觉得设计的很不合理。它会让元素脱离文档流,让父元素高度塌陷,同时又能影响到其他元素的文本流,不仅仅是父元素的文本流,还能影响到父元素同级元素的文本流等等。通常网页布局出现问题,都是浮动造成的。而且那些稀奇古怪清除方法,清除浮动的效果还不一样。

    文章写的有点乱,没有写详细的案例,理解起来会很费劲。等有时间了,会把各种情况的案例补充完全,把文章梳理一下。

    一些题外话,别人的文章只是用来参考的,不一定别人写的就对。如果出现问题了,最好的办法就是自己重新敲一遍,或者自己去debug,去看看出问题的元素哪些属性和你预想的不一样等等,只有自己理解了,才是最重要的。对自己所学的知识归纳整理,也是很重要的,去注册个有道云,映象笔记等等,把自己的笔记整理整理,到最后弄个思维导图知识点串一串。条理,思路清晰了,干什么都能触类旁通。

    写博客只是对于知识理解程度的一种检索,还有就是锻炼自己的表达能力,希望大家一起共勉。

    待续...

    相关文章

      网友评论

        本文标题:什么叫文档流,为什么清浮动,定位的规则是什么?

        本文链接:https://www.haomeiwen.com/subject/chuqpftx.html