xHTML/CSS:如何使内部div获得100%的宽度减去另一个div的宽度?

51

我有一个嵌套在外部div内的两个内部div,外部div的宽度为100%。这两个嵌套的div应该在同一行,并且第一个div应该根据其内容获得大小:

<div id="#outer" style="width:100%; border:1px">
  <div id="#inner1" style="border:1px; display:inline">
    inner div 1. Some text...
  </div>
  <div id="#inner2" style="width:100%????; border:1px; display:inline">
    inner div 2...
  </div>
</div>

如何在不指定#inner1 div宽度且其宽度取决于内部内容的情况下,使#inner2 div占据水平空间的其余部分?

注:我的情况下所有样式均在单独的类中,这里将CSS放入style属性中只是为了简化。

我希望结果能在IE7+和FF 3.6中工作。

更详细地说,对我来说,问题是这样的:

 <style type="text/css">
.captionText
{
 float:left;
} 

.captionLine
{
 height: 1px;
 background-color:black;
 margin: 0px;
 margin-left: 5px;
 margin-top: 5px;
 border: 0px;
 padding: 0px;
 padding-top: 1px;
}
 </style>
<table style="width:300px;">
<caption width="100%">
     <div class="captionText">Some text</div>
     <div class="captionLine"> </div>
</caption>
     <tr>
           <td>something</td>
     </tr>
</table>

以下是我想要的图片: Image of what I want


我知道我可以使用表格来实现,但我想使用div来完成。 - Artem
1
这对于表格来说可能不太明显。我从来没有完全理解浏览器用来计算未定义表格列宽度的规则。 - Paul D. Waite
10个回答

86

神秘的overflow: hidden;在这里是你的朋友。它阻止了与浮动元素相邻的元素延伸到浮动元素后面,我想这就是你要的布局。

这里有一些稍微编辑过的HTML:我认为你不能在你的id中使用#字符:

<div id="outer">
    <div id="inner1">
        inner div 1. Some text...
    </div>
    <div id="inner2">
        inner div 2...
    </div>
</div>

以下是实现您想要的布局所需的CSS。

(我加入了适用于IE 6的附加CSS和HTML 条件注释。我刚刚注意到您实际上不需要它在IE 6中工作,但如果您想对那里的IE 6用户友好...)

<style type="text/css">
#outer {
    overflow: hidden;/* Makes #outer contain its floated children */
    width: 100%;

    /* Colours and borders for illustration purposes */
    border: solid 3px #666;
    background: #ddd;
}

#inner1 {
    float: left;/* Make this div as wide as its contents */

    /* Colours and borders for illustration purposes */
    border: solid 3px #c00;
    background: #fdd;
}

#inner2 {
    overflow: hidden;/* Make this div take up the rest of the horizontal space, and no more */

    /* Colours and borders for illustration purposes */
    border: solid 3px #00c;
    background: #ddf;
}
</style>

<!--[if lte IE 6]>
<style type="text/css">
#inner2 {
    zoom: 1;/* Make this div take up the rest of the horizontal space, and no more, in IE 6 */
}

#inner1 {
    margin-right: -3px;/* Fix the 3-pixel gap that the previous rule introduces. (Shit like this is why web developers hate IE 6.) */
}
</style>
<![endif]-->

已在 IE6、7 和 8;Firefox 3.5 以及 Chrome 4 中测试并工作。


3
@Eric,我是那个给你的评论点了赞的人,但后来一个同事发给我这篇文章解释了一下。 - Michael
@Michael:啊,太好了,谢谢你。我从来没有真正理解为什么/如何overflow会对浮点数产生这种影响。前几天也有一个关于这个问题的Stack Overflow问题:请参见https://dev59.com/omox5IYBdhLWcg3weUCe - Paul D. Waite

3
如果您现在正在阅读这篇文章,您可能正在使用calc,所以要感激它。 HTML
<div class="universe">
  <div class="somewidth">
  </div>
  <div class="everythingelse">
  </div>
</div>

CSS

.universe {
  width: 100%;
  height: 100%;
}

.somewidth {
  width: 200px;
  height: 100%;
}

