css 如何将元素绝对定位在标题的第一行之后

owfi6suc  于 2022-11-26  发布在  其他
关注(0)|答案(2)|浏览(126)

我试着把一个HTML元素放在一个标题的第一行的末尾。为了更好的理解,我截图了它现在的样子和它应该是什么样子。
外观:

它应该是什么样子:

如您所见,我使用::first-line伪选择器将标题第一行的背景更改为红色。
到目前为止,我已经尝试将::after添加到::first-line中,但有两个问题。首先,我没有设法在::after中显示文本内容。其次,您不能将html内容同时添加到::before::after中,因此这是毫无意义的。
您应该知道,“sunshines”不是一个图像,而是一个实际的html元素:
第一个
这是带有scss模块的JSX,但基本上语法与HTML/CSS相同。
你有什么想法如何做到这一点,我想这是可能的,因为css是有能力知道在哪里结束的线,因为我可以改变背景。

rhfm7lfc

rhfm7lfc1#

如果可以将heading,html中的两行分隔开,您可以这样做:

<header>
        <div>
            <div class="first-line">
                <p>
                    sample title, pretty long

                <div className={css.container}>
                    <div className={css.shine1}></div>
                    <div className={css.shine2}></div>
                    <div className={css.shine3}></div>
                </div>
                </p>
            </div>
            <p>
                that is wrapping in two lines
            </p>
        </div>
    </header>

CSS:

header .first-line{
  position: relative;
  display: inline-block;
}
.container {
  position: absolute;
  display: inline;
  top: 20px;
  right: 5px;

  
}
.container div {
  position: absolute;
  height: 5px;
  border-radius: 5px;
  background-color: red;
  transform-origin: bottom left;
}
.shine1 {
  width: 26px;
  transform: rotate(-95deg) translate(20px, 5px);
}
.shine2 {
  width: 32px;
  transform: rotate(-45deg) translate(20px);
}
.shine3 {
  width: 26px;
  transform: rotate(0deg) translate(15px);
}
e4eetjau

e4eetjau2#

我已经想通了。
虽然我的解决方案非常“笨拙”,但它在我想到的任何测试用例中都能很好地工作。
我的解决方案是用相同的css属性在标题的第一行创建一个隐藏的副本,然后得到副本的宽度,用这个值定义sunshines的left属性。
下面是我用来获取第一行文本的函数:

const getFirstLine = el => {
  const text = el.innerHTML;

  //set the innerHTML to a character
  el.innerHTML = 'a';
  //get the offsetheight of the single character
  const singleLineHeight = el.offsetHeight;

  //split all innerHTML on spaces
  const arr = text.split(' ');

  //cur is the current value of the text we are testing to see if
  //it exceeds the singleLineHeight when set as innerHTML
  //prev is the previously tested string that did not exceed the singleLineHeight
  //cur and prev start as empty strings
  let cur = '';
  let prev = '';

  //loop through, up to array length
  for (let i = 0; i < arr.length; i++) {
    //examine the rest of text that is not already in previous string
    const restOfText = text.substring(prev.length, text.length);

    //the next space that is not at index 0
    const nextIndex =
      restOfText.indexOf(' ') === 0
        ? restOfText.substring(1, restOfText.length).indexOf(' ') + 1
        : restOfText.indexOf(' ');

    //the next part of the rest of the text
    cur += restOfText.substring(0, nextIndex);

    //set the innerHTML to the current text
    el.innerHTML = cur;

    //now we can check its offsetHeight
    if (el.offsetHeight > singleLineHeight) {
      //once offsetHeight of cur exceeds singleLineHeight
      //previous is the first line of text
      //set innerHTML = prev so
      el.innerHTML = prev;
      //we can grab the innertext
      const firstLine = el.innerText;
      const indexOfSecondLine = prev.lastIndexOf('<');

      //reset el
      el.innerHTML = text;

      return firstLine;
    }

    //offsetheight did not exceed singleLineHeight
    //so set previous = cur and loop again
    //prev = cur + ' ';
    prev += cur.substring(prev.length, cur.length);
  }
  el.innerHTML = text;
  return text;
};

如果你想做同样的小心等待字体的网页被加载或宽度你将得到将是错误的

document.fonts.ready.then(function () {})

我还设法处理了当标题具有text-align: center;属性时的情况,方法是将margin-left/right: auto;添加到副本,然后使用以下命令将副本添加到计算出的left中:

parseInt(window.getComputedStyle(invisibleTitle).marginLeft)

我知道它并不完美,但由于在css中没有简单的方法来做到这一点,这是我找到的唯一有效的方法。

相关问题