Trouble with nowrap and max-width on an absolutely positioned element

ⅰ亾dé卋堺 提交于 2020-01-14 07:11:14

问题


I'm guessing these two attributes don't actually work together, but my situation:

I'm trying to create a tooltip component. My tooltip is positioned absolutely, and as I don't know what the length of the content would be, has no width. So with width-related css, text just forms a tall, skinny column. I tried max-width, but on it's own, that does nothing. So I decided to try white-space: nowrap, and while it nicely doesn't wrap text, it also doesn't seem to honor max-width in a useful way, with text instead going out of the boundaries of the element.

I can't think of how to solve my problem, if there is a clean solution. I'd like to have an absolutely positioned div that expands to fit it's content until a maximum, at which point it wraps. One suggestion I saw was making the element a flexbox, but from what I can tell, that's not great with IE, so I don't think is viable in my situation. Any advice?

.wrapper {
  position: relative;
  display: inline;
}

.info {
  position: absolute;
  bottom: 1.2em;
  left: 0;
}
<div class="wrapper">
  <span>[ ? ]</span>
  <div class="info">Any long text can go in here to test what goes wrong with wrapping.</div>
</div>

回答1:


Avoid using white-space:nowrap as that will constrain your text to one line. max-width should work with a block level element with display absolute but not inside an inline element. To resolve this, I place the tooltip outside of your wrapper block and use javascript to position it at the mouse location.

Here is a simple solution for your issue. Click on "open tooltip" to display the tooltip and move the slider to change the value of max-width.

showContext = function() {
    var e = window.event;

    var posX = e.clientX;
    var posY = e.clientY;
    var info = document.getElementById("info");
    info.style.top = posY + "px";
    info.style.left = posX + "px";
    info.style.display = "block";
}

changeWidth = function(value) {
		var info = document.getElementById("info");
    info.style.maxWidth = value + "px";
}
.wrapper {
    position: relative;
}

.info {
    position: absolute;
    max-width:300px;
    display:none;
    border:1px solid black;
    background-color:white;
}

.range {
  margin:10px 0px 10px 0px;
  display:block;
}
<div class="wrapper">
    max-width slider
    <input id="range" class="range" type="range" min="100" max="600" oninput="changeWidth(this.value)"/>
    <input type="button" value="open tooltip" onclick="javascript:showContext();" />
</div>
<div id="info" class="info">Any long text can go in here to test what goes wrong with wrapping.</div>



回答2:


I'm not exactly sure what your goal is as there are a lot of contradictory things going on. But I'll try and hopefully you can guide me towards your desired solution:

https://jsfiddle.net/q7dyf6xh/

.wrapper {
    position: relative;
    display: run-in;
}

.info {
    position: absolute;
    max-width: 200px;
    white-space: pre-line;
}

Have a look at this fiddle, as you can see the tooltip now has a max-width. Have a look at what I'm using:

display: run-in;: Displays an element as either block or inline, depending on context

white-space: pre-line;: Sequences of whitespace will collapse into a single whitespace. Text will wrap when necessary, and on line breaks

For a better understanding of how things work look here:

white-space: If you use nowrap text will never wrap to the next line. The text continues on the same line until a tag is encountered!

This said your max-width is still working but with nowrap you overflow your element now. Try and give your element a background-color and you'll see that it actually is only as wide as your max-width defines.

See here how it overflows the element: https://jsfiddle.net/fcnh1qeo/

And now width overflow: hidden only the text inside your box will be displayed. Everything else is cut off! See here: https://jsfiddle.net/0qn4wxkg/

What I used now is display: run-in; and white-space: pre-line; as well as max-width: 200px which will give you hopefully your desired solution. Not knowing the context and code you using it is more of a guess than it is a answer. But maybe I can guide you towards a solution which fits your needs

Cheers!




回答3:


Add a min-width:100% and a white-space: nowrap;

.wrapper {
  position: relative;
  display: inline;
}
 
.info {
  position: absolute;
  min-width: 100%;
  white-space: nowrap;
}
<div class="wrapper">
    <span>[ ? ]</span>
    <div class="info">Any long text can go in here to test what goes wrong with wrapping.</div>
</div>



回答4:


