27

I have an absolutely positioned block of text inside a relatively positioned container. The absolutely positioned element exceeds the right boundary of its container.

The problem is: the text isn't wrapping as normal; it's breaking prematurely rather than expanding to its defined max-width:

Observed behavior:

enter image description here

Desired behavior

enter image description here

HTML/CSS (JSFIDDLE: http://jsfiddle.net/WmcjM/):

<style>
.container {
    position: relative;
    width: 300px;
    background: #ccc;
    height: 100px;
}

.text {
    position: absolute;
    max-width: 150px;
    left: 290px;
    top: 10px;
    background: lightblue;
}
</style>

<div class="container">
    <div class="text">Lorem ipsum dolor sit amet</div>
</div>

Note: A couple changes that appear to achieve the desired behavior, but which aren't quite what I'm looking for, include:

  • defining min-width: 150px on .text (the text might just be one word, and I don't want the container to be oversized)
  • positioning .text. relative to document, rather than to .container (it needs to appear beside the container, even when the browser is resized)
Emmett
  • 14,035
  • 12
  • 56
  • 81

5 Answers5

14

Try using position: relative; on .text

EDIT: Also put it inside an absolute positioned wrapper with your custom max-width

CSS

.container {
    position: relative;
    width: 300px;
    background: #ccc;
    height: 300px;
}

.wrap_text {
    position: absolute;
    max-width: 200px;
    top: 10px;
}

.text {
    position: relative;
    left: 290px;
    background: lightblue;
}

And HTML:

<div class="container">
    <div class="wrap_text">
        <div class="text">
            Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
        </div>
    </div>
</div>
Bogdan Rybak
  • 2,107
  • 1
  • 19
  • 22
14

Try to use one of these approaches:

Approach 1: transform: translate(x, y); instead of position: absolute; left: x; top: y;

Approach 2: width: max-content; For details read this answer.

Eduard Kolosovskyi
  • 1,396
  • 12
  • 18
  • This works perfectly when you have a span that you need to center the text and then place the span above some other element, but I have used translate ena position absolue. –  Jan 29 '20 at 22:39
6

change the absolute position to relative, and wrap .text in an absolutely positioned element.

http://jsfiddle.net/WmcjM/4/

.container {
    position: relative;
    width: 300px;
    background: #ccc;
    height: 300px;
}

.text {
    position: relative;
    /*min-width: 200px;*/
    left: 290px;
    background: lightblue;
}

.wrap {
    position: absolute;
    max-width: 200px;
    top: 10px;
}
  • Interesting.. why does this work? What is the defined behavior for a `position: relative` element inside another `position: relative` element? – Emmett Feb 11 '13 at 19:53
  • setting position:absolute removes the element from the normal flow of the document structure, therefore it doesn't know how wide to be. – Bogdan Rybak Feb 11 '13 at 19:56
  • 1
    Right, but it does seem to "know how wide to be" if `.text` has `left: 0` instead of `left: 290px` (i.e. when the text box doesn't exceed the container's boundary). – Emmett Feb 11 '13 at 20:00
  • Also, this solution only appears to work since there's nothing else in the container, and the text box's default position is 0,0. If I add other elements to the the container, then the text box is shifted from where I'd like it to appear. – Emmett Feb 11 '13 at 20:01
  • To solve that you can wrap .text in an absolutely positioned element that has a width defined (this would be your preferred "max-width") – Bogdan Rybak Feb 11 '13 at 20:07
  • Ah, I think using another container works! If you post that as an answer, I'll mark it as accepted (assuming nothing cleverer comes along). – Emmett Feb 11 '13 at 20:15
  • edited to Rick's suggestion. Course if he posts an answer later i think he deserves the credit for it :) –  Feb 11 '13 at 20:28
1

Here is a strategy that you can use that should work in Chrome, FF, Safari, and IE11 when I tested it last.

Basically, the idea is to trick the browser to think that you have the width. The previous answers work fine, but if you shrink the parent container's width, you will notice that your content starts to wrap when it hits the width of that parent container. So the idea to get around this is to use another container that is positioned where you want to anchor your content to, and then position your content with respect to that thing.

The difference here is we will use that first positioned container to set our desired max width. Since that container has 0 height, you won't even see it.

JSFiddle: http://jsfiddle.net/WmcjM/252/

HTML

<div class="container">
  <div class="sizing-container">
      <div class="your-text">You can put whatever you want here and you can see that the content wraps when you hit your max-width, but that max-width is actually defined as the width of the sizing container</div>
  </div>
</div>

CSS

.container {
    position: relative;
    background: #ccc;
    width: 70px;
    height: 70px;
    margin-bottom: 100px;
}

.your-text {
    position: absolute;
    left: 0;
    top: 100%;
    background: lightblue;
    word-break: break-word;
}

.sizing-container {
    position: absolute;
    display: block;
    height: 0px;
    background: red;
    width: 200px; // This is your max-width!
    top: 16px;
    left: 100%;
}

.container {
    position: relative;
    background: #ccc;
    width: 70px;
    height: 70px;
    margin-bottom: 100px;
}

.monkaS {
    position: absolute;
    left: 0;
    top: 100%;
    background: lightblue;
    word-break: break-word;
}

.poggers {
    position: absolute;
    display: block;
/*     height: 1px; comment this in to see whats happening*/ 
    height: 0px;
    background: red;
    width: 200px;
    top: 16px;
    left: 100%;
}
<div class="container">
  <div class="poggers">
      <div class="monkaS">Standard shit pogchamp chatlethal</div>
  </div>
</div>

<div class="container">
  <div class="poggers">
      <div class="monkaS">P O G G E R S P O G G E R S P O G G E R S P O G G E R S P O G G E R S P O G G E R S P O G G E R S P O G G E R S P O G G E R S P O G G E R S P O G G E R S</div>
  </div>
</div>

<div class="container">
  <div class="poggers">
      <div class="monkaS">Short</div>
  </div>
</div>

<div class="container">
  <div class="poggers">
      <div class="monkaS">ReallyLongReallyLongReallyLongReallyLongReallyLongReallyLongReallyLongReallyLongReallyLongReallyLongReallyLong</div>
  </div>
</div>
puopg
  • 563
  • 7
  • 17
0

Using max-width in conjunction with width: max-content alongside white-space: pre-wrap gave me the desired result without needing to use relative positioning or wrapping my text.

Set them as follows:

width: max-content;
max-width: 30ch;
white-space: pre-wrap
Atomixx
  • 210
  • 1
  • 10