Как создать макет html / css 3 строки, в котором средняя строка соответствует оставшемуся содержимому и не расширяет родительский

#html #css

#HTML #css

Вопрос:

Мне нужно создать макет с 3 строками, который будет находиться внутри среднего столбца макета flex с 3 столбцами.

Макет должен заполнять этот средний столбец (100%, 100%) и должен содержать:

  • Верхняя строка: может быть пустой или содержать содержимое. Его высота должна быть автоматической и должна расширяться до его содержимого.
  • Нижняя строка: такая же, как и верхняя строка.
  • Центральная строка: должна заполнять остальную часть вертикального пространства и не должна заставлять всю структуру расширяться за пределы того, что было изначально

Вот графическое описание:

введите описание изображения здесь

Сначала я попробовал с таблицей, однако возникла проблема, заключающаяся в том, что при расширении центральной ячейки она расширяла всю таблицу, и таблица не учитывала высоту.

Затем я попробовал с помощью display: flex и столкнулся с практически той же проблемой, когда центральный div получал много содержимого, внутреннее содержимое не прокручивалось, но div расширялся за пределы доступного пространства.

Я изо всех сил пытаюсь заставить эту работу работать так, как ожидалось…

Это одна из моих неудачных попыток:

https://jsfiddle.net/zm12bgxq/

 $("#fillme").click(() => {
  $("#row-center").empty();
  let pre = $("<pre>");
  pre.css({
    "white-space": "pre-wrap",
    "overflow-y": "scroll",
    "overflow-x": "auto"
  })
  $("#row-center").append(pre);
  for (let i = 0; i < 100; i  ) {
    pre.append("<span>Some long text, Some long text, Some long text, Some long text, Some long text, Some long text, Some long text<br></span>")
  }
})  
 html,
body {
  width: 100%;
  height: 100%;
}

#body {
  position: relative;
  top: 50px;
  left: 50px;
  height: 50%;
  width: 50%;
  background-color: green;
  display: flex;
  flex-direction: column;
}

#mainWin,
#content-wrapper {
  position: relative;
  width: 100%;
}

#content-wrapper {
  height: 100%;
}

#mainWin {
  flex: 1;
}

#menuBar {
  background-color: red;
  height: 40px;
  position: relative;
}

#content-wrapper {
  height: 100%;
  width: 100%;
  display: flex;
  border: 0 !important;
  margin: 0 !important;
  padding: 0 !important;
}

#column-left {
  flex-direction: row;
  display: block;
  position: relative;
  width: auto;
  height: 100%;
  border: 0 !important;
  margin: 0 !important;
  padding: 0 !important;
  background-color: green;
}

#column-right {
  flex-direction: row;
  display: block;
  position: relative;
  width: auto;
  height: 100%;
  border: 0 !important;
  margin: 0 !important;
  padding: 0 !important;
  background-color: green;
}

#column-center {
  flex-direction: row;
  display: flex;
  position: relative;
  height: 100%;
  flex: 1;
  border: 0 !important;
  margin: 0 !important;
  padding: 0 !important;
  background-color: yellow;
}

#center-content {
  display: flex;
  position: relative;
  height: 100%;
  width: 100%;
  flex-direction: column;
}

#center-content table {
  width: 100%;
  height: 100%;
  border: 0 !important;
  margin: 0 !important;
  padding: 0 !important;
  border-collapse: collapse;
  border-spacing: 0;
}

#center-content tr {
  border: 0 !important;
  margin: 0 !important;
  padding: 0 !important;
}

#center-content td {
  border: 0 !important;
  margin: 0 !important;
  padding: 0 !important;
}

#row-top {
  position: relative;
  width: 100%;
  height: 1%;
  flex-direction: column;
  border: 0 !important;
  margin: 0 !important;
  padding: 0 !important;
  background-color: blue;
}

#row-center {
  width: 100%;
  height: auto;
  position: relative;
  flex: 1;
  flex-direction: row;
  border: 0 !important;
  margin: 0 !important;
  padding: 0 !important;
  background-color: white;
}