Not that ling ago i had a very similar problem myself. I fixed it using flexbox what is already suggested in the comments here.

My code looks like this:

.has-tooltip {
  display: inline-flex; align-items: flex-start
}

.has-tooltip > .tooltip {
  padding: 1em;
  max-width: 300px;
  background: #bdc3c7;
  word-wrap: break-word;
  transform: translate(-50%,-110%)
}

I also copied this into this fiddle just in case you want to have a look at it. (:




回答5:


You are correct that this does not work.

Here's a solution that works if you are allowed to use BR tags. I have worked on tooltips many times and this is the best solution that I have.

Codepen: https://codepen.io/btn-ninja/pen/JNJrgp

It works by using white-space nowrap with a css translate:

<button type="button" class="btn btn-block hasTooltip">
  Tooltip on top
  <i class="tip">Most tooltips are short<br>but you can add line breaks.</i>
</button>

<button type="button" class="btn btn-block hasTooltip right">
  Tooltip on the right.
  <i class="tip">Tooltip on right<br>vertically centered.</i>
</button>     

.hasTooltip .tip {
    position: absolute;
    bottom: 100%; left: 50%; 
    transform: translateX(-50%); }

.hasTooltip.right .tip {
    bottom: auto; left: 100%; top:50%; 
    transform: translateY(-50%); }

The translate allows the absolutely-positioned tooltip to horizontally or vertically center itself vs the content. White space with a BR achieves wrapping for long content while allowing shorter tooltips to match width of the tooltip text.

Here's the full css:

.hasTooltip { 
  position:relative; }

.hasTooltip .tip {
  display:block;
  background: #333; color: #fff;
  box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.5);
  font-size:inherit; 
  font-style:normal;
  line-height: 1rem;
  text-align:center;
  padding: 8px 16px;
  border-radius:4px;
  margin-bottom:5px;
  pointer-events: none;
  position: absolute;
  bottom: 100%; left: 50%; transform: translateX(-50%);
  opacity: 0;
  transition: opacity .34s ease-in-out;
  white-space:nowrap;  
  z-index:99; }

.hasTooltip .tip:before {
  content: "";
  display:block; position:absolute; left:0; bottom:-5px; 
  width:100%; height:5px; }

.hasTooltip .tip:after {
  border-left: solid transparent 6px;
  border-right: solid transparent 6px;
  border-top: solid #333 6px;
  bottom: -4px;
  content: "";
  height: 0;
  left: 50%;
  margin-left: -6px;
  position: absolute;
  width: 0; }

.hasTooltip:focus .tip,
.hasTooltip:hover .tip {
  opacity: 1;
  pointer-events: auto; }

.hasTooltip.right .tip {
  bottom: auto; left: 100%; top:50%; transform: translateY(-50%);
  margin-bottom:0; 
  margin-left:5px; }

.hasTooltip.right .tip:before {
  left:-5px; bottom:auto; }

.hasTooltip.right .tip:after {
  border-left: 0;
  border-top: solid transparent 6px;
  border-bottom: solid transparent 6px;
  border-right: solid #333 6px;
  bottom:auto; 
  left: -4px;
  top:50%;
  margin-left: 0; 
  margin-top: -6px; }



回答6:


display="runin"The element generates a run-in box. Run-in elements act like inlines or blocks, depending on the surrounding elements. That is: If the run-in box contains a block box, same as block. If a block box follows the run-in box, the run-in box becomes the first inline box of the block box. If an inline box follows, the run-in box becomes a block box.

pre-line Sequences of whitespace are collapsed. Lines are broken at newline characters, at <br>, and as necessary to fill line boxes. The following table summarizes the behavior of the various white-space values:

The max-width CSS property sets the maximum width of an element. It prevents the used value of the width property from becoming larger than the value specified by max-width.

.wrapper {
  position: relative;
  display: run-in;
  top: 100px;
 }


.info {
 position: absolute;
 bottom: 1.2em;
 left: 0;
 max-width: 200px;
 white-space: pre-line;
 background-color: #ddd;

}



来源:https://stackoverflow.com/questions/45949322/trouble-with-nowrap-and-max-width-on-an-absolutely-positioned-element

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!