设置一个元素的长度(高度或宽度)减去另一个元素的可变长度,即calc(x-y),其中y未知

Mic*_*l_B 27 javascript css jquery css3 flexbox

我知道我们可以calc在定义长度时使用:

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

但是如果长度是可变的呢?

height: calc(100% - <<header with variable height>>);
Run Code Online (Sandbox Code Playgroud)

要么

width: calc(100% - 50px - <<box with variable width>>);
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

在CSS中有一种标准的方法吗?

我知道使用flexbox和表可以完成整个任务,但我想知道CSS是否提供了一种更简单的方法.Flexbox,表格和简单的Javascript是可接受的替代方案.

高度演示

宽度演示

Ori*_*iol 15

您可以使用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 */
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

水平箱也可以用浮筒实现:

#wrapper, .right { overflow: hidden; } /* Establish BFC */
#wrapper > div { border: 1px solid; }
.left, .middle { float: left; }
.left { width: 100px }
Run Code Online (Sandbox Code Playgroud)
<div id="wrapper">
  <div class="left">100px</div>
  <div class="middle">Auto width, given by contents</div>
  <div class="right">Remaining space</div>
</div>
Run Code Online (Sandbox Code Playgroud)


Pau*_*e_D 7

Flexbox可以做到这一点.

支持IE10及以上.

JSfiddle演示

* {
  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;
}
Run Code Online (Sandbox Code Playgroud)
<div id="container">
  <div id="top">green box variable height</div>
  <div id="bottom">blue box no longer overflows browser window</div>
</div>
Run Code Online (Sandbox Code Playgroud)


Abh*_*lks 5

我正在寻找简单便携的东西.同样,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%; }
Run Code Online (Sandbox Code Playgroud)

然后,您可以根据站点要求将特定于站点的样式添加到此基本CSS.喜欢nowrap

该解决方案的两个明显优势是:

  1. 您不需要更改标记,也不需要使用类来装饰所有子项.只需将该类flexh应用于您的父级即可div.

最低标记要求:

<div class="flexh">
    <div>...</div>
    <div>...</div>
    <div>...</div>
</div>
Run Code Online (Sandbox Code Playgroud)
  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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)


垂直:

没有flex布局,实现这一点有点棘手.表格布局在这里不起作用主要是因为,table-row不会保持用例所要求的固定高度.在height上一个table-rowtable-cell仅仅是一个指示所需要的最小的高度.如果空间受限制,或内容超出可用空间,则cellrow将根据内容增加其高度.

根据这里的规范:http://www.w3.org/TR/CSS21/tables.html#height-layout

一旦用户代理具有行中的所有单元格,就会计算"表格行"元素框的高度:它是行的计算"高度"的最大值,即行中每个单元格的计算"高度",和细胞所需的最小高度(MIN)......

...单元格框的高度是内容所需的最小高度

这种效果可以在这里看到:http://jsfiddle.net/abhitalks/6eropud3/

(调整窗口窗格的大小,您将看到第一行的高度会增加,因为内容无法适应指定的高度,因此无法实现目的)

因此,您可以使用内部标记(如div元素)间接限制高度,或者放开表格布局并计算灵活的高度.在您的用例中,您不希望更改标记,因此我不建议使用内部标记.

这里最好的选择是使用经过时间考验的普通block级别模型,div并计算灵活高度.正如您已经发现CSS无法实现的那样,您需要一个小的JavaScript代码段来为您完成.

一个简单的JavaScript代码段(没有jQuery),你可以包装window.load并放入你的项目(并完成)将如下所示:

var flexv = document.querySelectorAll('div.flexv');
/* iterate the instances on your page */    
[].forEach.call(flexv, function(div) {
    var children = [].slice.call(div.children), // get all children
        flexChild = children.splice(-1, 1),     // get the last child
        usedHeight = 0, totalHeight = div.offsetHeight;

    children.forEach(function(elem) {
        usedHeight += elem.offsetHeight; // aggregate the height
    });
    /* assign the calculated height on the last child */
    flexChild[0].style.height = (totalHeight - usedHeight) + 'px';
});
Run Code Online (Sandbox Code Playgroud)

CSS片段或多或少类似于水平片段,没有表格布局,您也可以将其放入项目中,只需添加其他特定于站点的样式.所需的最小标记保持不变.

演示小提琴2:http://jsfiddle.net/abhitalks/Ltcuxdwf/

演示片段:

document.addEventListener("load", flexit);

function flexit(e) {
	var flexv = document.querySelectorAll('div.flexv');
	[].forEach.call(flexv, function(div) {
		var children = [].slice.call(div.children), 
			flexChild = children.splice(-1, 1), 
			usedHeight = 0, totalHeight = div.offsetHeight;
		children.forEach(function(elem) {
			usedHeight += elem.offsetHeight;
		});
		flexChild[0].style.height = (totalHeight - usedHeight) + 'px';
	});
}
Run Code Online (Sandbox Code Playgroud)
div.flexv {
    display: inline-table; box-sizing: border-box; padding: 0; margin: 0; 
    overflow: hidden;
    /* Override your custom styling below */
    height: 320px; width: 20%; border: 1px solid black; font-size: 1em;
    margin: 8px;
}
div.flexv > div { 
    display: block; height: auto; box-sizing: border-box; 
    overflow: hidden;
    /* Override your custom styling below */
    background-color: lightgreen; border: 1px solid #ddd;
    padding: 5px 15px;
}
div.flexv > div:first-child {
    /* Override your custom styling below */
    min-height: 36px; height: 36px; max-height: 36px; 
    background-color: orange;
}
div.flexv > div:last-child {
    height: 100%;
    /* Override your custom styling below */
    background: skyblue;
}
Run Code Online (Sandbox Code Playgroud)
<div class="flexv">
    <div>36px Fixed Height</div>
    <div>Variable Content Height</div>
    <div>Flexible Remaining Height</div>
</div>

<div class="flexv">
    <div>36px Fixed Height</div>
    <div><img src='//placehold.it/64x72/66c' /></div>
    <div>Flexible Remaining Height</div>
</div>

<div class="flexv">
    <div>36px Fixed Height</div>
    <div>Variable Text Height</div>
    <div>
        <img src='//placehold.it/72x48/66c' />
        <p>Variable Content Height</p>
    </div>
    <div>Flexible Remaining Height</div>
</div>
Run Code Online (Sandbox Code Playgroud)

注意:正如@LGSon所指出的,display: inline-table用于演示的程序并不适用于Firefox.这是仅适用于演示,应由要么更换blockinline-block按照您的使用情况.