Подтвердить что ты не робот

Установка длины (высоты или ширины) для одного элемента за вычетом переменной длины другой, т.е. Calc (x - y), где y неизвестно

Я знаю, что мы можем использовать calc, когда определены длины:

flex-basis: calc(33.33% - 60px);
left: calc(50% - 25px);
height: calc(100em/5);

Но что, если длина переменной?

height: calc(100% - <<header with variable height>>);

ИЛИ

width: calc(100% - 50px - <<box with variable width>>);

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

Есть ли стандартный способ сделать это в CSS?

Я знаю, что общая задача возможна с помощью flexbox и таблиц, но мне интересно, предлагает ли CSS более простой метод. Flexbox, таблицы и простой Javascript являются приемлемыми альтернативами.

демонстрация высоты

демонстрация ширины

4b9b3361

Ответ 1

Вы можете использовать таблицы CSS:

.wrapper {
  display: table;
  width: 100%;
  margin: 15px 0;
}

.horizontal.wrapper > div {
  display: table-cell;
  white-space: nowrap; /* Prevent line wrapping */
  border: 1px solid;
}
.left { width: 100px } /* Minimum width of 100px */
.center { width: 0; }  /* Width given by contents */

.vertical.wrapper { height: 200px; }
.vertical.wrapper > div {
  display: table-row;
}
.vertical.wrapper > div > span {
  display: table-cell;
  border: 1px solid;
}
.top    { height: 100px; } /* Minimum heigth of 100px */
.middle { height: 0; }     /* Height given by content */
.bottom { height: 100%; }  /* As tall as possible */
<div class="horizontal wrapper">
  <div class="left">100px wide</div>
  <div class="center">Auto width, given by contents</div>
  <div class="right">Remaining space</div>
</div>
<div class="vertical wrapper">
  <div class="top"><span>100px tall</span></div>
  <div class="middle"><span>Auto height, given by contents</span></div>
  <div class="bottom"><span>Remaining space</span></div>
</div>

Ответ 2

Flexbox может это сделать.

Поддержка IE10 и выше.

JSfiddle Demo

* {
  margin: 0;
  padding: 0;
}
html,
body {
  height: 100%;
}
#container {
  height: 100%;
  display: flex;
  flex-direction: column;
}
#top {
  background-color: lightgreen;
}
#bottom {
  background-color: lightblue;
  flex: 1;
}
<div id="container">
  <div id="top">green box variable height</div>
  <div id="bottom">blue box no longer overflows browser window</div>
</div>

Ответ 3

Я ищу что-то простое и портативное. Точно так же CSS собственность может быть легко применена через документы, я ищу что-то подобное с точки зрения простоты приложения для этой функции.

... изолированное исправление является предпочтительным.

Горизонтально:

Это может быть достигнуто только с помощью CSS. Поскольку вы не предпочитаете макетное решение flex, следующей лучшей ставкой будет таблица.

Простой фрагмент CSS, который вы могли бы занести в свой проект (и сделать это), будет выглядеть следующим образом:

div.flexh {
    display: table; box-sizing: border-box; padding: 0; margin: 0;
}
div.flexh > div { 
    display: table-cell; width: auto; 
    box-sizing: border-box; vertical-align: middle;
}
div.flexh > div:first-child {
    /* Override your custom styling below */
    min-width: 75px; width: 75px; max-width: 75px; 
}
div.flexh > div:last-child { width: 100%; }

Затем вы можете добавить стиль вашего сайта для этого базового CSS в соответствии с требованиями сайта. Например, nowrap и т.д.

Двумя очевидными преимуществами этого решения являются:

  • Вам не нужно менять свою разметку, а также не нужно украшать всех детей классами. Просто примените класс flexh к вашему родительскому div, и это было бы так.

Требуется минимальная разметка:

<div class="flexh">
    <div>...</div>
    <div>...</div>
    <div>...</div>
</div>
  1. Вы не ограничены только тремя столбцами. У вас может быть столько столбцов, сколько потребуется. Первая имеет фиксированную ширину, последняя будет гибкой, а все столбцы между ними получат ширину на основе контента.

