Есть ли надежный кросс-браузерный способ распределить оставшееся пространство в родительском элементе между несколькими DIV? - PullRequest
5 голосов
/ 13 марта 2012

Фон

Я работаю над интерфейсом на основе браузера, который должен заполнять весь экран без прокрутки. Базовая раскладка выглядит так:

layout sketch

Чего я хочу достичь

Титульный div должен иметь фиксированную высоту (2em), а остальные 4 div / панели должны делиться на оставшееся пространство экрана в соответствии с установленным процентом.

Что я пробовал

Лучшее решение, которое я нашел, это " CSS - Как заставить элементы на 100% оставшегося / доступного пространства родительского элемента, не выходя за его пределы? ", что предполагает использование контейнера div с position:absolute. Это работает во всех браузерах, но требует создания дополнительных DIV. Кроме того, панель 2 иногда можно принудительно запустить на следующей строке из-за неточностей в процентах ширины .

Мое предыдущее решение было основано на CSS3 Flexbox , но модель имеет недостатки, поскольку она не изменяет размеры дочерних элементов, имеющих процентную высоту, после растяжения контейнеров (по крайней мере, в Chrome этого не происходит). (Более новые атрибуты flex- * реализованы только в Chrome, а стандарт все еще меняется.)

Я также попробовал функцию calc () ; однако это еще не реализовано в Chrome. Кроме того, он требует жесткого кодирования высоты элемента заголовка в двух местах, чего я пытался избежать.

Edit:

Что я ищу

Просто чтобы прояснить, я не прошу идеального / чистого CSS-решения (так как, похоже, ничего не существует). Если кто-то может предложить какой-либо плагин jQuery или фреймворк с открытым исходным кодом, который может сделать это, для меня это будет достаточно.

Кроме того, мне не требуется обратной совместимости с выпусками браузера до 2012 года. (Поскольку решение использует технологию, которая реализована в некоторых браузерах и будет внедрена Firefox и Chrome в ближайшем будущем, это достаточно хорошо для меня.)

Ответы [ 7 ]

8 голосов
/ 13 марта 2012

Немного что-то сшитое: http://jsfiddle.net/gDTGn/2/

2 голосов
/ 20 марта 2012

Чистое решение CSS: http://jsfiddle.net/ehqcx/7/embedded/result/

Предполагается, что вы установили ширину, которая в сумме не превышает 100%, небольшой пробел с правой стороны обычно можно исправить, используя тот же фон или фон страницы. Альтернативой является введение некоторого Javascript, который правильно устанавливает ширину последней панели, но это должен быть некоторый тривиальный код jQuery ... $("#panels .small:last").width(browser width - other small panels);

Должно работать правильно для высоты, продумайте заголовок jsFiddle, который снимает некоторую высоту ...

Edit:

Мех, кажется, #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%; }
2 голосов
/ 16 марта 2012

Вот чистая версия CSS:

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

Хитрость в этом методе заключается в использовании position:absolute и использовании top, bottom и height длясоздать фиксированный заголовок с расширяющимися панелями.Также очень важно использовать:

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

, чтобы сделать расчеты высоты и ширины согласованными в разных браузерах.Протестировано и работает в IE9, Firefox и Chrome.

0 голосов
/ 22 марта 2012

Это мое предложение (чистый CSS) ... Проверено на IE7 +, Chrome & 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; }

​
0 голосов
/ 17 марта 2012

Возможно, я что-то упустил в вашем вопросе, но посмотрите, ищите ли вы это Чистое решение CSS, которое работает во всех браузерах вплоть до IE7.

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

0 голосов
/ 16 марта 2012

редактировать 2:

Протестировано в

  • Chrome / Safari: сбой в 1 или 2 пикселях из-за процентов вычислений
  • FireFox: идеально
  • IE9: идеально
  • Опера: не может иметь десятичных разрядов в процентах значений ширины. Это плохо
  • lte IE8: не поддерживает функцию уменьшения массива. Нужно придумать один (как здесь: 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))
​
0 голосов
/ 16 марта 2012

Это возможно при использовании новой модели flexbox CSS3. Он был разработан для решения проблемы, с которой вы столкнулись.

Вот простой пример :

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, с плановой поддержкой в ​​IE.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...