css 如何创建溢出文本内容的突出显示效果?

g52tjvyc  于 2023-08-09  发布在  其他
关注(0)|答案(2)|浏览(121)

我试图创造一个突出显示的效果,在前面和结尾留下一点空间,以便于阅读,模仿你如何突出一本书。以下是几种尝试:

p {
  width: 10em;
}

mark.with-padding {
  border-radius: 10px;
  padding: 0.4em 0.2em;
  background-color: hsl(200deg 100% 80%);
  box-decoration-break: clone;
}

mark.with-before-after {
  border-radius: 10px;
  padding: 0.4em 0px;
  background-color: hsl(200deg 100% 80%);
  box-decoration-break: clone;
}

mark.with-before-after::before {
  content: '\2009';
}

mark.with-before-after::after {
  content: '\2009';
}

个字符
1.使用padding沿着box-decoration-break: clone;也可以在软换行符上应用padding,这是我喜欢的。但是,可以理解的是,文本的垂直对齐方式并不完全正确,因为填充会占用一些在开始时突出显示的行的空间。
1.使用::before + ::after与薄空间确保垂直对齐的行开始与突出显示没有。但是,这意味着突出显示和新行上的文本之间没有间隙。
对于实体书,文本通常是左对齐的,并且突出显示该边界之外的“溢出”。所以它是1 + 2的混合,你有两个填充(取决于你开始突出显示的位置)和垂直对齐。
如何用纯CSS(没有JS)创建这样的效果?
下面是我在Notability中手动绘制的所需结果的近似示例:
x1c 0d1x的数据
这有三个属性:
1.换行可以工作(就像inline元素)。
1.文字合理;突出显示的行(‘t’)的文本的左边缘与未突出显示的行(‘p’)的左边缘相匹配。
1.在文本前后的突出显示部分,每行都有“填充”。
这些属性的组合意味着突出显示必须“溢出”到文本内容的左/右边界之外。

jdgnovmf

jdgnovmf1#

尝试复制文本,突出显示复制的文本,并使其透明。然后将不可见的高亮显示的复制文本叠加到可见文本上。
该解决方案要求建立默认字体,并按照OP代码(OoriginalPost aka the question)中的内容显式设置文本宽度(参见图I)。

图一

html { font: 300 2ch/2.25ex 'Segoe UI'; }
p { width: 11em; }

字符串
接下来,用<div> Package 可见文本,并为其分配一个类(例如:然后将<p>添加到<div>,并为其分配一个类(例如:复制<div>的文本并将其放置在<p>中。然后用<mark>将复制文本中应该突出显示的部分换行。(见图二)。

图二

<div class='anchor'>Copy this text. Highlight this part.
<p class='ghost'>Copy this text. <mark>Highlight this part.</mark></p>
</div>


以下是有关CSS测量单位的注解:

图三

| 项目名称| Description |
| --| ------------ |
| 相对于父元素的font-size的长度。|在本例中,默认值font-sizehtml设置,因此1em = 2ch。|
| 相对于“x”(取决于font-family)或0.5em的高度的长度。|在示例中,ex用于垂直paddingline-height和定位。|
| 相对于“0”宽度的长度(取决于font-family)。|在示例中,ch用于水平padding和定位。|

示例中有详细注解

html {
  font: 300 2ch/2.25ex 'Segoe UI'
}

p {
  width: 11em;
}

.anchor {
  /* 
  This establishes the <div> as the area for <p class='ghost'> to position 
  itself in.
  */
  position: relative;
  width: 11em;
  margin: 1em 0;
}

.ghost {
  /*
  Allows <p> to position itself within the perimeter of it's parent
  <div class='anchor'>.
  */
  position: absolute;
  /*
  Places <p> to occupy the layer underneath <div>.
  */
  z-index: -1;
  /*
  Shifts <p> down 
  */
  bottom: -2.5ex;
  /*
  Shifts <p> to the left
  */
  left: -0.5ch;
  /*
  <p> should be slightly wider than <div class='anchor'>
  */
  width: 12em;
  /*
  Hides the text
  */
  color: transparent;
}

mark {
  /*
  This establishes <mark> as the area for <mark>::before pseudo-element to position to
  */
  position: relative;
  /*
  Positions <mark> underneath <p>
  */
  z-index: -2;
  padding: 1ex 0.5ch 0 0;
  border-radius: 10px;
  /*
  Should be smaller than default line-height set at root to compensate for the
  extra padding
  */
  line-height: 1.25ex;
  /*
  Hides the text
  */
  color: transparent;
  background-color: hsl(200deg 100% 80%);
  /*
  Shapes the "box" as a continuous shape when wrapped. Needs vendor prefix
  for Chrome and Safari
  */
  box-decoration-break: slice;
  -webkit-box-decoration-break: slice;
}

mark::before {
  content: '\2009';
  /*
  Allows <::mark> to position itself within the perimeter of it's parent
  <mark>
  */
  position: absolute;
  /*
  Positions <::mark> underneath <mark>
  */
  z-index: -3;
  /*
  Keeps <::mark> at the top edge of <mark>
  */
  top: 0;
  /*
  Shifts <::mark> to the left.
  */
  left: -0.5ch;
  width: 6ch;
  padding: 1ex 0 1ex 1ch;
  border-top-left-radius: 10px;
  border-bottom-left-radius: 10px;
  /*
  Should be relatively smaller than the line-height of root because of 
  it's large padding. <::mark> is an extension of <mark> when it wraps over 
  to the next line. It also blends in if there is no wrapping.
  */
  line-height: 1.65ex;
  background-color: hsl(200deg 100% 80%);
}

mark::after {
  content: '\a0\a0';
  /*
  Allows <mark::> to position itself within the perimeter of it's parent
  <mark>
  */
  position: absolute;
  /*
  Positions <mark::> underneath <::mark>
  */
  z-index: -4;
  /*
  Keeps <::mark> at the top edge of <mark>
  */
  top: 0;
  /*
  Shifts <mark::> to the right.
  */
  right: -1.5ch;
  width: 3ch;
  padding: 1ex 1ch 1ex 0;
  border-top-right-radius: 10px;
  border-bottom-right-radius: 10px;
  /*
  Should be relatively smaller than the line-height of root because of 
  it's large padding. <mark::> is the end of the highlight.
  */
  line-height: 1.65ex;
  background-color: hsl(200deg 100% 80%);
}
<p>Here is some text that isn't highlighted and it wraps around.</p>

<div class='anchor'>Here is some text. Here is some highlighted text.
  <p class='ghost'>Here is some text. <mark>Here is some highlighted text.</mark></p>
</div>

<div class='anchor'>All of this is highlighted.
  <p class='ghost'><mark>All of this is highlighted.</mark></p>
</div>

<div class='anchor'>This text is highlighted. This text is not.
  <p class='ghost'><mark>This text is highlighted.</mark> This text is not.</p>
</div>

的字符串

5jdjgkvh

5jdjgkvh2#

使用相对定位的更简单的解决方案,不需要复制内容。(我不知道这是否会在某些情况下打破。
左填充被负的左偏移抵消。

p {
  width: 12em;
}

mark.with-relative {
  border-radius: 10px;
  padding: 0.4em 0.2em 0.4em 0.25em;
  position: relative;
  z-index: -1;
  left: -0.25em;
  background-color: hsl(200deg 100% 80%);
  box-decoration-break: clone;
}

个字符
这会在突出显示结束于新行之后增加一点额外的空间,但这对我的用例来说是可以的。

相关问题