#row-bottom {
  position: relative;
  width: 100%;
  height: 1%;
  flex-direction: row;
  border: 0 !important;
  margin: 0 !important;
  padding: 0 !important;
  background-color: magenta;
}  
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="body">
  <div id="menuBar">
    <ul>
      <li>Somemenu</li>
    </ul>
  </div>
  <div id="mainWin">
    <div id="content-wrapper">
      <div id="column-left">
        Left
      </div>
      <div id="column-center">
        <div id="center-content">
          <table>
            <tbody>
              <tr>
                <td id="row-top">Top</td>
              </tr>
              <tr>
                <td id="row-center">
                  <button id="fillme">
                Fill me
              </button>
                </td>
              </tr>
              <tr>
                <td id="row-bottom">
                  <div id="cmdCont">
                    <textarea autofocus="" rows="1" style="width:100%;height: 20px;"></textarea>
                  </div>
                </td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
      <div id="column-right">
        Right
      </div>
    </div>
  </div>
</div>  

Здесь все выглядит нормально, пока вы не нажмете кнопку, и белое поле не расширит таблицу … даже если таблица имеет фиксированный размер (50% от родительского). Pre получает полосу прокрутки, но поскольку она расширена до максимума, это ничего не значит…

Что должно произойти, так это то, что белое поле остается того же размера, и pre заполняет его, а pre получает полосу прокрутки, которая фактически прокручивается.

Еще одна проблема заключается в том, что в pre есть «пробел: pre», который не должен расширять белое поле ни по горизонтали. он должен быть обрезан или, если я добавлю overflow-x: scroll, он должен быть доступен для просмотра путем прокрутки pre.

Комментарии:

1. Я пытался создать для вас фрагмент, но ваш код div не совпадает с кодом таблицы в скрипке

2. извините, я разместил неправильную ссылку, я обновил вопрос сейчас

3. Но сделайте ФРАГМЕНТЫ, чтобы нам не приходилось оставлять ТАК, чтобы выглядеть

4. Сейчас есть один, но я не знал, как это сделать. Попробую в следующий раз. Извините.

5. Просто нажмите кнопку [<>] редактора фрагментов

Ответ №1:

Не можете ли вы просто добавить класс таким образом…

 pre {
 height: 100%;
 position: absolute;
 top: 0;
}
  

 $("#fillme").click(() => {
  $("#row-center").empty();
  let pre = $("<pre>");
  pre.css({
    "white-space": "pre-wrap",
    "overflow-y": "scroll",
    "overflow-x": "auto"
  })
  $("#row-center").append(pre);
  for (let i = 0; i < 100; i  ) {
    pre.append("<span>Some long text, Some long text, Some long text, Some long text, Some long text, Some long text, Some long text<br></span>")
  }
})  
 pre {
 height: 100%;
 position: absolute;
 top: 0;
}
  
html,
body {
  width: 100%;
  height: 100%;
}

#body {
  position: relative;
  top: 50px;
  left: 50px;
  height: 50%;
  width: 50%;
  background-color: green;
  display: flex;
  flex-direction: column;
}

#mainWin,
#content-wrapper {
  position: relative;
  width: 100%;
}

#content-wrapper {
  height: 100%;
}

#mainWin {
  flex: 1;
}

#menuBar {
  background-color: red;
  height: 40px;
  position: relative;
}

#content-wrapper {
  height: 100%;
  width: 100%;
  display: flex;
  border: 0 !important;
  margin: 0 !important;
  padding: 0 !important;
}

#column-left {
  flex-direction: row;
  display: block;
  position: relative;
  width: auto;
  height: 100%;
  border: 0 !important;
  margin: 0 !important;
  padding: 0 !important;
  background-color: green;
}

#column-right {
  flex-direction: row;
  display: block;
  position: relative;
  width: auto;
  height: 100%;
  border: 0 !important;
  margin: 0 !important;
  padding: 0 !important;
  background-color: green;
}

#column-center {
  flex-direction: row;
  display: flex;
  position: relative;
  height: 100%;
  flex: 1;
  border: 0 !important;
  margin: 0 !important;
  padding: 0 !important;
  background-color: yellow;
}

