Проблема с nowrap и max-width на абсолютно позиционированном элементе

Я предполагаю, что эти два атрибута фактически не работают вместе, но моя ситуация:

Я пытаюсь создать компонент всплывающей подсказки. Моя подсказка позиционируется абсолютно, и, поскольку я не знаю, какая длина содержимого будет, не имеет ширины. Таким образом, с помощью CSS, связанного с шириной, текст просто образует высокий, тощий столбец. Я пробовал max-width, но сам по себе ничего не делает. Поэтому я решил попробовать white-space: nowrap, и, хотя он красиво не обертывает текст, он также, по-видимому, не оценивает max-width полезным способом, а текст выходит из границ элемента.

Я не могу придумать, как решить мою проблему, если есть чистое решение. Я хотел бы иметь абсолютно позиционированный div, который расширяется, чтобы соответствовать его содержимому до максимума, после чего он обертывается. Одно из предложений, которое я видел, делало элемент a flexbox, но из того, что я могу сказать, это не очень хорошо с IE, поэтому я не думаю, что он жизнеспособен в моей ситуации. Любые советы?

.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

Избегайте использования white-space:nowrap, поскольку это ограничит ваш текст одной строкой. max-width должен работать с элементом уровня блока с абсолютным отображением, но не внутри встроенного элемента. Чтобы решить эту проблему, я помещаю всплывающую подсказку за пределы вашего блока-оболочки и использую javascript для размещения ее в месте расположения мыши.

Вот простое решение для вашей проблемы. Нажмите "открыть всплывающую подсказку", чтобы отобразить всплывающую подсказку, и переместите ползунок, чтобы изменить значение 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

Я не совсем уверен, какова ваша цель, так как происходит много противоречивых вещей. Но я постараюсь, надеюсь, вы можете направлять меня к вашему желаемому решению:

https://jsfiddle.net/q7dyf6xh/

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

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

Посмотрите на эту скрипку, поскольку вы можете видеть, что всплывающая подсказка теперь имеет максимальную ширину. Посмотрите, что я использую:

display: run-in;: отображает элемент как блок или встроенный, в зависимости от контекста

white-space: pre-line;: Последовательности пробелов рушится в одно пробелы. Текст будет обернут при необходимости, а при разрыве строки

Чтобы лучше понять, как выглядят работы:

белое пространство. Если вы используете nowrap, текст никогда не будет перенесен на следующую строку. Текст продолжается в одной строке до тех пор, пока не будет обнаружен тег!

Это говорит о том, что ваш max-width все еще работает, но теперь nowrap вы переполняете свой элемент. Попробуйте и дайте элементу background-color, и вы увидите, что он на самом деле такой же широкий, как и ваш max-width.

См. здесь, как он переполняет элемент: https://jsfiddle.net/fcnh1qeo/

И теперь ширина overflow: hidden будет отображаться только текст внутри вашего окна. Все остальное отрезано! См. Здесь: https://jsfiddle.net/0qn4wxkg/

То, что я использовал сейчас, это display: run-in; и white-space: pre-line;, а также max-width: 200px, что даст вам, надеюсь, ваше желаемое решение. Не зная, какой контекст и код вы используете, это скорее догадка, чем ответ. Но, может быть, я смогу направить вас к решению, которое соответствует вашим потребностям.

Ура!

Ответ 3

Добавьте min-width:100% и 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

Не так давно у меня была очень похожая проблема. Я исправил его с помощью flexbox того, что уже предложено в комментариях здесь.

Мой код выглядит следующим образом:

.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%)
}

Я также скопировал это в эту скрипту, если вы хотите взглянуть на нее. (

Ответ 5

Вы правы, что это не работает.

Вот решение, которое работает, если вам разрешено использовать теги BR. Я много раз работал над подсказками, и это лучшее решение, которое у меня есть.

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

Он работает, используя white-space nowrap с 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%); }

Перевод позволяет абсолютно позиционируемую подсказку горизонтально или вертикально центрировать себя и содержимое. Белое пространство с BR достигает обертывания для длинного содержимого, позволяя более короткие всплывающие подсказки соответствовать ширине текста всплывающей подсказки.

Здесь полный 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" Элемент генерирует окно ввода. Элементы запуска действуют как ряды или блоки, в зависимости от окружающих элементов. То есть: Если поле запуска содержит блок-блок, то же, что и блок. Если блок-блок следует за окном запуска, поле ввода становится первым встроенным полем блока. Если появляется встроенный блок, поле ввода становится блочным блоком.

pre-line Последовательности пробелов сбрасываются. Строки разбиты на символы новой строки, <br> и, если необходимо, для заполнения строк. Следующая таблица суммирует поведение различных значений white-space:

Свойство CSS max-width устанавливает максимальную ширину элемента. Это предотвращает, чтобы используемое значение свойства width становилось больше значения, указанного 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;

}