Search code examples
csswebkitword-break

Css for an element that allows break-word on child divs, but that can also expand to take the width of its children


I'm trying to determine whether it's possible to create css for an element that supports word-wrap:break-word, but that also expands to take the width of its children when breaking is not possible.

<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>

In the above sample, the url breaks properly, but the table and img overflow the red outer div if the window becomes narraower than the table.

If I make the outer div display:inline-block or display:table, the red outer div correctly expands to include the content, but the url doesn't break if the window is narrower than the url.

I only need this to work in WebKit (on Android), and I'm trying to find a CSS only (no Javascript) solution if possible.


Solution

  • Looking at the CSS spec, it's likely that what I'm trying to do is impossible, although I find the size calculations fairly difficult to decipher. Here are some important bits:

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

    The content width of a non-replaced inline element's boxes is that of the rendered content within them

    So if I want the background of my containing box to grow to be the width of the children, it appears I need to make sure it's layout is calulated in an inline formatting context:

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

    When an inline box exceeds the width of a line box, it is split into several boxes and these boxes are distributed across several line boxes. If an inline box cannot be split (e.g., if the inline box contains a single character, or language specific word breaking rules disallow a break within the inline box, or if the inline box is affected by a white-space value of nowrap or pre), then the inline box overflows the line box.

    Great. Hopefully the breaking rules also include emergency wrapping possibilities.

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

    This property specifies whether the UA may break within a word to prevent overflow when an otherwise-unbreakable string is too long to fit within the line box.

    Doesn't really help; let's look at the newer draft spec:

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

    Break opportunities not part of ‘overflow-wrap: normal’ line breaking are not considered when calculating ‘min-content’ intrinsic sizes.

    This isn't very clear, but if 'min-content' instrinsic sizes has something to do with the same calculations used to determine line-breaking possibilities, I might be out of luck.


    I ended up just using Javascript to measure the content and decide whether to show it in block or inline context. Sigh.

    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';
      }
    }