#center-content {
  display: flex;
  position: relative;
  height: 100%;
  width: 100%;
  flex-direction: column;
}

#center-content table {
  width: 100%;
  height: 100%;
  border: 0 !important;
  margin: 0 !important;
  padding: 0 !important;
  border-collapse: collapse;
  border-spacing: 0;
}

#center-content tr {
  border: 0 !important;
  margin: 0 !important;
  padding: 0 !important;
}

#center-content td {
  border: 0 !important;
  margin: 0 !important;
  padding: 0 !important;
}

#row-top {
  position: relative;
  width: 100%;
  height: 1%;
  flex-direction: column;
  border: 0 !important;
  margin: 0 !important;
  padding: 0 !important;
  background-color: blue;
}

#row-center {
  width: 100%;
  height: auto;
  position: relative;
  flex: 1;
  flex-direction: row;
  border: 0 !important;
  margin: 0 !important;
  padding: 0 !important;
  background-color: white;
}

#row-bottom {
  position: relative;
  width: 100%;
  height: 1%;
  flex-direction: row;
  border: 0 !important;
  margin: 0 !important;
  padding: 0 !important;
  background-color: magenta;
}  
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="body">
  <div id="menuBar">
    <ul>
      <li>Somemenu</li>
    </ul>
  </div>
  <div id="mainWin">
    <div id="content-wrapper">
      <div id="column-left">
        Left
      </div>
      <div id="column-center">
        <div id="center-content">
          <table>
            <tbody>
              <tr>
                <td id="row-top">Top</td>
              </tr>
              <tr>
                <td id="row-center">
                  <button id="fillme">
                Fill me
              </button>
                </td>
              </tr>
              <tr>
                <td id="row-bottom">
                  <div id="cmdCont">
                    <textarea autofocus="" rows="1" style="width:100%;height: 20px;"></textarea>
                  </div>
                </td>
              </tr>
            </tbody>
          </table>
        </div>
      </div>
      <div id="column-right">
        Right
      </div>
    </div>
  </div>
</div>  

Комментарии:

1. Il работает в Chrome, в Firefox таблица расширяется по вертикали за пределы процента от относительного родительского набора в его стиле.

2. Возможно, tables — это не выход, но у меня похожие проблемы с настройками макета с помощью divs.

3. Просто установите position: absolute и top: 0; Проверьте обновление.

Ответ №2:

Вам действительно следует избегать использования <table> для размещения вашей страницы (если только это не для реальной таблицы). Избавьте себя от будущих проблем и используйте вместо этого CSS grid.

Макет из 3 столбцов, аналогичный тому, как вы описали, так же прост, как:

 .container {
  height: 100%;
  display:grid;
  grid-template-rows: auto 1fr auto;
}

.middle {
  overflow: scroll;
}
  

РЕДАКТИРОВАТЬ: я не мог легко определить, какой код в вашей скрипке был требованием, а какой был просто частью процесса отладки. Итак, вот реплика, которую я перестроил с помощью CSS grid, которая решает вашу проблему:

https://jsfiddle.net/mwsj94qx/

Комментарии:

1. Мне кажется, что 1fr расширяется дальше, чем высота его родительского элемента, когда содержимое внутри высокое. По крайней мере, протестировано в firefox. Возможно, я что-то упускаю. Если вы можете заставить скрипку работать, начав с моей скрипки в вопросе, это было бы идеально.

2. Я обновил свой ответ новой скрипкой. Много html / css было удалено, но я надеюсь, что вы все еще можете найти это полезным. 🙂

3. Спасибо за усилия, Эдди, к сожалению, я уже знал, что предоставление переполнения средней ячейки устраняет проблему. Однако это не работает для меня, потому что внутренний PRE, который я вводю, является компонентом, к которому у меня нет доступа, и управляет его собственной прокруткой. Таким образом, PRE должен прокручиваться, а не div, как в вашем примере.

4. Интересно, вы можете присвоить внутреннему <pre> a height: 100% ? Это приведет к его сужению и позволит прокручивать. (Я изменил ту же скрипку на новую с примером)