CSS-плавающие аннотации с собственным потоком

Update

Я принес щедрость, но правильный ответ так и не был достигнут. Я реализовал решение JS, которое работает для меня, но я пока не буду отмечать ответ как правильный. Если это возможно с помощью только CSS/HTML, я все равно буду любить его видеть. Но общий консенсус в том, что в настоящее время это невозможно.

Цель

CodePen здесь, снизу снизу внизу.

У меня есть некоторый HTML-контент, который я хотел бы аннотировать с небольшим сообщением, плавающим прямо над ним, с левой стороны, вроде аннотаций <ruby> (но не совсем). Могут быть много частей контента, каждый со своими аннотациями. Содержимое должно соответствовать нормальному потоку текста. Вот мой текущий HTML:

<div class='item' style='color: red'>
  <div class='annotation'>nope</div>
  <div class='content'>It a bird, </div>
</div>
<div class='item' style='color: green'>
  <div class='annotation'>still no</div>
  <div class='content'>it a plane, </div>
</div>
<div class='item' style='color: blue'>
  <div class='annotation'>yeah!</div>
  <div class='content'>it Superman! </div>
</div>
<div class='item' style='color: orange'>
  <div class='annotation'>muahaha</div>
  <div class='content'>Go get the Kryptonite</div>
</div>

Рабочий пример

Ниже предложение It a bird, it a plane, it Superman! Go get the Kryptonite имеет 4 отдельные части (4 части content), каждая из которых представлена ​​другим цветом. Каждый кусок контента имеет свой собственный annotation, выделенный курсивом над ним.

enter image description here

У меня это работает, создавая как контент, так и аннотацию float: left и давая аннотации отрицательный margin. Это пример 1 в CodePen.

Разбитый пример 1

Проблема возникает, когда аннотация больше, чем содержание. Ниже аннотация still no изменилась на более длинную you may be right. Две строки содержания продолжают следовать нормальному потоку (по желанию), но поскольку аннотации все еще выровнены до левого края их содержимого, они перекрываются.

enter image description here

Это пример 2 в CodePen.

Разбитый пример 2

Предлагаемое решение состояло в том, чтобы использовать таблицу с visibility:collapse для выравнивания, что хорошо работает при предотвращении перекрытия, но это приводит к лишнему пространству после аннотаций, в тех случаях, когда аннотация начинается за левым краем содержимого.

Broken ex 2

Как это должно работать

Я хочу, чтобы аннотации соответствовали их собственному потоку, но не нарушали естественный поток содержимого. Ниже показано, как строка содержимого остается единственным непрерывным предложением, но yeah! переходит вправо, чтобы позволить длинному you may be right иметь всю комнату, в которой он нуждается. Тем не менее, muahaha исправляет назад, потому что у него есть место для сидения прямо на вершине Go get the kryptonite.

enter image description here

Я могу изменить как CSS, так и HTML, чтобы это произошло, но решение только для CSS было бы оптимальным. Спасибо.

.item {
  margin-top: 20px;
}
.content, .annotation {
  float: left;
  white-space: pre;
}
.annotation {
  margin-top: -25px;
  font-style: italic;
}


h3 {
  clear: both;
  margin: 0;
  padding: 20px 0;
}

td:first-child {
  color: red;
}
td:nth-child(2) {
  color: green
}
td:nth-child(3) {
  color: blue;
}
td:nth-child(4) {
  color: orange;
}
<h3>Working Example</h3>
<div class='item' style='color: red'>
  <div class='annotation'>nope</div>
  <div class='content'>It a bird, </div>
</div>
<div class='item' style='color: green'>
  <div class='annotation'>still no</div>
  <div class='content'>it a plane, </div>
</div>
<div class='item' style='color: blue'>
  <div class='annotation'>yeah!</div>
  <div class='content'>it Superman! </div>
</div>
<div class='item' style='color: orange'>
  <div class='annotation'>muahaha</div>
  <div class='content'>Go get the Kryptonite</div>
</div>


<h3>Broken Example 1 (note the overlap)</h3>
<div class='item' style='color: red'>
  <div class='annotation'>nope</div>
  <div class='content'>It a bird, </div>
</div>
<div class='item' style='color: green'>
  <div class='annotation'>you may be right</div>
  <div class='content'>it a plane, </div>
</div>
<div class='item' style='color: blue'>
  <div class='annotation'>yeah!</div>
  <div class='content'>it Superman! </div>
</div>
<div class='item' style='color: orange'>
  <div class='annotation'>muahaha</div>
  <div class='content'>Go get the Kryptonite</div>
</div>

<h3>Broken Example 2 (note the overlap)</h3>
 <table>
  <tr style='font-style: italic'>
    <td>nope</td><td>you may be right</td><td>yeah!</td><td>muahaha</td>
  </tr>
  <tr style="visibility:collapse;"><td>It a bird, </td><td>it a plane, </td><td>it Superman! </td><td>Go get the kryptonite</td></tr>
