尽管有“line-height: 1”和“overflow: hidden”,但仍然保持悬挂字符可见

Gur*_*ofu 8 html css

目标

在此处输入图片说明

<div class="Card">
  <div class="Card-FullNameLabel">Gregg Sims</div>
  <div class="Card-OrganizationNameLabel">Compubotics</div>
</div>
Run Code Online (Sandbox Code Playgroud)
  1. .Card-FullNameLabelfont-size: 16pxline-height: 1
  2. .Card-OrganizationNameLabelfont-size: 12pxline-height: 1
  3. .Card-FullNameLabel和之间的垂直空间.Card-OrganizationNameLabel必须正好为6px
  4. 以下 CSS 规则必须有效且不得更改。
.Card-FullNameLabel + .Card-OrganizationNameLabel {
  margin-top: 6px;
}
Run Code Online (Sandbox Code Playgroud)
  1. 双方.Card-FullNameLabel.Card-OrganizationNameLabel必须有溢出公差(例如,如果该内容会像ÀÇ?jgpfhjklb?iEstosTreMalfaci等它不能从parrent突出)。
  2. 尽管 to ,所有字母都必须完全可见line-height: 1
  3. 不允许在 CSS 代码中使用心算(幻数和/或硬编码偏移量和其他必须预先计算的值)。

可以做什么:将 Pug 预处理器的功能用于标记,将 CSS 预处理器用于样式。

初始小提琴不满足条件编号5:目前该卡不支持溢出。

在此处输入图片说明

关于line-height: 1,不好的做法

我一再被告知我必须设置line-height的价值超过1.

很明显,设置 line-height: 1 是一种不好的做法。我提醒你,无单位值是与字体大小相关的,而不是与内容区域相关的,处理比内容区域小的虚拟区域是我们许多问题的根源。

深入研究 CSS:字体度量、行高和垂直对齐

好吧,我不打算对此提出异议。我想要的只是达到我的目标(如上所述)的工作解决方案。它的使用是我的责任,如果您同意line-height必须超过,我不会推荐这个解决方案1

但是为什么我不想line-height这么坚持地增加呢?

原因一:精确定义两个元素之间的垂直空间会变得过于复杂

该规则.Card-FullNameLabel + .Card-OrganizationNameLabel { margin-top: 6px; }清晰、直观,并通过 CSS 表达了准则(如上图所示)。“.Card-OrganizationNameLabel必须退出.Card-FullNameLabel6 个像素”,仅此而已。

