CSS:将宽度/高度设置为百分比减去像素


479

我试图创建一些可重用的CSS类,以提高网站的一致性和减少混乱,而且我坚持尝试标准化我经常使用的一件事。

我有一个<div>我不想为其设置高度的容器(因为它会根据其在网站上的位置而有所不同),并且在其中是一个header <div>,然后是一个无序的项目列表,所有这些项目都应用了CSS他们。

看起来很像这样:

小部件

我想无序列表占用容器中剩余的房间<div>,知道头部<div>18px高大的。我只是不知道如何将列表的高度指定为“ 100%减去的结果18px”。

我已经在SO的其他几个上下文中看到了这个问题,但是我认为有必要再次询问我的特殊情况。在这种情况下,有人对您有任何建议吗?


6
设置边距?__
kennytm 2010年

@KennyTM,我认为您是在建议我在无序列表(例如17像素)上放置页边空白。但这只是将整个列表推低了。它不会导致它收缩以留在容器中。从本质上讲,它保持了当前的高度,但仅被降低了17px。这不能解决我的问题,但是我认为这是朝正确方向迈出的一步,因为我在网上看到了其他使用该技术的方法。
MegaMatt 2010年

我刚刚在这里发布的问题中解决了这个问题。stackoverflow.com/a/10420387/340947
史蒂文·卢

Answers:


895

我意识到这是一篇过时的文章,但是鉴于没有被建议,值得一提的是,如果您正在编写与CSS3兼容的浏览器,则可以使用calc

height: calc(100% - 18px);

值得注意的是,并不是目前所有的浏览器都支持标准的CSS3 calc()函数,因此可能需要实现该功能的浏览器特定版本,如下所示:

/* Firefox */
height: -moz-calc(100% - 18px);
/* WebKit */
height: -webkit-calc(100% - 18px);
/* Opera */
height: -o-calc(100% - 18px);
/* Standard */
height: calc(100% - 18px);

5
是的,暂时正常。
Levi Botelho 2013年

1
在IE10和Chrome 27中为我工作。您好,先生,我的英雄!
BrainSlugs83 2013年

3
@LeviBotelho我不好。操作员周围没有空间。
用户

20
另外,如果使用Less,则最好使用编译文件,lessc --strict-math=on以免评估内部表达式calc-只是我遇到的问题并花费了大量时间(从Less 2.0.0开始)
Dmitry Wojciechowski

34
请注意,周围的减号的空间是不可选的:100%-18px100%- 18px,并100% -18px没有在我测试的浏览器。
nisetama

71

对于一些不同的方法,可以在列表中使用类似以下内容的方法:

position: absolute;
top: 18px;
bottom: 0px;
width: 100%;

只要父容器具有 position: relative;


1
谢啦。父容器正在position: relative;绊倒我。
gthmb 2012年

对于那些可能像我这样想知道的人:位置必须absolute位于子容器中,而不能位于relative
2015年

续(对不起):但是,父级只需要定位(也可以absolute),也需要将其设置为100%的高度。
格雷格

1
不幸的是,它在Safari iOS 8上不起作用。(在Android 4.1股票浏览器和标准FF 34上经过测试,正常运行):-(
Greg,

在某些情况下,这可能会起作用,但也可能会造成一些麻烦,因为从正常流中删除了绝对定位的元素,请参阅stackoverflow.com/a/12821537/4173303
Christophe Weis 2015年

26

我为此使用jQuery

function setSizes() {
   var containerHeight = $("#listContainer").height();
   $("#myList").height(containerHeight - 18);
}

然后绑定窗口调整大小以在每次调整浏览器窗口大小时重新计算它(如果容器的大小随着窗口调整大小而改变)

$(window).resize(function() { setSizes(); });

12
@puffpio,当然,JS是一种根据具体情况完成此操作的方法。但是正如我所说,我正在尝试使CSS通用,以应用于多个页面(顺便说一句,这些页面继承自母版页)。因此,我不想使用JS。但是,谢谢您的回答。
MegaMatt 2010年

7
不要将样式放在JavaScript中。
格雷格2012年

8
@greg,如果CSS具有一些更有用的功能,它将很有帮助。您要做的某些事情很荒谬。
乔纳森。

1
@puffpio确实是不错的解决方案。但是在窗口上绑定事件对我来说不是一个好的解决方案。如果我的页面上有3-4个或更多此类元素,则必须在窗口调整大小处理程序中更新每个元素的高度和宽度。这将比CSS解决方案慢一些。
sachinjain024

1
“不要将xyz放入JavaScript中”就像在说“不支持80%的浏览器市场”。
Beejor

16

不要将高度定义为百分比,只需设置top=0bottom=0,如下所示:

#div {
   top: 0; bottom: 0;
   position: absolute;
   width: 100%;
}

