Установка длины (высоты или ширины) для одного элемента за вычетом переменной длины другой, т.е. 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 являются приемлемыми альтернативами.
демонстрация высоты
демонстрация ширины
Ответы
Ответ 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>
- Вы не ограничены только тремя столбцами. У вас может быть столько столбцов, сколько потребуется. Первая имеет фиксированную ширину, последняя будет гибкой, а все столбцы между ними получат ширину на основе контента.
Демо-скрипт: 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]);
}
}
}
Ответ 5
В CSS
Хотя я никогда не пробовал, я считаю, что это сработает:
.top {
height:13px;
}
.main {
height:calc(100% - var(height));
}
http://www.creativebloq.com/netmag/why-you-need-use-css-variables-91412904
В SASS
$top_height: 50px
.main {
height: calc(100% - $top_height)
}
Функция Sass Variable в функции CSS calc()
Ответ 6
В обоих случаях на контейнере css вы должны поставить:
#container {
overflow: hidden;
}
Но он скроет информацию, которая переполняет контейнер. Я думаю, что это так, поскольку вы помещаете white-space: nowrap;
, это означает, что вы не хотите изменять высоту, поэтому вам нужно скрыть текст, который не может соответствовать контейнеру.