是否有可靠的跨浏览器方式在几个DIV之间分配父元素中的剩余空间?

时间:2012-03-12 20:01:47

标签: css css3

背景

我正在开发一个基于浏览器的UI,需要在不进行任何滚动的情况下填满整个屏幕。基本布局是这样的:

layout sketch

我想要实现的目标

标题div应具有固定高度(2em),其余4个div / panel应根据我设置的百分比分配屏幕的剩余空间。

我尝试了什么

我找到的最佳解决方案是“CSS - How to force elements to 100% of remaining/available space of parent element without extending beyond it?”,其中涉及使用带position:absolute的容器div。这适用于所有浏览器,但需要创建一些额外的DIV。此外,由于inaccuracies in percentage widths,有时可能会强制面板2在下一行开始。

我以前的解决方案基于CSS3 Flexbox,但模型存在缺陷,因为在拉伸容器盒后(至少Chrome没有),它不会调整具有百分比高度的子元素。 (较新的flex- *属性仅在Chrome中实现,标准仍在变化。)

我也尝试了calc()功能;但是,它还没有在Chrome中实现。此外,它需要在两个地方对标题元素的高度进行硬编码,这是我一直试图避免的。

修改

我在寻找什么

为了清楚起见,我并不是要求一个完美的/纯CSS解决方案(因为似乎没有)。如果任何人都可以建议任何可以执行此操作的jQuery插件或开源框架,那对我来说就足够了。

此外,我不要求在2012年之前与浏览器版本有任何向后兼容性。(只要该解决方案使用在某些浏览器中实现的技术,并且将在不久的将来由Firefox和Chrome实现,它就是对我来说足够好了。)

7 个答案:

答案 0 :(得分:8)

一些东西扔在一起: http://jsfiddle.net/gDTGn/2/

答案 1 :(得分:2)

这是一个纯CSS版本:

http://jsfiddle.net/t0nyh0/KHzsg/63/

此技术的诀窍是使用position:absolute并使用topbottomheight创建带有展开面板的固定标头。使用它也非常重要:

box-sizing: border-box;
-moz-box-sizing: border-box;

使浏览器的高度和宽度计算保持一致。经过测试,适用于IE9,Firefox和Chrome。

答案 2 :(得分:2)

纯CSS解决方案:http://jsfiddle.net/ehqcx/7/embedded/result/

这假设您设置的宽度不超过100%,右侧的小间隙通常可以通过使用相同的背景或页面背景来固定。另一种方法是引入一些Javascript来正确设置最后一个面板的宽度,但这应该是一些简单的jQuery代码... $("#panels .small:last").width(browser width - other small panels);

对于高度应该正常工作,想一想带走一些高度的jsFiddle标题......

修改

  

嗯,似乎#title让我烦恼...... http://fiddle.jshell.net/ehqcx/7/show/light/

     