.everythingelse {
  width: 800px; /* fallback for emergencies */
  width: calc(100% - 200px);
  width: -moz-calc(100% - 200px);
  width: -webkit-calc(100% - 200px);
  height: 100%;
}

请查看 JSFiddle 上的示例


这真的非常酷。不过在写作时不支持IE7 :) - Artem

0
尝试这样做:将 inner1 嵌套在 inner2 中,并从 inner2 中删除 display:inline,像这样:
<div id="#outer" style="width:100%; border:1px solid red">
  <div id="#inner2" style="width:100%; border:1px solid black;">
     <div id="#inner1" style="border:1px solid blue; display:inline">
      inner div 1. Some text...
     </div>
  inner div 2...
  </div>
</div>

您可以在这里看到它的运行效果:http://jsbin.com/adiwi


是的,这对文本有效,但如果我需要 div 具有其余空间,因为我只需要绘制边框而不需要文本呢? - Artem

0

从您的代码来看,似乎您正在尝试获取一条水平线以填充div中的空白空间。如果我猜对了,您正在尝试使用标记创建视觉效果。如果我说错了,请纠正我。

(看到您想要的图像会很不错)

示例:

Title ---------------------------

or

Title: Caption ------------------

这不是最佳实践。你应该尝试使用CSS来实现这个效果。

首先尝试使你的代码更语义化:

<div id="#outer" style="width:100%; border:1px">
  <h3 style="border:1px; display:inline">
    Caption
  </h3>
</div>

获取线条的方法:
  1. 使用您想要的颜色创建一个图像
  2. 将其高度设置为您想要的线条高度(以像素为单位)
  3. 使用 background 属性来定位它

.

#outer h3 {
display: inline;
background-color: #000;
color: #FFF;
}

#outer {
width: 100%; /* is the default of block element but just for celerity */
background: #000 url('image path') center left; /* position the image */
}

0
你的第一个问题是在id前面加了'#'。#只用于CSS中引用具有该id的元素,例如CSS规则#outer{width:100%}引用了你的元素:
<div id="outer"></div>

此外,如果没有对块级元素进行浮动,您不需要在div(或任何其他块级元素)上使用宽度,因为它们已经自动占用了100%的可用宽度。

如果您想要两个DIV出现在同一行,则必须将第一个DIV向左浮动。相邻的DIV将出现在旁边,同样您不需要为第二个元素指定宽度。以下是完整的示例,包括每个div的不同颜色边框。

我已经将边框加大,以便您更清楚地看到发生了什么。

<html><body>
<style type="text/css">
#outer {
    border: solid 5px #c00;
}
#inner1 {
    border: solid 5px #0c0;
    float: left;
    width: 200px;
    height: 300px;
}
#inner2 {
    border: solid 5px #00c;
    height: 300px;
    margin-left: 210px; /* 200px left width + 2 x 5px borders */
}
</style>

<div id="outer">
  <div id="inner1">
    inner div 1. Some text...
  </div>
  <div id="inner2">
    inner div 2...
  </div>
</div>

</body></html>

失败。Inner1 应该从其内容中获取其大小。 - Dustman
那就不要指定宽度。 - mythz
这实际上是一个非常通用的答案,也更加兼容。overflow hidden 是对浏览器的一种hack。 - Manatax

0
另一个解决方案是运行一个 JavaScript,在文档加载时调整 captionLine 类的大小,就像这样。
花费一些时间来使其在 IE8 下工作,尚未尝试过 IE7,但应该可以正常工作。
需要注意的两件事情:
  1. IE 不支持 getElementsByClassName,因此该函数被重写。
  2. 当使用 style.marginLeft 调整对象的大小和位置时,IE 会以不同的方式处理边距,某种程度上 IE 似乎将 margin 保留在类声明中,并将其添加到新的 style.margin 中。
<body onload="resizeCaptionLine()">
<style>
caption {
 border: 1px solid blue;
 padding: 0px;
}
.captionText {
 border: 1px solid red;
 float: left;
}
.captionLine {
 background-color:black;
 margin: 0px;
 margin: 5px 0px 0px 5px;
 border: 0px;
 padding: 0px;
 padding-top: 1px;
}
</style>

<table style="width:300px;">
<caption width="100%" name="caption1">
     <div class="captionText">Some text</div>
     <div class="captionLine"> </div>
