1

I have a situation beyond my immediate control (library-related) where text in an HTML div goes beyond its enclosing bounding box. I give a simple example below, although in my case it is a div within a <foreignObject> inside a <g> within an <svg>...

In the example below, is there a way to programmatically detect if the text goes beyond its bounding box? Getting the size of the enclosed <div> and its associated parent seems to return the same width, which is NOT the width of the text.

<!doctype html>
<html lang="">

<head>
  <style>
    .container {
      background: yellow;
      border: 2px solid black;
      width: 200px;
      height: 100px;
    }

    .tooBig {
      white-space: nowrap;
    }
  </style>

  <script>
    function figureOutSizes() {
      let container = document.getElementById("my-container");
      let contBound = container.getBoundingClientRect();
      console.log(`Container size: ${boundToString(contBound)}` );

      let tooBig = document.getElementById("tooBig");
      let bigBound = tooBig.getBoundingClientRect();
      console.log(`text size: ${boundToString(bigBound)}` );
    }

    function boundToString(rect) {
      return `rect(w=${rect.width}, h=${rect.height})`;
    }
  </script>

  <meta charset="utf-8">
  <title>Out of bounds</title>
</head>

<body>

  <div id="my-container" class="container" >
      <div id="tooBig" class="tooBig">This line is too big for its containing div! What am I going to do?</div>
  </div>

  <div>
    <button onclick="figureOutSizes();">Get sizes</button>
  </div>
</body>

</html>
black panda
  • 2,842
  • 1
  • 20
  • 28

2 Answers2

1

You can use scrollWidth and scrollHeight instead of getBoundingClientRect:

function figureOutSizes() {
  let container = document.getElementById("my-container");
  let contBound = container.getBoundingClientRect();
  console.log(`Container size: ${boundToString(contBound)}`);

  let tooBig = document.getElementById("tooBig");
  let bigBound = {
    width: tooBig.scrollWidth,
    height: tooBig.scrollHeight
  };

  console.log(`text size: ${boundToString(bigBound)}`);
}

function boundToString(rect) {
  return `rect(w=${rect.width}, h=${rect.height})`;
}
.container {
  background: yellow;
  border: 2px solid black;
  width: 200px;
  height: 100px;
}

.tooBig {
  white-space: nowrap;
}
<div id="my-container" class="container">
  <div id="tooBig" class="tooBig">This line is too big for its containing div! What am I going to do?</div>
</div>

<div>
  <button onclick="figureOutSizes();">Get sizes</button>
</div>
Kosh
  • 16,966
  • 2
  • 19
  • 34
1

Getting only text width

If you only want to detect if a string goes out of its parent element, the best way is to do it with the jQuery element.width() method where you put the string inside a span, because the div element automatically gets a 100% width by default.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<span id='tooBig' style='white-space: nowrap;'>This string is too long ...</span>
<script>
  var x = $('#tooBig').width();
  console.log("Text width: "+x);
</script>

Now, you can compare it to the container's width and check if the string is wider than its parent.

If you want to avoid wrapping, add the white-space: nowrap; CSS style for the parent span or use &nbsp; character encoding instead of spaces.

Wrap string automatically with CSS

I suppose your purpose is not only to detect if the text flows out of a div, rather to wrap the string, so there is a quite elegant CSS method for this. The technique uses flexbox, test-overflow: ellipsis and overflow: hidden and the behaviour of string overflow. You do not need to use any kind of JavaScript for it, the text wraps and get the ... ending automatically.

/* Text is a header now,
  so need to truncate there for it to work */
.flex-child > h2 {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Text is directly within flex child,
   so doing the wrapping here */
.flex-child {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
<div class="flex-parent">
  <div class="flex-child">
    <h2>Resize the window to see how this very very long text gets resized...</h2>
  </div>
</div>

Reference

CSS Flexbox Resize
jQuery text width

squancy
  • 565
  • 1
  • 7
  • 25