无论如何我可以根据它包含的文本行数调整 LI 元素的高度? (更多行 = 更高的 LI)(否 jQuery)

Is there anyway I can adjust the height of an LI element based on the number of lines of texts it contains? (More lines = taller LI) (No jQuery)

大家好,我在做一个测试软件。现在,我正在制作一个显示答案选项的问题页面。

我将答案选项显示为 li 元素。有时,我问的一些问题有超长的答案选择,而且它会溢出 li 元素。我目前的解决方案是使 li 足够大以包含最大的答案选择,但现在对于 2 个单词、3 个单词的答案选择来说看起来很愚蠢。

所以现在,我希望 li 元素的高度基本上根据答案选项的文本行数而变化(而不是溢出,我希望它增长以通俗地说)。

这是相关的片段。

<ul>
  <li className={(this.state.submitted) && (answerkey[question]==='A' ) ? 'correct': (answers[question]==='a' ) && (answerkey[question] !=='A' ) && (this.state.submitted) ? 'wrong': ''}>
    <input type='radio' value='a' id='a-option' name='selector' checked={response==='a' } onChange={this.onChange} />
    <label for='a-option'>
        <div className='adjust-reading-text'>
          {answerchoices[question][0]}
        </div>
      </label>
    <div className='check'></div>
  </li>
  <li className={(this.state.submitted) && (answerkey[question]==='B' ) ? 'correct': (answers[question]==='b' ) && (answerkey[question] !=='B' ) && (this.state.submitted) ? 'wrong': ''}>
    <input type='radio' value='b' id='b-option' name='selector' checked={response==='b' } onChange={this.onChange} />
    <label for='b-option'>
      <div className='adjust-reading-text'>
        {answerchoices[question][1]}
      </div>
    </label>
    <div className='check'></div>
  </li>
  <li className={(this.state.submitted) && (answerkey[question]==='C' ) ? 'correct': (answers[question]==='c' ) && (answerkey[question] !=='C' ) && (this.state.submitted) ? 'wrong': ''}>
    <input type='radio' value='c' id='c-option' name='selector' checked={response==='c' } onChange={this.onChange} />
    <label for='c-option'>
      <div className='adjust-reading-text'>
        {answerchoices[question][2]}
      </div>
    </label>
    <div className='check'></div>
  </li>
  <li className={(this.state.submitted) && (answerkey[question]==='D' ) ? 'correct': (answers[question]==='d' ) && (answerkey[question] !=='D' ) && (this.state.submitted) ? 'wrong': ''}>
    <input type='radio' value='d' id='d-option' name='selector' checked={response==='d' } onChange={this.onChange} />
    <label for='d-option'>
      <div className='adjust-reading-text'>
        {answerchoices[question][3]}
      </div>
    </label>
    <div className='check'></div>
  </li>
</ul>

不要担心与问题无关的反应状态,只要知道 {answerchoices[question][3]} 加载答案选项的文本即可。

这是 css 需要更改的内容。

.container-reading ul{
  list-style: none;
  margin: 0;
  padding: 20px;
}

.container-reading ul li{
  color: black;
  position: relative;
  display: inline;
  width: 95%;
  font-size: 16px;
  border-bottom: 1px solid #333;
  padding-bottom: 5px;
}

这可以用纯 CSS 来解决。您已经有一套 width。假设该百分比解析为实际数字,文本将在达到该宽度时自动换行。但是,宽度不适用于行内元素。请改用 display: inline-block

.container-reading ul {
  list-style: none;
  margin: 0;
  padding: 20px;
}

.container-reading ul li {
  color: black;
  position: relative;
  display: inline-block; /* The change */
  width: 100px; /* Ensure this resolves to an actual value */
  font-size: 16px;
  border-bottom: 1px solid #333;
  padding-bottom: 5px;
}
<div class='container-reading'>
  <ul>
    <li>A really really really long piece of text that will cause the wrap to trigger
  </ul>
</div>

我想可能是一个隐藏元素充当了 克隆 因为在 JS 中很难确定元素中文本的长度,所以我们只放置 list items 元素中的文本,随着文本数量的增加而增长。这将使我们能够获得容器的宽度,并为我们提供文本占用的准确长度(以像素为单位)。我们将其与列表项的 clientWidth 进行比较,找出哪些元素溢出了。

我认为为 flexbox 元素设置样式可能更容易,所以我将文本包装在 span 标签中并将其放在单选输入之后。然后我们向选择器添加一些样式并将选择器添加到父元素。放置一个 align-items: center 垂直 居中输入和文本。

const answers = document.querySelectorAll('.container-reading li')

function contOverflown(element) {
  let clone = document.createElement('DIV')
  let output = false
  clone.textContent = element.textContent
  clone.style.visibility = 'hidden'
  clone.style.padding = 0;
  clone.style.border = 'none';
  clone.style.position = 'absolute'
  document.body.append(clone)  
  element.clientWidth < clone.clientWidth ?
    output = true :
    null
  return output;
}

function resetLayoutForOverFlown(elements) {
  elements.forEach(answer => {
    if (contOverflown(answer) !== false) {
      let span = document.createElement('SPAN')
      span.style.width = '90%'
      span.textContent = answer.textContent
      let npt = answer.children[0]
      answer.textContent = ''
      answer.append(npt, span)
      answer.style.display = 'flex'
      answer.classList.add('overflown')
    }
  })
}

resetLayoutForOverFlown(answers)
.container-reading ul {
  list-style: none;
  padding: 20px;
  margin: 0;
}

.container-reading ul li {
  color: black;
  position: relative;
  width: 95%;
  font-size: 16px;
  border-bottom: 1px solid #333;
  padding-bottom: 5px;
}

.container-reading ul li input {
  padding-right: 2rem;
}

.overflown {
  display: flex;
  justify-content: flex-start;
  align-items: center;  
}

.overflown span {  
  margin-left: .3em;
  flex-wrap: wrap;
  flex: 2;
  max-width: calc(100% - 2em);
}
<div class='container-reading'>
  <ul>
    <li class="answer-item">
      <input type="radio" name="check"> This answer is a far too long for our list items content. We will wrap its text in a span tag and flex the input and span for a more cohesive layout
    </li>
    <li class="answer-item"><input type="radio" name="check"> This answer is ok</li>
    <li class="answer-item"><input type="radio" name="check"> This answer is also ok</li>
    <li class="answer-item"><input type="radio" name="check"> This answer is ok</li>
    <li class="answer-item">
      <input type="radio" name="check"> Yet another answer that is a far too long for our list items content, so JS will determine its length and write a new layout and style for its content
    </li>
  </ul>
</div>