• position跟display、margin collapse、overflow、float这些特性相互叠加后会怎么样?


    position跟display、margin collapse、overflow、float这些特性相互叠加后会怎么样?

     总结:浮动的行内变成块级元素,绝对定位的行内也会变成块级元素。绝对定位时浮动失效,top,bottom,left,right能改变位置。相邻普通流块级垂直方向margin叠压。浮动,inline-block,绝对定位不会和垂直方向其他元素margin叠压。BFC不会和子元素margin叠压。(absolute,fixed都是绝对定位)

    这是寒冬大神提出的一个题目,刚开始看到这题的时候完全不知道从什么地方回答起好,题目内容比较广泛,找不到针对点。后来我觉得这个题目应该能拆成几个点来回答:1、'display'、'position' 和 'float' 的相互关系;2、position跟display、overflow、float下的margin collapse。

    一、'display'、'position' 和 'float' 的相互关系
    首先我们先来看下这3个属性。
    display 属性规定元素应该生成的框的类型 block 象块类型元素一样显示none 缺省值inline象行内元素类型一样显示 inline-block 象行内元素一样显示,但其内容象块类型元素一样显示list-item 象块类型元素一样显示,并添加样式列表标记(display 还有很多其他值设置,读者自行查找)。
     position 属性规定元素的定位类型。 absolute表示生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位fixed(老IE不支持)生成绝对定位的元素,相对于浏览器窗口进行定位relative生成相对定位的元素,相对于其正常位置进行定位static  默认值没有定位,元素出现在正常的流中(忽略 top, bottom, left, right z-index 声明)
     Float也是是一种布局方式,它定义元素在哪个方向浮动以往这个属性总应用于图像,使文本围绕在图像周围,不过在 CSS 中,任何元素都可以浮动。浮动元素会生成一个块级框,而不论它本身是何种元素。 在布局过程中也经常会使用它来达到左右并排布局的效果

    那么这三种布局和框形成的关键特性( display )之间有什么关系呢,请看下面流程图:

    转换对应表:

    设定值计算值
    inline-table table
    inline, run-in, table-row-group, table-column, table-column-group, table-header-group, 
    table-footer-group, table-row, table-cell, table-caption, inline-block
    block
    其他 同设定值

    总的来说,可以把它看作是一个类似优先级的机制, "position:absolute" 和 "position:fixed" 优先级最高,有它存在的时候,浮动不起作用,'display' 的值也需要调整; 其次,元素的 'float' 特性的值不是 "none" 的时候或者它是根元素的时候,调整 'display' 的值; 最后,非根元素,并且非浮动元素,并且非绝对定位的元素,'display' 特性值同设置值

    这从另一个侧面说明了一个问题:浮动或绝对定位的元素,只能是块元素或表格

    1. 'display' 的值为 'none'

    如果 'display' 的值为 'none',那么 'position' 和 'float' 不起作用。在这种情况下,元素不产生框。因此浮动和定位无效。

    2. 'position' 的值是 'absolute' 或 'fixed'

    如果 'position' 的值是 'absolute' 或 'fixed',框就是绝对定位的,'float' 计算后的值应该是 'none',并且,'display' 会被按照上表设置。 框的位置将由 'top','right','bottom' 和 'left' 属性和该框的包含块确定。

    也就是说,当元素是绝对定位时,浮动失效,'display' 会被按规则重置。

    示例代码:

    复制代码
    <script type="text/javascript">
        function getStyle(obj, style) {
           var _style = (style == "float") ? "styleFloat" : style;
           return document.defaultView ? document.defaultView.getComputedStyle(obj, null).getPropertyValue(style) : obj.currentStyle[_style.replace(/-[a-z]/g, function() {
               return arguments[0].charAt(1).toUpperCase();
           })];
        }
        window.onload = function() {
           document.getElementById("info").innerHTML = "float : " + getStyle(document.getElementById("test"), "float") +
                   "<br/>display : " + getStyle(document.getElementById("test"), "display");
        }
    </script>
    <div id="test" style="position:absolute; float:left;display:inline;"></div>
    <div id="info"></div>
    复制代码

    上面代码中有一个既是绝对定位又是浮动的元素,以上代码可取出其 'display' 和 'float' 的计算值。

    IE 中,'float' 值和 'display' 的特性值未发生变化,还是 "float: left; display: inline"。

    其他浏览器中计算后的结果是:"float: none; display: block"。

    3. 'float' 的值不是 "none"

    如果 'float' 的值不是 "none",该框浮动并且 'display' 会被按照转换对应表设置。

    复制代码
    <!DOCTYPE html>
    <script type="text/javascript">
        function getStyle(obj, style) {
           var _style = (style == "float") ? "styleFloat" : style;
           return document.defaultView ? document.defaultView.getComputedStyle(obj, null).getPropertyValue(style) : obj.currentStyle[_style.replace(/-[a-z]/g, function() {
               return arguments[0].charAt(1).toUpperCase();
           })];
        }
        window.onload = function() {
           document.getElementById("info").innerHTML = "display : " + getStyle(document.getElementById("test"), "display");
        }
    </script>
    <span id="test" style="100px; height:100px; border:1px solid red;float:left;">float span</span>
    <div id="info"></div>
    复制代码

    按照规则,SPAN 是行内元素,因此不能够设置其宽度和高度。但是浮动后,'display' 值按照转换对应表设置后,成为块级元素。

    IE 中截图:

    其他浏览器中:

    4. 元素是根元素

    如果元素是根元素,'display' 的值按照转换对应表设置。

    5. 否则,应用指定的 'display' 特性值。

    二、position跟display、overflow、float下的margin collapse。

    margin collapse我觉得这里的意思应该是Collapsing margins,即外边距折叠,指的是毗邻的两个或多个外边距 (margin) 会合并成一个外边距。

    其中所说的 margin 毗邻,可以归结为以下两点:

    • 这两个或多个外边距没有被非空内容、padding、border 或 clear 分隔开。
    • 这些 margin 都处于普通流中。

    1.两个或多个毗邻的普通流中的块元素垂直方向上的 margin 会折叠。

    注意一点,在没有被分隔开的情况下,一个元素的 margin-top 会和它普通流中的第一个子元素(非浮动元素等)的 margin-top 相邻; 只有在一个元素的 height 是 "auto" 的情况下,它的 margin-bottom 才会和它普通流中的最后一个子元素(非浮动元素等)的 margin-bottom 相邻。

    示例代码:

    复制代码
    <div style="border:1px solid red; 100px;">
        <div style="margin:50px 0;  height:50px; 50px;">
           <div style="margin:20px 0;">
               <div style="margin:100px 0;">B</div>
           </div>
        </div>
    </div>
    复制代码
    效果图:

    margin 折叠举例

    以上代码中,margin 会把 B 的包含块撑开。

    如果一个元素的 height 特性的值不是 auto,那么它的 margin-bottom 和它子元素的 margin-bottom 不算相邻,因此,不会发生折叠。 margin-top 没有此限制,所以是 100px,margin-bottom 没有折叠,只有 50px。

    垂直方向

    是指具体的方位,只有垂直方向的 margin 才会折叠,也就是说,水平方向的 margin 不会发生折叠的现象。

    折叠后 margin 的计算

    1). 参与折叠的 margin 都是正值

    例子:

    <div style="height:50px; margin-bottom:50px;50px; ">A</div>
    <div style="height:50px;margin-top:100px; 50px; ">B</div>

    示意图:

    在 margin 都是正数的情况下,取其中 margin 较大的值为最终 margin 值。

    2). 参与折叠的 margin 都是负值

    当 margin 都是负值的时候,取的是其中绝对值较大的,然后,从 0 位置,负向位移。

    示例代码:

    <div style="height:100px; margin-bottom:-75px;100px; ">A</div>
    <div style="height:100px;margin-top:-50px; margin-left:50px; 100px; ">B</div>

    示意图:

    3). 参与折叠的 margin 中有正值,有负值

    如果,毗邻的 margin 中有正值,同时存在负值会怎样呢?有正有负,先取出负 margin 中绝对值中最大的,然后,和正 margin 值中最大的 margin 相加。

    示例代码:

    <div style="height:50px; margin-bottom:-50px;50px; ">A</div>
    <div style="height:50px;margin-top:100px; 50px; ">B</div>

    示意图:

    上面的例子最终的 margin 应该是 100 + (-50) = 50px。

    4). 相邻的 margin 要一起参与计算,不得分步计算

    要注意,相邻的元素不一定非要是兄弟节点,父子节点也可以,即使不是兄弟父子节点也可以相邻。

    而且,在计算时,相邻的 margin 要一起参与计算,不得分步计算。

    一个复杂的实例:

    复制代码
    <div style="margin:50px 0; 50px;">
        <div style="margin:-60px 0;">
               <div style="margin:150px 0;">A</div>
        </div>
    </div>
    <div style="margin:-100px 0; 50px;">
        <div style="margin:-120px 0;>
               <div style="margin:200px 0;">B</div>
        </div>
    </div>
    复制代码

    错误的计算方式:算 A 和 B 之间的 margin,分别算 A 和其父元素的折叠,然后与其父元素的父元素的折叠,这个值算出来之后,应该是 90px。依此法算出 B 的为 80px;然后,A和B折叠,margin 为 90px。

    请注意,多个 margin 相邻折叠成一个 margin,所以计算的时候,应该取所有相关的值一起计算,而不能分开分步来算。

    以上例子中,A 和 B 之间的 margin 折叠产生的 margin,是6个相邻 margin 折叠的结果。将其 margin 值分为两组:

    • 正值:50px,150px,200px
    • 负值:-60px,-100px,-120px

    根据有正有负时的计算规则,正值的最大值为 200px,负值中绝对值最大的是 -120px,所以,最终折叠后的 margin 应该是 200 + (-120) = 80px。

    2.浮动元素、inline-block 元素、绝对定位元素的 margin 不会和垂直方向上其他元素的 margin 折叠

    浮动元素的 margin 在垂直方向上也不会发生 margin 折叠,即使和它相邻的子元素也不会。

    3.创建了块级格式化上下文的元素,不和它的子元素发生 margin 折叠

    以 “overflow : hidden” 

     

     参考资料来源:http://www.w3help.org/zh-cn/
  • 相关阅读:
    js将页面上取得的元素坐标转换为电脑屏幕坐标
    一个例子形象的理解协程和线程的区别
    为什么有的人把代码写的如此复杂?
    都说Dapper性能好,突然就遇到个坑,还是个性能问题
    springgateway基于数据库 + nacos 的动态路由
    k8s配置deployment的 liveness 和 readiness 探针 若
    UML设计图5部署图 若
    UML设计图1用例图 若
    UML设计图6序列图 若
    UML设计图2数据流图 若
  • 原文地址:https://www.cnblogs.com/wulinzi/p/8426383.html
Copyright © 2020-2023  润新知