</caption>
     <tr>
           <td>something</td>
     </tr>
</table>
<table style="width:300px;">
<caption width="100%" name="caption2">
     <div class="captionText">Some text</div>
     <div class="captionLine"> </div>
</caption>
     <tr>
           <td>something</td>
     </tr>
</table>

<script type="text/javascript">

function getElementsByClassName(node, class_name) {
  elems = node.all || node.getElementsByTagName('*');
  var arr = new Array();
  for(j = 0; j < elems.length; j++)
  {
    if (elems[j].className == class_name)
       arr[arr.length] = elems[j];
  }
  return arr;
}

function resizeCaptionLine()
{
 var elems = getElementsByClassName(document, 'captionLine');
 for(i = 0; i < elems.length ; i++)
 {
   var parent = elems[i].parentNode;
   var sibling = getElementsByClassName(parent, 'captionText');
   var width = parent.offsetWidth - sibling[0].offsetWidth;

    if(elems[i].currentStyle)
   {
     var currentMargin = elems[i].currentStyle.marginLeft;
     var margin = parseInt(currentMargin.substr(0,currentMargin.length-2));
     elems[i].style.marginLeft = (sibling[0].offsetWidth) + "px";
   }
   else if (document.defaultView && document.defaultView.getComputedStyle)
   {
     var currentStyle = document.defaultView.getComputedStyle(elems[i], '');
     var currentMargin = currentStyle.marginLeft;
     var margin = parseInt(currentMargin.substr(0,currentMargin.length-2));
     elems[i].style.marginLeft = (sibling[0].offsetWidth + margin) + "px";
   }
   else
   {
     var currentMargin = elems[i].style.marginLeft;
     var margin = parseInt(currentMargin.substr(0,currentMargin.length-2));
     elems[i].style.marginLeft = (sibling[0].offsetWidth) + "px";
   }
   elems[i].style.width = (width - margin)+"px";
 } 
}
</script>
</body>

0

你需要将inner1 div向左浮动,像这样:

<div id="#outer" ....>
    <div id='#inner1" style="float:left; border: 1px solid #000;">
        blabla
    </div>
    <div id="#inner2" style="... DON'T USE WIDTH AND DISPLAY HERE! ...">
        gnihihi
    </div>
</div>

这应该能解决问题。看一下!再见


在这种情况下,第二个 div 重叠在第一个 div 上,并获得了100%的宽度。 - Artem

0

您不需要使用 div 嵌套元素,只需像这样使用 SPAN

 <div>
     <span style="display:inline-block;width: auto;border: solid 1px black;">
            hey you
     </span>
     <span style="display:inline-block;marging: 0px 2px;border: solid 1px black;">
           always use proper tools.
     </span>
 </div>

似乎IE7不支持inline-block:http://www.quirksmode.org/css/display.html - Artem
@Artem - 不,IE5.5是该图表上唯一不支持它的IE版本。 - Quentin
仅做记录,在IE 7及更早版本中,display:inline-block;仅支持默认为display:inline;的元素 - 例如,它在<span><a>支持,但不支持在<div><li>上。 - Paul D. Waite

0

在 @Nasser Hajloo 的回答基础上进行扩展,这对我有效(即使在 IE6 中也是如此)

 <div style="width: 400px; border: solid 1px red;"> 
     <span style="float:left;width: auto;border: solid 1px black;"> 
            hey you 
     </span> 
     <div style="display:inline-block;margin: 0px 2px;border: solid 1px black;">always use proper tools.</div> 
 </div> 

尝试将主要的div大小设置为小于400像素,以查看它如何调整。(它也适用于div而不是span-关键在于第一个div/span中的width: auto。)


如果您在示例中将宽度设置为1400,您会发现为什么它不起作用:在FF3.6中,右侧部分无法获得其余的空间。抱歉。 - Artem
只有在工作时用IE6(别笑!)。回到家后会看一下。 - Traingamer

0

答案非常简单!如果您在左侧有一个固定的 div(菜单),那么给固定的 div 设置 float: left,并将您的右侧的可变 div 设置为比第一个固定 div 的宽度更大的 margin-left


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接