Preserve normal word wrapping inside absolutely positioned container
Asked Answered
W

5

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)
Whoopee answered 11/2, 2013 at 19:40 Comment(0)
U
15

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>
Unify answered 11/2, 2013 at 19:48 Comment(0)
S
16

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.

Search answered 22/5, 2018 at 10:4 Comment(1)
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.Siobhan
U
15

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>
Unify answered 11/2, 2013 at 19:48 Comment(0)
C
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;
}
Churchwarden answered 11/2, 2013 at 19:49 Comment(7)
Interesting.. why does this work? What is the defined behavior for a position: relative element inside another position: relative element?Whoopee
setting position:absolute removes the element from the normal flow of the document structure, therefore it doesn't know how wide to be.Unify
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).Whoopee
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.Whoopee
To solve that you can wrap .text in an absolutely positioned element that has a width defined (this would be your preferred "max-width")Unify
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).Whoopee
edited to Rick's suggestion. Course if he posts an answer later i think he deserves the credit for it :)Churchwarden
A
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>
Apraxia answered 19/4, 2018 at 3:42 Comment(0)
E
1

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
Extensive answered 22/3, 2023 at 2:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.