但是,如果我们需要的定义之间的相同的垂直空间.Card-FullNameLabel,并.Card-OrganizationNameLabel在线路高度大于1(或它们的顶部和底部填充)?规则的值margin-top(下图中未覆盖的粉红色区域可视化).Card-FullNameLabel + .Card-OrganizationNameLabel现在是:

  1. 所需的范围(6px)
  2. 下面的额外垂直空间.Card-FullNameLabel(指定为l_b
  3. 上方额外的垂直空间.Card-OrganizationNameLabel(指定为l_a

在此处输入图片说明

正如我上面说,心算是不允许的,因为它贬低编程(CSS中的情况下CSS预处理程序的能力),使灵活性/可维护性的影响(如果我们改变line-heightfont-size或期望的标签之间的垂直空间,一切都需要在心理上重新计算)。

虽然预处理器的变量(今天在原生 CSS 中可用)可以解决这个问题,但维护它会太复杂。要计算上图中不相交的红色粉红色,我们需要:

  1. 变量font-size.Card-FullNameLabel
  2. 变量line-height.Card-FullNameLabel
  3. 计算下面的额外空间.Card-FullNameLabel
  4. 变量font-size.Card-OrganizationNameLabel
  5. 变量line-height.Card-OrganizationNameLabel
  6. 计算下面的额外空间 .Card-OrganizationNameLabel
  7. Variablelize之间的期望范围.Card-FullNameLabel.Card-OrganizationNameLabel(在该实施例6点的像素)。

在此之后,我们可以最终计算margin-top规则.Card-FullNameLabel + .Card-OrganizationNameLabel。对于每对像.Card-FullNameLabel和这样的元素也是一样的.Card-OrganizationNameLabel!!2020 年代的 Web 开发技术太差。

原因2:不需要每种语言

在下面的示例中,日语符号非常适合与line-height: 1(16px) 对齐:

在此处输入图片说明

我想中文、韩文和许多其他具有非拉丁字符的语言也是如此。

但是:在少数情况下,外国符号可能会混合:

在此处输入图片说明

如果要谈高质量,必须支持这种情况。

我不想只为这个例外增加行高。线之间的垂直空间实际上变成了没有也没关系6px:尾部jÀ具有较小的重量,不会破坏几何美学。

我的努力

尝试 1:使用:before:after

SASS-mixinTextTruncation接受$extraSpace添加顶部和底部填充的参数。在:before:after伪元素补偿这种垫衬负利润。

@mixin TextTruncation($extraSpace, $displayEllipsis: false) {
  
  overflow: hidden;
  white-space: nowrap;
  
  @if ($displayEllipsis) {
    text-overflow: ellipsis;
  } @else {
    text-overflow: clip;
  }
  
  padding-top: $extraSpace;
  padding-bottom: $extraSpace;
  
  &:before,
  &:after {
    content: "";
    display: block;
  }
  
  &:before {
    margin-top: -$extraSpace;
  }
  
  &:after {
    margin-bottom: -$extraSpace;
  }
}

body {
  padding: 12px;
}

* {
  line-height: 1;
  font-family: Arial, sans-serif;
}

.Card {
  
  display: flex;
  flex-direction: column;
  align-items: center;
  
  width: 240px;
  height: 320px;
  padding: 6px 12px 12px;
  
  background: white;
  box-shadow: 0 0 3px rgba(0, 0, 0, 0.5);
}

.Card-FullNameLabel {
  
  max-width: 100%; /* Required when the flex parent has `align-items: center` */
  @include TextTruncation($extraSpace: 2px, $displayEllipsis: true);
  
  font-size: 16px;
  color: #707070;
}

.Card-OrganizationNameLabel {
  
  max-width: 100%; /* Required when the flex parent has `align-items: center` */
  @include TextTruncation($extraSpace: 2px, $displayEllipsis: true);
  
  font-size: 12px;
  color: #A2A2A2;
}

.Card-FullNameLabel + .Card-OrganizationNameLabel {
  margin-top: 6px;
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,它不起作用:效果与没有定义边距和填充一样:

在此处输入图片说明

代码笔

尝试 2:使用包装器

如果组合overflow-x: hiddenoverflow-y: visible工程,这是解决方案。但它不起作用,这个问题已经在问题CSS overflow-x:visible; 中考虑过和溢出-y:隐藏;导致滚动条问题

我想尽可能使用包装器,但在这里看起来包装器将是最后的手段。为了避免每次都写两个标签,我创建了 Pug mixin:

mixin SingleLineLabel

  span.SingleLineLabel&attributes(attributes)
    span.SingleLineLabel-Text
      block
Run Code Online (Sandbox Code Playgroud)

好吧,SingleLineLabel现在是一个组件。除了 Pug mixin 之外,还需要定义基本样式,SASS mixin 允许单独自定义标签:

// Constant styles
.SingleLineLabel {

  overflow-y: visible;

  &:before,
  &:after {
    content: "";
    display: block;
  }


  &-Text {
    display: block;
    overflow-x: hidden;
    white-space: nowrap;
  }
}

// Variable styles
@mixin SingleLineLabel($truncatedVerticalSpaceCompensation, $displayEllipsis: false) {
  
  &:before {
    margin-top: -$truncatedVerticalSpaceCompensation
  }

  &:after {
    margin-bottom: -$truncatedVerticalSpaceCompensation
  }
  

  .SingleLineLabel-Text {
    
    padding-top: $truncatedVerticalSpaceCompensation;
    padding-bottom: $truncatedVerticalSpaceCompensation;
    
    @if ($displayEllipsis) {
      text-overflow: ellipsis;
    } @else {
      text-overflow: clip;
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

现在我们可以应用它:

.Card-FullNameLabel {
  
  max-width: 100%; /* Required when the flex parent has `align-items: center` */
  @include SingleLineLabel($truncatedVerticalSpaceCompensation: 1px, $displayEllipsis: true);
  
  font-size: 16px;
  color: #707070;
}

.Card-OrganizationNameLabel {
  
  max-width: 100%; /* Required when the flex parent has `align-items: center` */
  @include SingleLineLabel($truncatedVerticalSpaceCompensation: 2px, $displayEllipsis: true);
  
  font-size: 12px;
  color: #A2A2A2;
}

.Card-FullNameLabel + .Card-OrganizationNameLabel {
  margin-top: 6px;
}
Run Code Online (Sandbox Code Playgroud)

好像达到了目标:

在此处输入图片说明

代码笔

不幸的是,它存在发生规律不清楚的错误。有时会出现小的垂直滚动条。

在此处输入图片说明

真不知道怎么复现,但是在过去的实验中也出现过,比如通过开发工具把浏览器切换到设备模拟模式,然后退出这个模式。如果在小提琴中重复相同的实验,很可能不会得到相同的效果。

最后

基于您的出色答案的解决方案将包含在不断增长的@yamato-daiwa/frontend库中。

如果你有这样的问题的符号的完整列表gpÀ?等等,请与大家共享-我会用它来测试,并把它们添加到的溢出容限测试未来哈巴狗功能。

Aar*_*nat 1

我知道您明确指出您需要保留line-height: 1margin-top: 6px,但是当您发现记录的溢出 CSS 问题时,您有点坚持当前的限制。

如果可以灵活地对待这些限制,我有一个在视觉上与您最初想要的解决方案相同的解决方案。

原始状态

我从你的初始小提琴开始,并在 html 中添加了省略号截断 CSS 和有问题的文本。

.Card-FullNameLabel,
.Card-OrganizationNameLabel {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
Run Code Online (Sandbox Code Playgroud)

结果就是这种状态,我称之为“原始”,因为它使你的line-heightmargin价值观保持不变。请注意,我添加了一条overflow: hidden规则来代替有问题的overflow-xoverflow-y规则混合。

提议的修复

我建议对 CSS 进行以下更改。这增加到line-height允许1.5所有字体的上升部分和下降部分可见。然后我添加了负偏移边距来补偿:

.Card-FullNameLabel,
.Card-OrganizationNameLabel {
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;

  /* Shows all ascenders and descenders */
  line-height: 1.5;
}

.Card-FullNameLabel {
  font-size: 16px;
  color: #707070;

  /* Compensates for line-height */
  margin: -4px 0;
}

.Card-OrganizationNameLabel {
  font-size: 12px;
  color: #A2A2A2;

  /* Compensates for line-height */
  margin: -3px 0;
}

.Card-FullNameLabel + .Card-OrganizationNameLabel {
  /* 6px visually (minus 3px) */
  margin-top: 3px;
}
Run Code Online (Sandbox Code Playgroud)

结果可以在这里看到,我将其称为“建议的修复”。我已经确认结果在最新的桌面 Chrome、Firefox 和 MacOS 上的 Safari 以及 iOS 上的移动 Safari 中是一致的。

比较

我根据“之前”和“之后”的屏幕截图制作了一个简单的动画,表明输出在视觉上是相同的,只是建议的修复不会切断字体的上升部分和下降部分。

请注意,您可以单击动画查看全尺寸、1:1 像素精度的版本。

在此输入图像描述

我对所谓的“中间元素”进行了一些额外的测试,以证明即使中间存在元素,建议的修复也会与原始修复相同。

在此输入图像描述


更新:自动化

正如评论中明确指出的,要求之一是 CSS 中没有“硬编码”或“魔术”数字。因此,虽然上述解决方案有效,但需要提前进行手动算术。

这是一个更新的Codepen,它可以通过使用一些 SCSS 逻辑自动生成与上面显示的类似的 CSS,这些逻辑将根据这些输入值计算偏移量:

多变的 当前值
$globalLineHeight 1
$minLineHeight 1.5
$fullNameFontSize 16px
$fullNameLineHeight $globalLineHeight
$orgNameFontSize 12px
$orgNameLineHeight $globalLineHeight
$orgNameMarginTop 6px

出于演示目的,我添加了一些额外的代码,这些代码将显示“之前”和“之后”悬停效果,以便您可以看到 SCSS 逻辑与原始 CSS 相比的行为方式。正如 HTML 和 CSS 中所示,您可以删除以 开头的行以下的任何内容#DELETE-ME

  • 对于问题中的第 7 点,您可能希望将其更改为“CSS 中没有幻数或硬编码偏移值”之类的内容。我会把这句话解释为你想要的。 (2认同)