Демо-скрипт: http://jsfiddle.net/abhitalks/qqq4mq23/

Демо-фрагмент:

div.flexh {
    display: table; box-sizing: border-box; padding: 0; margin: 0;
    /* Override your custom styling below */
    width: 80%; border: 2px solid black;
    border-right: 2px dashed black; 
    font-size: 1em;
}
div.flexh > div { 
    display: table-cell; width: auto; 
    box-sizing: border-box; vertical-align: middle;
    /* Override your custom styling below */
    background-color: lightgreen; border: 1px solid #ddd;
    padding: 15px 5px;
}
div.flexh > div:first-child {
    /* Override your custom styling below */
    min-width: 75px; width: 75px; max-width: 75px; 
    background-color: orange;
}
div.flexh > div:last-child {
    width: 100%;
    /* Override your custom styling below */
    background: skyblue;
}
<div class="flexh">
    <div>75px Fixed Width</div>
    <div>Variable Content Width</div>
    <div>Flexible Remaining Width</div>
</div>

<hr/>
<div class="flexh">
    <div>75px Fixed Width</div>
    <div><img src='//placehold.it/128x48/66c' /></div>
    <div>Flexible Remaining Width</div>
</div>

<hr/>
<div class="flexh">
    <div>75px Fixed Width</div>
    <div>Variable TextWidth</div>
    <div>
        <img src='//placehold.it/128x48/66c' />
        <p>Variable ContentWidth</p>
    </div>
    <div>Flexible Remaining Width</div>
</div>

Ответ 4

Обновление

Как я уже говорил , и кроме flex, это также разрешимо с помощью display: table, и вот демонстрация скриптов Я показал это.

Если для вертикальной демонстрации требуется фиксированная вершина, вот обновленная версия моей оригинальной версии display:table: скриптная демонстрация

Иногда я не мог (или не хотел) использовать либо flex, либо таблицы, и у меня вкл и выкл было использовано css calc() и css attr().

Оба заканчиваются, хотя, поскольку calc() может использовать только +-*/, а attr() может возвращать только строковое значение, которое невозможно вычислить с помощью calc().

Мое предложение, использующее простой javascript, основано на том, что эти 2 метода в какой-то момент могут быть расширены, чтобы мы могли лучше их использовать.

Вот как я хотел бы видеть, как они работают:

width: calc(100% - attr(this.style.left))

но, как они этого не делают, и я не могу добавить его в свой CSS, так как он не будет правильно проверять (может даже сломать синтаксический разбор, кто знает). Вместо этого я добавил вариант как атрибут элемента, с некоторыми причудами, чтобы упростить вычисление.

И в этом случае (2 демонстрации) это выглядит так:

//height
<div id="bottom" data-calcattr="top,height,calc(100% - toppx)">...</div>

//width 
<div class="box right" data-calcattr="left,width,calc(100% - leftpx)">...</div>

Вместе с ниже script, который никоим образом не полностью разработан/протестирован во всех комбинациях свойств, он корректирует размер div.

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

Вот скрипка, показывающая как демонстрацию высоты, так и ширину, интегрированную, используя тот же script.

function calcattr() {
    var els = document.querySelectorAll('[data-calcattr]');
    for (i = 0; i < els.length; i++) {
        var what = els[i].getAttribute('data-calcattr');
        if (what) {
            what = what.split(',');
            var rect = els[i].getBoundingClientRect();
            var parentrect = els[i].parentNode.getBoundingClientRect();
            var brd = window.getComputedStyle(els[i].parentNode,null).getPropertyValue('border-' + what[0] + '-width');            
            what[2] = what[2].replace(what[0],parseInt(rect[what[0]]-parentrect[what[0]]) - parseInt(brd));
            els[i].setAttribute("style", what[1] + ":" + what[2]);
        }
    }
}

Ответ 6

В обоих случаях на контейнере css вы должны поставить:

#container {
    overflow: hidden;
}

Но он скроет информацию, которая переполняет контейнер. Я думаю, что это так, поскольку вы помещаете white-space: nowrap;, это означает, что вы не хотите изменять высоту, поэтому вам нужно скрыть текст, который не может соответствовать контейнеру.