ECMAScript是可行的方式,由于其他简单性而留下我的答案...... :(

HTML:

<div id="content">
    <div id="title">Title!</div>
    <div id="panels">
        <div id="panel0" class="small">0</div>
        <div id="panel1" class="small">1</div>
        <div id="panel2" class="small">2</div>
        <div id="panel3" class="wide">3</div>
    </div>
</div>​

CSS:

* { margin, padding: 0px; }
#content { background-color: black; }
#title { background-color: red; }
#panels { background-color: orange; }
#panel0 { background-color: purple; }
#panel1 { background-color: brown; }
#panel2 { background-color: orange; }
#panel3 { background-color: green; }

html, body, #content, #panels { max-height: 100%; height: 100%; max-width: 100%; width: 100%; }
#panels .small { float: left; }
#panels .wide { clear: both; }

#title { height : 2em; }
#panels .small { height: 75%; }
#panels .wide { height: 25%; }
#panel0, #panel1, #panel2 { width: 33.33%; }

答案 3 :(得分:0)

可以使用新的CSS3 flexbox模型。它基本上是为解决您所面临的问题而设计的。

这是一个简单的example

CSS:

*{margin:0 padding:0;}
html{height:100%;}
body{height:100%; display:box; box-orient:vertical;}
body > div {box-flex:1; border:1px solid black;}
.header {box-flex:0; height:4em;}
.content { 
  display: box;
  box-orient: horizontal;
}
.content div {
  box-flex: 1;
  border:1px solid black;
}

HTML:

<html>
    <body>
    <div class="header">Title</div>
    <div class="content">
        <div>Panel 0</div>
        <div>Panel 1</div>
        <div>Panel 2</div>
    </div>
    <div>Panel 3</div>
    </body>
</html>

在Chrome,Safari和Firefox中有良好的support,并且计划在IE中提供支持。

答案 4 :(得分:0)

编辑2:

中测试过
  • Chrome / Safari:因计算百分比而导致1或2个像素失败
  • FireFox:完美
  • IE9:完美
  • Opera:百分比宽度值中不能包含小数位数。这是错误
  • lte IE8:不支持Array reduce功能。一个人必须做一个(如从这里:Array.reduce),然后它至少在IE8中工作

编辑1:

我添加了水平布局和窗口调整大小功能


我摆弄了一下:

这只是一个演示:要拥有一个完整的应用程序,您必须添加水平布局的编程。但它开始了

http://jsfiddle.net/HerrSerker/PmHtf/

这是代码

HTML

<div class="full-stretch">
        <div class="flex-layout flex-layout-vertical">
            <div class="flex-layout-fixed" style="height:50px; text-align: center">
                <div class="padding">Title</div>
            </div>
            <div class="flex-layout-consume flex-layout-consume-3" style="text-align: center">
                <div class="flex-layout flex-layout-horizontal">
                    <div class="flex-layout-consume flex-layout-consume-1" style="text-align: center">
                        <div class="padding">Panel 0</div>
                    </div>
                    <div class="flex-layout-consume flex-layout-consume-1" style="text-align: center">
                        <div class="padding">Panel 1</div>
                    </div>
                    <div class="flex-layout-consume flex-layout-consume-1" style="text-align: center">
                        <div class="padding">Panel 2</div>
                    </div>
                </div>

            </div>
            <div class="flex-layout-consume flex-layout-consume-1" style="text-align: center">
                <div class="padding">Panel 3</div>
            </div>
        </div>
</div>​

CSS

.full-stretch {
    position: absolute;
    top: 2px;
    right:2px;
    bottom:2px;
    left: 2px;
}
.padding {
    position: absolute;
    top: 2px;
    right:2px;
    bottom:2px;
    left: 2px;
    border: 1px solid darkGray;
    background: lightBlue;
    border-radius: 10px;
}

.flex-layout {
    position: absolute;
    top: 0;
    right:0;
    bottom:0;
    left: 0;
    overflow: hidden;
}

.flex-layout-consume {
    height: 100%;
    float:left;
    overflow: hidden;
    position: relative;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
}
.flex-layout-vertical > .flex-layout-consume {
    width: 100%;
}


.flex-layout-fixed {
    height: 100%;
    float:left;
    overflow: hidden;
    position: relative;

}
.flex-layout-vertical > .flex-layout-fixed {
    width: 100%;
}

的jQuery

(function($) {

  var flex = function() {
      $('.flex-layout').each(function() {
          var fixed = $(this).children('.flex-layout-fixed');


          if ($(this).hasClass('flex-layout-horizontal')) { // horizontal
              var fixed_widths = $(this)
                  .children('.flex-layout-fixed')
                  .get()
                  .reduce(function(total, elem) {
                      return (total + $(elem).outerWidth())
                  },0)
              ;
              var remain_width = ($(this).outerWidth() - fixed_widths)/$(this).outerWidth() * 100; // percent
              var consumers = $(this)
                  .children('.flex-layout-consume')
                  .get()
              ;
              var count_consumers = consumers
                  .reduce(function(total, elem) {
                      var cm = parseInt($(elem).attr('class').match(/flex-layout-consume-(\d+)/)[1]);
                      $(elem).data('consume_multiplicator', cm);
                      return total + cm;
                  },0)
              ;
              var consumers_tic = (remain_width/count_consumers)
              $(consumers).each(function() {
                  $(this).width(Math.round((consumers_tic * $(this).data('consume_multiplicator'))*1000)/1000+'%')
              }) 


          } else if ($(this).hasClass('flex-layout-vertical')) { // vertical
              var fixed_heights = $(this)
                  .children('.flex-layout-fixed')
                  .get()
                  .reduce(function(total, elem) {
                      return (total + $(elem).outerHeight())
                  },0)
              ;
              var remain_height = ($(this).outerHeight() - fixed_heights)/$(this).outerHeight() * 100; // percent
              var consumers = $(this)
                  .children('.flex-layout-consume')
                  .get()
              ;
              var count_consumers = consumers
                  .reduce(function(total, elem) {
                      var cm = parseInt($(elem).attr('class').match(/flex-layout-consume-(\d+)/)[1]);
                      $(elem).data('consume_multiplicator', cm);
                      return total + cm;
                  },0)
              ;
              var consumers_tic = (remain_height/count_consumers)
              $(consumers).each(function() {
                  $(this).height(Math.round((consumers_tic * $(this).data('consume_multiplicator'))*1000)/1000+'%')
              }) 
          }
    })
  };
  $(function() {
    flex()
        $(self).resize(flex)
  })                      
}(jQuery))
​

答案 5 :(得分:0)

我可能会在你的问题中遗漏一些东西,但看看这是否是你想要的。纯CSS解决方案,适用于IE7以下的所有浏览器。

http://jsfiddle.net/nyHgM/1/

答案 6 :(得分:0)

这是我的建议(纯css)...在IE7 +,Chrome&amp; FF http://jsfiddle.net/victmo/hKGUe/

<强> HTML

<div id='header'></div>
<div id='col0'></div>
<div id='col1'></div>
<div id='col2'></div>
<div id='footer'></div>

<强> CSS

div{
    position:absolute;
}

#header{
    top:0px;
    left:0px;
    right:0px;
    height:3em;
}

#footer{
    bottom:0px;
    left:0px;
    right:0px;
    height:2em;
}

#col0,
#col1,
#col2{
    top:3em; /* header height */
    bottom:2em; /* footer height */
    width:33.33%;
}

#col0{ left:0%;   width:30%; } /* left =  0       */
#col1{ left:30%;  width:40%; } /* left =  0 + 30  */
#col2{ left:70%;  width:30%; } /* left = 30 + 40  */




/* Colors */
#header{ background:#bbb; }
#col0{ background:#ccc; }
#col1{ background:#ddd; }
#col2{ background:#eee; }
#footer{ background:#aaa; }

​