您能否解释为什么不将高度设置为百分比?
Shrikant Sharat

@ShrikantSharat这是绝对定位元素的视觉格式规范的一部分。该解决方案利用了可能性5的优势。“高度”为“自动”,“顶部”和“底部”不是“自动”,然后设置了“ margin-top”和“ margin-bottom”的“ auto”值设为0并求解“高度””。浏览器可以计算元素的高度,因为它知道距父元素的顶部和底部有多远。
罗斯·艾伦

至少在Firefox中,这似乎不起作用。即使所有父元素都设置为height:100%display:block。否则,这将是一个非常优雅的解决方案。有趣的是,margin:auto即使固定宽度的对象在水平方向上也可以正常工作,但它也无法在垂直方向上居中。
Beejor

8

假设标题高度为17px

列出CSS:

height: 100%;
padding-top: 17px;

标头CSS:

height: 17px;
float: left;
width: 100%;

是的,那就是我的意思。
dclowd9901 2010年

1
那没有我所希望的那么好。我的无序列表从该标题div下开始。标头div占用了容器中的空间,因此将17px的padding-top放在列表上只是要将其从上图中的位置向下推17px,而不是从容器div顶部推17px。这是上面答案中给出的CSS的图片:i41.tinypic.com/mcuk1x.jpg。不过,我很感谢您的努力,如果您认为我缺少某些东西,请告诉我。顺便说一句,我有溢出:自动在无序列表上。
MegaMatt 2010年

2
如果您发布了实际的CSS,则对它进行故障排除会容易得多,这样我们就可以准确了解正在发生的交互。您可能尝试的另一件事是您的ul的负上边距。ul { margin-top: -17px; }
ghoppe

7
  1. 在要减去像素的元素上使用负边距。(所需元素)
  2. 使 overflow:hidden;包含元素
  3. 切换到overflow:auto;所需的元素。

它为我工作!


3
这对我来说就像是一种魅力(我什至不需要更改溢出)。很好的解决方案,谢谢!
2013年

1
非常棒!很高兴了解流行的“ CSS calc”解决方案,但这要简单得多,并且具有更广泛的浏览器支持。负边距完美!
西蒙·斯坦伯格2014年

这是一个非常优雅且兼容的解决方案。主要缺点是该元素必须为固定高度。否则,您将需要使用JS或calc()在运行时将其居中。但是在许多情况下,这不应该成为问题。要记住的另一件事是,在以后调试代码时,对边距,填充和偏移使用大量负值会导致混乱,因此,请尝试使事情保持简单。
Beejor

5

尝试调整大小。对于列表:

height: 100%;
/* Presuming 10px header height */
padding-top: 10px;
/* Firefox */
-moz-box-sizing: border-box;
/* WebKit */
-webkit-box-sizing: border-box;
/* Standard */
box-sizing: border-box;

对于标题:

position: absolute;
left: 0;
top: 0;
height: 10px;

当然,父容器应具有以下内容:

position: relative;

3

实现相同目标的另一种方法:flex box。将容器设为一列弹性框,然后您就可以自由地允许某些元素具有固定大小(默认行为)或填充/缩小到容器空间(使用flex-grow:1和flex-缩小:1)。

#wrap {        
  display:flex;
  flex-direction:column;
}
.extendOrShrink {
  flex-shrink:1;
  flex-grow:1;
  overflow:auto;
}