</table>
<table style="margin-top:-25px;"><tr><td>It a bird, </td><td>it a plane, </td><td>it Superman!</td><td>Go get the kryptonite</td></tr></table>

<h3>How it should look (cheating with positioning)</h3>
<div class='item' style='color: red'>
  <div class='annotation'>nope</div>
  <div class='content'>It a bird, </div>
</div>
<div class='item' style='color: green'>
  <div class='annotation'>you may be right</div>
  <div class='content'>it a plane, </div>
</div>
<div class='item' style='color: blue'>
  <div class='annotation' style='margin-left: 35px'>yeah!</div>
  <div class='content'>it Superman! </div>
</div>
<div class='item' style='color: orange'>
  <div class='annotation'>muahaha</div>
  <div class='content'>Go get the Kryptonite</div>
</div>

Ответы

Ответ 1

Возможно, это вам подойдет:

<table>
  <tr>
    <td>nope</td>
    <td>you may be right</td>
    <td>yeah it is!</td>
  </tr>
  <tr style="visibility:collapse;">
    <td>It a bird,</td>
    <td>it a plane,</td>
    <td>it Superman!</td>
  </tr>
</table>
<table style="margin-top:-25px;">
  <tr>
    <td>It a bird,</td>
    <td>it a plane,</td>
    <td>it Superman!</td>
  </tr>
</table>

Ответ 2

http://codepen.io/anon/pen/OVWBLv

Я думаю, что получил его только с CSS:

.item {
  display: inline-block;
}
.content, .annotation {
  display: inline;
  white-space: pre;
}
.annotation {
  font-style: italic;
}

.annotation:after {
  content: "";
  display: inline-block;
  width: 100%;
}

Псевдоэлемент заставляет содержимое следующей строке аннотации, в то время как родительский .item блокирован inline, чтобы оставаться рядом друг с другом.

Ответ 3

Я не уверен, что это то, что вам нужно, но здесь изменен CodePen

HTML:

<!-- first group -->
<div class='item'>
  <div class='annotation'>I'm an annotation</div>
  <div class='content'>I am the actual content </div>
</div>
<div class='item'>
  <div class='annotation'>I'm a second annotation</div>
  <div class='content'>I am a second piece of content</div>
</div>

<!-- second group -->
<div class='item'>
  <div class='annotation'>I'm a particularly long annotation</div>
  <div class='content'>I am the actual content </div>
</div>
<div class='item'>
  <div class='annotation'>I'm a second annotation</div>
  <div class='content'>I am a second piece of content</div>
</div>   

CSS:

.item {
  font-size: 20px;
  margin-top: 30px;
  float: left;
}
.content, .annotation {
  white-space: pre;
}
.annotation {
  margin-top: -25px;
  font-style: italic;
}

Я в основном перемещал float: левое объявление из .content, .annotation элементов в .item.

Надеюсь, что это поможет.

Ответ 4

Я не совсем понимаю, что вам нужно, но если для каждого элемента/контента будет много аннотаций, тогда имеет смысл обернуть их в свой контейнер (например, называется notes).

Затем аннотации могут быть объявлены как inline без нарушения потока других элементов.

Как я уже сказал, без лучшего представления о том, что вы после, я думаю, что ниже самое близкое, что я могу прийти.

Демо-версия Codepen

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
.item {
  font-size: 20px;
  float: left;
  width: 50%;
  overflow: hidden;
  margin-bottom: 10px;
  border: 1px solid red;
}
.notes {
  overflow: hidden;
}
.annotation {
  font-style: italic;
  display: inline;
  margin-right: 1em;
}
<div class='item'>
  <div class="notes">
    <div class='annotation'>I'm an annotation</div>
    <div class='annotation'>I'm a second annotation</div>
  </div>
  <div class='content'>I am the first content</div>
</div>
<div class='item'>
  <div class="notes">
    <div class='annotation'>I'm an annotation</div>
    <div class='annotation'>I'm a second annotation</div>
  </div>
  <div class='content'>I am the second content</div>
</div>

<div class='item'>
  <div class="notes">
    <div class='annotation'>I'm an long long long long annotation</div>
    <div class='annotation'>I'm a second annotation</div>
  </div>
  <div class='content'>I am the third content</div>
</div>

<div class='item'>
  <div class="notes">
    <div class='annotation'>I'm an long long long long annotation</div>
    <div class='annotation'>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ut, aspernatur.</div>
  </div>
  <div class='content'>I am the fourth content</div>
</div>

Ответ 5

Как консенсус, похоже, говорит, что это невозможно в CSS только, у меня есть решение JS ниже, но у него есть некоторые неприятные случаи с упаковкой.

