为窄浏览器精确格式化演员表 windows

Precisely formatting a cast list for narrow browser windows

我需要在网页上设置一个“演员表”(一系列 person/role 对)的格式,以便在一行文本比可用文本宽时接近专业外观的结果 space 在浏览器中 window。但我不确定我是否应该查看 CSS flexbox、grid、JavaScript 或其他东西,或者这些是否能够生成任何接近我想要的东西。

以下是同一个演员表的一些示例,为不同的宽度手动设置了格式。 (我在这里使用固定宽度的字体,以便更容易显示对齐方式,但更喜欢使用可变宽度字体的方法。)

Wolfgang Amadeus Mozart ................. Court Composer
Antonio Salieri ........ Assistant to the Court Composer
Tim ... Assistant to the Assistant to the Court Composer
John Jacob Jingleheimer Schmidt ................. Intern
John Jacob Jingleheimer Schmidt Jr. ....... Secretary to
                     the Assistant to the Court Composer

Wolfgang Amadeus Mozart ..... Court Composer
Antonio Salieri ..... Assistant to the Court
                                    Composer
Tim ...... Assistant to the Assistant to the
                              Court Composer
John Jacob Jingleheimer Schmidt ..... Intern
John Jacob Jingleheimer
   Schmidt Jr. ............ Secretary to the
             Assistant to the Court Composer

Wolfgang Amadeus Mozart ... Court       ; not ideal, better to break the longer name
                         Composer
Antonio Salieri ....... Assistant
            to the Court Composer
Tim ............ Assistant to the 
  Assistant to the Court Composer
John Jacob Jingleheimer
   Schmidt ............... Intern
John Jacob Jingleheimer
   Schmidt Jr. ..... Secretary to
             the Assistant to the 
                   Court Composer

Wolfgang Amadeus
   Mozart .... Court Composer
Antonio Salieri ... Assistant
        to the Court Composer
Tim ........ Assistant to the
       Assistant to the Court
                     Composer
John Jacob Jingleheimer
   Schmidt ........... Intern
John Jacob Jingleheimer
   Schmidt Jr. .... Secretary
      to the Assistant to the
               Court Composer

表达此布局方案背后的逻辑的一种方式可能是:

  1. 对于每个 person/role 对,尝试将文本设置在一行中。如果它太宽了:
  2. 计算“person”部分最后一个单词和“role”部分第一个单词的宽度。
  3. 将“人”部分分成多行,使每行不超过可用宽度的70%,最后一行不超过“角色”部分第一个字的宽度(加上一个常数来说明缩进和点)。
  4. 将“角色”部分分成多行,使每行不超过可用宽度的70%,第一行不超过“人”部分最后一个字的宽度(加上一个常数)。
  5. 设置“人物”部分,后续行缩进。
  6. 在“人”部分的最后一行之后,设置“角色”部分的第一行,向右对齐,用点号填充多余的space。
  7. 设置“角色”部分的剩余行,右对齐。

仅使用 CSS 是否有可能获得上述结果?或者是可以在JavaScript中做这种事情,测量单词和手动定位换行符?有没有人做过类似的事情?任何指点表示赞赏。

虽然只需要 CSS 就可以做到这一点,但需要计算第二列第一行所需的缩进,这必须由 JavaScript 完成。

此代码段在每个包含文本的第一列 div 中有两个跨度。第一个跨度允许白色背景仅用于文本,第二个跨度允许计算实际文本的结尾。从那里可以找到第二列第一行所需的缩进。

由于点只是视觉线索,因此可以通过伪元素包含它们,重复径向渐变形成点。

function resize() {
  const cast = document.querySelector('.cast');
  const castX = cast.getBoundingClientRect().x;
  const leftCols = document.querySelectorAll('.cast > *:nth-child(odd)');
  leftCols.forEach(leftCol => {
    const lastEl = leftCol.querySelector('*:last-child');
    const x = lastEl.getBoundingClientRect().x + lastEl.getBoundingClientRect().width - castX;
    const rightCol = leftCol.nextElementSibling;
    const indent = x - (cast.getBoundingClientRect().width * 30 / 100);
    rightCol.style.setProperty('--indent', indent + 'px');
  });
}
window.onload = resize;
window.onresize = resize;
.cast {
  width: 50vw;
  position: relative;
  --lineheight: 1.1em;
  overflow: hidden;
}

.cast>* {
  max-width: 70%;
  margin: 0;
  padding: 0;
  line-height: var(--lineheight);
}

.cast> :nth-child(odd) {
  text-indent: -2em;
  padding-left: 2em;
  text-align: left;
}

.cast>*> :first-child {
  background: white;
}

.cast> :nth-child(odd) :first-child {
  position: relative;
}

.cast> :nth-child(odd) :first-child::after {
  width: 100vw;
  height: var(--lineheight);
  content: '';
  position: absolute;
  bottom: 0;
  z-index: -1;
  background-image: radial-gradient(gray 0 20%, transparent 20% 100%);
  background-repeat: repeat no-repeat;
  background-size: calc(var(--lineheight) / 2) calc(var(--lineheight) / 2);
  background-position: 0 bottom;
}

.cast> :nth-child(even) {
  --indent: 6em;
  text-align: right;
  position: relative;
  left: 30%;
  text-indent: var(--indent);
  margin-top: calc(-1 * var(--lineheight));
}
<div class="cast">
  <div><span>Wolfgang Amadeus Mozart</span><span></span></div>
  <div><span>Court Composer</span></div>
  <div><span>Antonio Salieri</span><span></span></div>
  <div><span>Assistant to the Court Composer</span></div>
  <div><span>Tim</span><span></span></div>
  <div><span>Assistant to the Assistant to the Court Composer</span></div>
  <div><span>John Jacob Jingleheimer Schmidt</span><span></span></div>
  <div><span>Intern</span></div>
  <div><span>John Jacob Jingleheimer Schmidt Jr.</span><span></span></div>
  <div><span>Secretary to the Assistant to the Court Composer</span></div>
</div>