请参阅https://jsfiddle.net/2Lmodwxk/ (尝试扩展或缩小窗口以注意效果)

注意:您也可以使用简写属性:

   flex:1 1 auto;

我认为这可能是今天最好的答案,因为这意味着不必为标题div指定高度(在我的原始问题中为18px),并且不必减去填充和边距之类的内容。没有设置像素,一切都会自理。
MegaMatt

2

我尝试了其他一些答案,但都没有达到我想要的效果。我们的情况非常相似,我们有一个窗口标题,并且该窗口可以通过窗口主体中的图像进行调整大小。我们想要锁定调整大小的宽高比​​,而无需添加计算来考虑标头的固定大小,并且仍然使图像充满窗体。

下面,我创建了一个非常简单的代码段,该代码段显示了我们最终完成的操作,该操作对于我们的情况似乎很有效,并且应该与大多数浏览器兼容。

在我们的窗口元素上,我们添加了20px的边距,这有助于相对于屏幕上的其他元素定位,但不影响窗口的“大小”。然后,将窗口标题放置在绝对位置(将其从其他元素的流中删除,因此不会导致其他元素(如无序列表)移动),并且其顶部放置在-20px处,从而将标题放置在页边距内窗户的 最后,我们的ul元素被添加到窗口中,并且高度可以设置为100%,这将导致它填充窗口的主体(不包括边距)。

*,*:before,*:after
{
  box-sizing: border-box;
}

.window
{
  position: relative;
  top: 20px;
  left: 50px;
  margin-top: 20px;
  width: 150px;
  height: 150px;
}

.window-header
{
  position: absolute;
  top: -20px;
  height: 20px;
  border: 2px solid black;
  width: 100%;
}

ul
{
  border: 5px dashed gray;
  height: 100%;
}
<div class="window">
  <div class="window-header">Hey this is a header</div>
  <ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
    <li>Item 5</li>
  </ul>
</div>


1

谢谢,我在您的帮助下解决了我的问题,对它进行了一些调整,因为我希望div的宽度为100%,宽度为100%(底部栏的高度较小),并且主体上没有滚动条(没有hack /隐藏滚动条)。

对于CSS:

 html{
  width:100%;height:100%;margin:0px;border:0px;padding:0px;
 }
 body{
  position:relative;width:100%;height:100%;margin:0px;border:0px;padding:0px;
 }
 div.adjusted{
  position:absolute;width:auto;height:auto;left:0px;right:0px;top:0px;bottom:36px;margin:0px;border:0px;padding:0px;
 }
 div.the_bottom_bar{
  width:100%;height:31px;margin:0px;border:0px;padding:0px;
}

对于HTML:

<body>
<div class="adjusted">
 // My elements that go on dynamic size area
 <div class="the_bottom_bar">
  // My elements that goes on bottom bar (fixed heigh of 31 pixels)
 </div>  
</div>  

就是这样做了,哦,是的,我在div。上调整的值比调整底部的高度要大一些,否则显示垂直滚动条,我将其调整为最接近的值。

这种差异是因为动态区域上的元素之一是增加了一个我不知道如何摆脱的底孔...这是一个视频标签(HTML5),请注意,我在该视频标签中添加了这个CSS(因此没有理由在底部打孔,但确实如此):

 video{
  width:100%;height:100%;margin:0px;border:0px;padding:0px;
 }

令人讨厌的东西:有一部视频占用了100%的浏览量(并在调整浏览器大小时动态调整了大小,但没有改变宽高比),而我用于某些文本,按钮等(以及验证器)的div的底部空间W3C和CSS)。

编辑:我发现了原因,视频标签就像文本,而不是块元素,所以我用此CSS修复了它:

 video{
  display:block;width:100%;height:100%;margin:0px;border:0px;padding:0px;
 }

注意display:block;on video标签。


0

我不确定这是否在您的特定情况下有效,但是我发现,如果包含的div是固定大小,则在div内部填充将在div内部推送内容。您将不得不浮动或绝对定位标头元素,但是否则,我没有针对可变大小的div尝试过此操作。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.