CodePen

В основном размещение аннотаций и содержимого на отдельных строках, inline-block

<div class='annotations'>
  <div class='annotation' style='color: red'>nope</div>
  <div class='annotation' style='color: green'>you might be right</div>
  <div class='annotation' style='color: blue'>hell yeah it is</div>
</div>
<div class='contents'>
  <div class='content'style='color: red'>It a bird, </div>
  <div class='content' style='color: green'>it a plane, </div>
  <div class='content' style='color: blue'>it Superman!</div>
</div>

.content, .annotation {
  white-space: pre;
  display: inline-block;
}
.annotation {
  font-style: italic;
}

И затем с помощью JS установить width каждой аннотации, большей из двух ширины (ее собственной или ее содержимого).

const items = _.zip(
  _.toArray(document.getElementsByClassName('annotation')),
  _.toArray(document.getElementsByClassName('content'))
)

_.forEach(items, ([annotation, content]) => {
  const max = Math.max(content.offsetWidth, annotation.offsetWidth)
  annotation.style.width = `${max}px`
})

Результаты в желаемом формате:

enter image description here

Ответ 6

Как насчет чего-то подобного? Кодепен здесь.

Изменить, 6/1: этот ответ является единственным, который приходит даже удаленно близко к решению вашей проблемы. Вы просто не хотите многострочных аннотаций? Сохранение аннотаций с выравниванием по левому краю и возможность их переноса на следующую строку улучшает четкость и читаемость для конечного пользователя. Понравилась бы какая-нибудь обратная связь!

.content {
      margin: 50px auto;
    }
    .has-annotation {
      position: relative;
      display: inline-block;
    }
    
    .annotation {
      position: absolute;
      bottom: 20px;
      font-style: italic;
    }
    
    #a { color: red; }
    #b { color: green; }
    #c { color: blue; }
    #d { color: orange; }
<div class="content">
      <div class="has-annotation" id="a">
        <span class="annotation">nope</span>
        It a bird, 
      </div>
      <div class="has-annotation" id="b">
        <span class="annotation">you may be right</span>
        it a plane, 
      </div>
      <div class="has-annotation" id="c">
        <span class="annotation">yeah!</span>
        it Superman! 
      </div>
      <div class="has-annotation" id="d">
        <span class="annotation">muahaha</span>
        Go get the Kryptonite
      </div>
    </div>

Ответ 7

Я изменил класс annotation с div на span и встроен в content div.

http://jsbin.com/qejemeredi/2/

 .item {
  margin-top: 20px;
}

.content {
  float: left;
margin-right:-25px;
}
.annotation {
  margin-top: -25px;
  font-style: italic;
   float: left;
  white-space: pre;

}



td:first-child {
  color: red;
}
td:nth-child(2) {
  color: green
}
td:nth-child(3) {
  color: blue;
}
td:nth-child(4) {
  color: orange;
}

HTML

<div class='item' style='color: red'>

  <div class='content'><span class='annotation'>nope</span> It a bird,     </div>
</div>

 <div class='item' style='color: green'>

  <div class='content'>
    <span class='annotation'>you may be rightsdfdsg</span>
    it a plane, </div>
</div>
<div class='item' style='color: blue'>

  <div class='content'><span class='annotation'>yeah!</span>it Superman! </div>
</div>
<div class='item' style='color: orange'>

  <div class='content'><span class='annotation'>muahaha</span>
    Go get the Kryptonite</div>
</div>

Ответ 8

Возможно, вы захотите выполнить следующие действия:

.item {
  float: left;
  width: calc(100% - 20px);
}
.annotation {
  font-style: italic;
}
.content,
.annotation {
  display: inline-flex;
  float: left;
  min-width: 60px;
  padding: 5px;
  text-align: left;
  white-space: nowrap;
}
h3 {
  clear: both;
  margin: 0;
  padding: 20px 0;
}
<h3>example1</h3>
<div class='item' style='color: red'>
  <div class='annotation'>nope</div>
  <div class='annotation'>you may be right</div>
  <div class='annotation'>yeah!</div>
  <div class='annotation'>muahaha</div>

</div>
<div class='item' style='color: green'>
  <div class='content'>It a bird,</div>
  <div class='content'>it a plane,</div>
  <div class='content'>it Superman!</div>
  <div class='content'>Go get the Kryptonite</div>
</div>
<h3>Example 2</h3>
<div class='item' style='color: red'>
  <div class='annotation'>nope</div>
  <div class='annotation'>Still no</div>
  <div class='annotation'>yeah!</div>
  <div class='annotation'>muahaha</div>

</div>
<div class='item' style='color: green'>
  <div class='content'>It a bird,</div>
  <div class='content'>it a plane,</div>
  <div class='content'>it Superman!</div>
  <div class='content'>Go get the Kryptonite</div>
</div>