• 三种方式实现动态元素水平居中


    今天临下班的时候隔壁组的同事拉住我跟我讨论一个问题,想要实现的功能如下:

    在一个div中有多个水平排列的div,但这些div的宽度不定,并且可以动态增加或者减少。要求这些div组始终居中排列。如图:

    看了一下他的代码,是用浮动来做的,但是所有的div都靠左排列。因为块下班了,两个人急急忙忙调试了一会儿没能得到正确的结果,于是下班后想好好研究一下。最终找到了三种实现的方式,写出来跟大家一起讨论讨论。

    尝试一:使用Float+margin:auto+js
    我就沿着他的float思路继续思考。如果使用float的话,被浮动的元素始终会靠左或者靠右排列,只有将其父元素居中,这些元素才有可能居中放置。不然的话要动态改动他们的margin-left或者margin-right才能实现效果。
    那么如何实现父元素居中呢,如果是定宽的元素那好办,直接"margin: 0 auto"就可以实现。但是这里的父元素的大小是不固定的,要随着子元素增减而改变。继续走下去的办法只有用JS去控制父元素的宽度。写了代码进行实验,是可以做到。

     1 <!DOCTYPE>
     2 <html>
     3     <head>
     4         <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
     5     <style type="text/css">
     6         #content{
     7             margin: 0 auto; //父元素水平居中
     8             height: 202px;
     9             background-color: lightblue;
    10         }
    11         #content div{
    12             width: 100px;
    13             height: 200px;
    14             float: left; //子元素向左浮动
    15             border: 1px solid blue;
    16             background-color:gray;
    17         }
    18         #toolbar{           
    19             margin: 20px auto;
    20             text-align: center;
    21         }
    22         #footer{
    23             clear: both;
    24         }   
    25     </style>
    26 
    27     <script type="text/javascript">
    28         function doLayout(){
    29             var contentDiv = document.getElementById("content");
    30             var children = contentDiv.children;
    31             var width = 0;
    32             for(var i = 0, l = children.length; i < l; i ++){
    33                 width += children[i].offsetWidth;
    34             }
    35 
    36             contentDiv.style.width = width+"px";
    37         }
    38         function addDiv(){
    39             var contentDiv = document.getElementById("content");
    40             var newDiv = document.createElement("Div");
    41             newDiv.innerHTML = "new added div";
    42             contentDiv.appendChild(newDiv);
    43             doLayout();
    44         }
    45     </script>
    46     
    47     </head>
    48     <body onload="doLayout()">
    49     <div id="page">
    50         <div id="header"><h1>自动水平居中</h1></div>       
    51         <div id="content">
    52             <div id="div1">                    
    53                 <p>13123</p>
    54                 <span>13123</span>
    55             </div>
    56             <div id="div2">                    
    57                 <a href="#">13123</a>
    58                 <p>13123</p>
    59                 <span>13123</span>
    60             </div>
    61         </div>       
    62         <div id="toolbar">
    63             <input type="button" value="Add Float Div" onClick="addDiv()"/>
    64         </div>
    65         <div id="footer">
    66             <p>没人关注的页脚</P>
    67         </div>
    68     </div>
    69     </body>
    70 </html>

    尝试二:使用inline-block

    使用JS当然可以解决这样的问题,但到底只使用css能不能实现呢,毕竟这应该属于一个布局的问题。于是想到了前几天看的一篇关于inline-block代替float实现瀑布流的文章,就想试试这里也能否使用inline-block实现这个水平居中的效果。

    于是开始查找inline-block的定义和用法:

    inline-block:This value causes an element to generate an inline-level block container. The inside of an inline-block is formatted as a block box, and the element itself is formatted as an atomic inline-level box.

    意思是:inline-block会触发元素呈现成一个行级别的块包含对象,这个对象内部的元素呈现成块级元素,而这个元素本身呈现成行级别的元素。 我的理解是,对与它的父元素以及兄弟元素,它是一个行级别的元素,可以与其他行级别元素同行放置;但对于它内部的元素,它是块级元素,及内部的元素不需要额外的设置来触发BFC。

    经过一定的尝试和调试,终于在text-align:center的配合下,基本实现了想要的效果:

     1 <!DOCTYPE>
     2 <html>
     3     <head>
     4         <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
     5     <style type="text/css">
     6         #content{
     7             text-align:center; //内部元素居中
     8             height: 200px;
     9             background-color: lightblue;
    10         }
    11         #content div{
    12             width: 100px;
    13             height: 200px;
    14             display:inline-block;
    15             border: 1px solid blue;
    16             background-color:gray;
    17         }
    18         #toolbar{           
    19             margin: 20px auto;
    20             text-align: center;
    21         }
    22         #footer{
    23             clear: both;
    24         }   
    25     </style>
    26 
    27     <script type="text/javascript">
    28         function addDiv(){
    29             var contentDiv = document.getElementById("content");
    30             var newDiv = document.createElement("Div");
    31             contentDiv.appendChild(newDiv);
    32         }
    33     </script>
    34     </head>
    35     <body>
    36     <div id="page">
    37         <div id="header"><h1>自动水平居中</h1></div>
    38 
    39         <div id="content">
    40             <div id="div1"> 
    41             </div>
    42             <div id="div2"> 
    43             </div>
    44         </div>
    45        
    46         <div id="toolbar">
    47             <input type="button" value="Add Float Div" onClick="addDiv()"/>
    48         </div>
    49         <div id="footer">
    50             <p>没人关注的页脚</P>
    51         </div>
    52     </div>
    53     </body>
    54 </html>

    但是在尝试放入了一些块级元素到各个div中的时候,发现当内部元素高度不一样的时候,各个块的排列就不能对齐了:

    这可能就是内部的块级元素产生了换行的原因吧,但是也不能确定,有时间仔细研究一下,也希望知道的高手能指点一下。

    但是我还是找到了解决的办法,就是vertical-align,在设置成top之后,每个元素内部都从顶端开始排布,所以也就能对齐了。

     1 <!DOCTYPE>
     2 <html>
     3     <head>
     4         <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
     5     <style type="text/css">
     6         #content{
     7             text-align:center;
     8             height: 202px;
     9             background-color: lightblue;
    10         }
    11         #content div{
    12             width: 100px;
    13             height: 200px;
    14             display:inline-block;
    15             border: 1px solid blue;
    16             vertical-align: top;
    17             background-color:gray;
    18         }
    19         #toolbar{           
    20             margin: 20px auto;
    21             text-align: center;
    22         }
    23         #footer{
    24             clear: both;
    25         }   
    26     </style>
    27 
    28     <script type="text/javascript">
    29         function addDiv(){
    30             var contentDiv = document.getElementById("content");
    31             var newDiv = document.createElement("Div");
    32             newDiv.innerHTML = "new added div";
    33             contentDiv.appendChild(newDiv);
    34         }
    35     </script>
    36     </head>
    37     <body>
    38     <div id="page">
    39         <div id="header"><h1>自动水平居中</h1></div>
    40        
    41             <div id="content">
    42                 <div id="div1">                    
    43                     <p>13123</p>
    44                     <span>13123</span>
    45                 </div>
    46                 <div id="div2">                    
    47                     <a href="#">13123</a>
    48                     <p>13123</p>
    49                     <span>13123</span>
    50                 </div>
    51             </div>
    52        
    53         <div id="toolbar">
    54             <input type="button" value="Add Float Div" onClick="addDiv()"/>
    55         </div>
    56         <div id="footer">
    57             <p>没人关注的页脚</P>
    58         </div>
    59     </div>
    60     </body>
    61 </html>

    至此,使用inline-block顺利解决了问题。但是在查阅资料的时候都说inline-block有浏览器兼容的问题,自己在chrome,firefox和IE10试了之后都没发现问题。也算是一种解决方案吧。

    尝试三:使用position:relative实现

    在查阅水平居中的过程当中,还看到有同学说可以使用position:relative加上float来实现,于是也尝试了一下。确实也是可以的:

     1 <!DOCTYPE>
     2 <html>
     3     <head>
     4         <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
     5     <style type="text/css">
     6         #content{
     7             float: left;
     8             position:relative;
     9             left: 50%;//父元素相对左50%
    10             height: 202px;
    11         }
    12         #content div{ 
    13             float: left;
    14             position:relative;
    15             right: 50%;//子元素相对右50% 这里写成left:-50%也能工作
    16             width: 100px;
    17             height: 200px;
    18             border: 1px solid blue;
    19             background-color:gray;
    20         }
    21         #toolbar{         
    22             clear:both;  
    23             margin: 20px auto;
    24             text-align: center;
    25         }
    26         #footer{
    27             clear: both;
    28         }   
    29     </style>
    30 
    31     <script type="text/javascript">
    32         function addDiv(){
    33             var contentDiv = document.getElementById("content");
    34             var newDiv = document.createElement("Div");
    35             newDiv.innerHTML = "new added div";
    36             contentDiv.appendChild(newDiv);
    37         }
    38     </script>
    39     </head>
    40     <body>
    41     <div id="page">
    42         <div id="header"><h1>自动水平居中</h1></div>
    43        
    44             <div id="content">
    45                 <div id="div1">                    
    46                     <p>13123</p>
    47                     <span>13123</span>
    48                 </div>
    49                 <div id="div2">                    
    50                     <a href="#">13123</a>
    51                     <p>13123</p>
    52                     <span>13123</span>
    53                 </div>
    54             </div>
    55        
    56         <div id="toolbar">
    57             <input type="button" value="Add Float Div" onClick="addDiv()"/>
    58         </div>
    59         <div id="footer">
    60             <p>没人关注的页脚</P>
    61         </div>
    62     </div>
    63     </body>
    64 </html>

    这里先普及一下polistion:relative的概念:
    relative :  对象不可层叠,但将依据left,right,top,bottom等属性在正常文档流中偏移位置。
    这个解释与一般的理解有点偏差,我最开始的时候也是理解成相对定位,以为是相对父节点的,但实际上相对的是正常情况下自己的位置。所以也就很容易解释,代码中的父节点相对其父节点向右移动50%后它的开始就正好在正中间,然后子元素都相对自身向左偏移50%,自然也就能将自己的中心放在整体的中间。也就实现了居中排放的效果。

    至此,这个自动水平居中的问题也算完美解决了。技术这种东西,都是取之于民用之于民,希望能够给大家一些帮助,也希望能跟大家一起探讨更多的问题。

  • 相关阅读:
    code3728 联合权值
    Codevs 4600 [NOI2015]程序自动分析
    code1540 银河英雄传说
    code1074 食物链
    堆排序
    哈夫曼树与哈夫曼码
    优先队列用法
    code1154 能量项链
    code1225 八数码Bfs
    javascript5
  • 原文地址:https://www.cnblogs.com/owenChen/p/3228875.html
Copyright © 2020-2023  润新知