一个允许子div换行的元素的CSS,但同时可以根据其子元素的宽度进行扩展。

10

我试图确定是否可能创建一个元素的CSS,该元素支持word-wrap:break-word,但在不可能进行换行时也会扩展以占用其子元素的宽度。

<html>
  <style>
  .outer {
    background-color:red;
    word-wrap:break-word;
  }
  </style>
  <div class="outer">
    User generated content:
    <a href="http://www.google.com">http://anannoyinglylongurlthatcausesthepagetogrowtolongunlessIusewordwrapbreakwordasdfasfasdfasdfasdfasdfasdfsadfasdfadsf</a>
    <table>
      <tr>
        <td>asdfasdfadsffdsasdfasdfsadfafsd</td>
        <td>asdfasdfadsffdaasdfassdffaafasds</td>
      </tr>
    </table>
    <img src="http://www.google.com/intl/en_com/images/srpr/logo3w.png"/>
  </div>
</html>
在上面的示例中,URL 可以正确地换行,但如果窗口变窄,则表格和图像会溢出红色外部 div。
如果我将外部 div 设置为 display:inline-block 或 display:table,则红色外部 div 会正确扩展以包含内容,但是如果窗口比 URL 更窄,则 URL 不会换行。
我只需要在 WebKit(Android 上)中使其工作,并且如果可能,我正在尝试找到仅使用 CSS(无 JavaScript)的解决方案。

我正在寻找一个仅使用CSS的解决方案,或者证明这样的解决方案是不可能的。 - nas
不确定这是否符合您的要求,但实际上您可以通过 CSS 属性 word-break 来确保换行。请查看此 JSFiddle - skyline3000
给出你想要的图片。 - c69
5个回答

8
如果我正确理解您的需求,您只需要在.outer上设置 overflow:auto 。以下是一个示例:http://jsfiddle.net/hgLbh/1/(已在Safari和Chrome上测试)。
更新:
根据您的滚动相关评论,我尝试了其他几种解决方案,并找到了一些满意的东西。提前说一声,这很脏,但如果您可以处理绝对定位的内容并且愿意复制生成的标记,则希望它能正常工作(至少在我的本地Safari上)。
解决方案是复制您的内容并将新内容包装在其他2个div中,因此HTML看起来像这样:
<div class="outer-fixed">
    <div class="just-a-helper-wrapper">
        ... user generated content
    </div>
</div>
<div class="outer">
    ... same user generated content
</div>

对于CSS:

.outer,
.outer-fixed {
    background-color:red;
    word-wrap:break-word;
    position: absolute;
    left: 0;
    right: 0;
}

.outer-fixed {
    position: fixed;
    right: 0;
}
.outer-fixed * {
    visibility: hidden;
}

我想指出,just-a-helper-wrapper 只是必需的,因为outer-fixed *不能选择文本节点(即不在其他标记中的内容)。例如,您示例中的字符串“用户生成的内容:”仍将可见。如果您实际上没有这种内容,则可以将其删除。
这是链接:http://jsfiddle.net/hgLbh/2/

谢谢您的建议。不幸的是,在移动webkit上滚动div无效。我可以使用像iScroll这样的js库来进行自己的滚动,但这并不是我想要的,因为我更喜欢整个页面滚动而不仅仅是div。 - nas
1
你的更新是一个很酷的想法。我一直在尝试想出一些用重复内容来实现这个功能的方法。虽然我不会使用它,但这个想法值得奖励。 - nas
我同意Alex的观点(我很高兴他认可了你的想法),你的解决方案显示出了独创性。当然,复制内容存在(搜索引擎)问题,但这是一个有趣的解决方案。 - ScottS

7

width: 100%;分配并使用table-layout: fixed;强制使td单元格适合表格,并允许文本换行。

  table {
        width:100%;
        table-layout:fixed
      }

这是代码片段:http://jsfiddle.net/hgLbh/ @AlexM display:inline-block; 无法限制表格的宽度。溢出的锚点导致背景扩展,使得未换行的表格在视觉上不可见。 - Rob W
我无法控制用户生成的内容,其中包括表格。我在上面添加了一个<img>标签作为另一个元素溢出父元素的示例。 - nas

3
我不知道移动 webkit 是否能用,但此方法在 Chrome 中可行。 这里 是对应代码的 jsfiddle 链接。
.outer {
    background-color:red;
    word-wrap:break-word;
    overflow:hidden;
  }

.outer table {
    width: 100%;
    table-layout:fixed
}

.outer * {
    max-width: 100%;
}

这个解决方案会缩小图片以及其他可能使 div 溢出的内容,这不是我想要的。感谢您的回复。 - nas
然后发布您打算布局的图片 - yunzen

2

我觉得draevor已经给出了答案,但我怀疑你不希望在

中间出现滚动条。如果是这样,并且根据你的限制,你可以尝试以下方法将
变成窗口:

CSS

html {height: 100%}
body {overflow: auto; height: 100%; margin: 0;}
.outer {
    word-wrap: break-word; 
    background-color: red;
    overflow: auto;
    min-height: 100%;
}

这个解决方案适用于你不介意外部div增长到窗口的高度,并且你没有使用移动Webkit。谢谢你的回复。 - nas

2
看了CSS规范,我认为我想做的事情可能是不可能的,虽然我发现尺寸计算相当难以理解。以下是一些重要的部分:

http://www.w3.org/TR/CSS21/visudet.html

一个非替换的内联元素框的内容宽度是其内部呈现内容的宽度。因此,如果我想让包含框的背景色扩展到子元素的宽度,似乎需要确保其布局是在内联格式化上下文中计算的:

http://www.w3.org/TR/CSS21/visuren.html#normal-flow

当一个内联框超过行框的宽度时,它会被分成几个框,并分布在几个行框中。如果无法分割内联框(例如,如果内联框只包含一个字符,或者语言特定的断词规则不允许在内联框内断词,或者内联框受 nowrap 或 pre 的空格值影响),则内联框将溢出行框。
很好。希望断词规则也包括紧急换行的可能性。

http://www.w3.org/TR/2010/WD-css3-text-20101005/#word-wrap

此属性指定 UA 是否可以在单词内部断开以防止溢出,当一段通常无法断开的字符串太长而无法适应行框时。

http://www.w3.org/TR/css3-text/#overflow-wrap

不属于“overflow-wrap: normal”的行断点不会在计算“min-content”内在尺寸时考虑。这并不是很清楚,但如果“min-content”内在尺寸与确定断行可能性使用的相同计算有关,那么我可能就没有什么运气了。
我最终只使用 JavaScript 来测量内容并决定是否以块级或内联上下文显示。唉。
var messages = document.body.getElementsByClassName('mail_uncollapsed');

// Show overflowing content by setting element display to inline-block. This
// prevents break-word from being applied to the element, so we only do this
// if the element would overflow anyway.
for (var i = 0; i < messages.length; ++i) {
  var message = messages[i];
  message.style.display = 'block';
  var isOverflowing = message.clientWidth < message.scrollWidth;
  if (isOverflowing) {
    message.style.display = 'inline-block';
  }
}

1
当然,JavaScript的解决方案很简单,但你在帖子中说这是不可接受的。无论如何,我已经更新了我的答案,并提供了一个工作示例(尽管有些hackish),而且没有使用JavaScript。 - deviousdodo
如果有人在想,word-wrap 最近被重命名为 overflow-wrap,因此 2010 年的草案和最新的草案之间存在差异。两个属性名称都是别名,并共享相同的值和渲染规则。 - BoltClock

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