【问题标题】:Text is not positioned the same in Safari as in other browsers文本在 Safari 中的位置与在其他浏览器中的位置不同
【发布时间】:2019-05-24 12:18:44
【问题描述】:

文本在 Safari 中的位置与在其他浏览器中的位置不同。这有什么原因吗?有没有一种风格可以确保它符合精确的测量要求。

* {
  margin: 0;
  padding: 0;
}
#btn_signup {
  opacity: 1;
  position: absolute;
  width: 185px;
  height: 50px;
  left: 10px;
  top: 10px;
  overflow: visible;
}
#Rectangle_1 {
  opacity: 1;
  fill: transparent;
  stroke: rgb(67, 66, 93);
  stroke-width: 1px;
  stroke-linejoin: miter;
  stroke-linecap: butt;
  stroke-miterlimit: 4;
  shape-rendering: auto;
}
.Rectangle_1 {
  position: absolute;
  overflow: visible;
  width: 185px;
  height: 50px;
  left: 0px;
  top: 0px;
}
#Sign_up {
  opacity: 1;
  position: absolute;
  left: 58px;
  top: 16px;
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  overflow: visible;
  width: 63px;
  white-space: nowrap;
  text-align: center;
}
#Path_1 {
  opacity: 1;
  fill: rgba(0,0,0,0);
  stroke: rgb(112, 112, 112);
  stroke-width: 0.5px;
  stroke-linejoin: miter;
  stroke-linecap: butt;
  stroke-miterlimit: 4;
  shape-rendering: auto;
}
.Path_1 {
  overflow: visible;
  position: absolute;
  top: 16.5px;
  left: 1px;
  width: 183.5px;
  height: 0.5px;
  transform: matrix(1,0,0,1,0,0);
}
<div id="A5">
  <div id="btn_signup">
    <svg class="Rectangle_1">
      <rect id="Rectangle_1" rx="4" ry="4" x="0" y="0" width="185" height="50"></rect>
    </svg>
    <div id="Sign_up">
      <span style="font-family:Helvetica;font-style:normal;font-weight:normal;font-size:18px;color:rgba(77,79,92,1);display:inherit;">Sign up</span>
    </div>
    <svg viewBox="12.5 0 183.5 0.5" class="Path_1">
      <path id="Path_1" d="M 12.5 0 L 196 0"></path>
    </svg>
  </div>
</div>

在 Firefox 中,文本与行齐平。在 Safari 中会有一些像素间隙,如下图所示:

如何消除这个差距?

增加了赏金。如果您需要更清晰的信息,请提出问题。

更新:
感谢所有垂直居中的建议。我有一半的案例将通过垂直居中来修复,但其余的是顶部对齐案例。

看起来我想要的是让我的文本内容,大写高度的内容边界框与文本行的顶部边缘对齐,如图所示。

资源:
看起来这是跨平台的常见问题。
Cap height and x-height metrics are inaccurate
Vertical Metrics

【问题讨论】:

  • 可能是不同的line-height;尝试明确设置。
  • 奇数。我想不出其他任何东西,我这里没有 Safari 可供测试,抱歉。改为投票。
  • 要对齐字体,您需要阅读其指标,这是一种可能的方法:stackoverflow.com/questions/38242098/…
  • 备注,将我的别名添加到您的 cmets 以便我收到通知。

标签: html css safari webkit typography


【解决方案1】:

请用 CSS 替换这段代码:

#Sign_up {
    opacity: 1;
    box-sizing: border-box;
    overflow: visible;
    white-space: nowrap;
    height: 50px;
    line-height: 50px;
    text-align: center;
    display: block;
}

【讨论】:

  • 没有解释的代码质量非常低。
【解决方案2】:

字体在不同的浏览器上呈现不同。这是同一行文本的捕获。它在所有主要浏览器上都被捕获,并将其放在彼此之上以说明问题的严重性。 (取自this article

不同的字体会给出不同的结果

当我需要让文本垂直对齐像素完美时,我们有一个团队进行了一些研究。我们发现某些字体的垂直对齐方式比其他字体更好 - 因此值得测试。

你总是可以用 JS 破解它

如果是 safari - 更改行高(或边距或其他)

if (navigator.userAgent.toLowerCase().indexOf('safari') > -1) {
  $('.your-element').css({lineHeight: "21px"});
}

【讨论】:

  • 在另一条评论中,我建议将文本绘制到画布上,然后读取第一个非透明像素的位置,有人可以手动找出大写高度,然后设置使用该偏移量来准确设置垂直位置在每个浏览器中。不过这需要 JavaScript。
【解决方案3】:

#btn_signup 保留position: relative;。 同时使用以下 CSS 将 Sign_up 居中

#Sign_up {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
}

它在所有浏览器中都一样。

* {
  margin: 0;
  padding: 0;
}

#btn_signup {
  opacity: 1;
  position: relative;
  width: 185px;
  height: 50px;
  left: 10px;
  top: 10px;
  overflow: visible;
}

#Rectangle_1 {
  opacity: 1;
  fill: transparent;
  stroke: rgb(67, 66, 93);
  stroke-width: 1px;
  stroke-linejoin: miter;
  stroke-linecap: butt;
  stroke-miterlimit: 4;
  shape-rendering: auto;
}

.Rectangle_1 {
  position: absolute;
  overflow: visible;
  width: 185px;
  height: 50px;
  left: 0px;
  top: 0px;
}

#Sign_up {
  opacity: 1;
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  overflow: visible;
  width: 63px;
  white-space: nowrap;
  text-align: center;
}

#Path_1 {
  opacity: 1;
  fill: rgba(0, 0, 0, 0);
  stroke: rgb(112, 112, 112);
  stroke-width: 0.5px;
  stroke-linejoin: miter;
  stroke-linecap: butt;
  stroke-miterlimit: 4;
  shape-rendering: auto;
}

.Path_1 {
  overflow: visible;
  position: absolute;
  top: 16.5px;
  left: 1px;
  width: 183.5px;
  height: 0.5px;
  transform: matrix(1, 0, 0, 1, 0, 0);
}
<div id="A5">
  <div id="btn_signup">
    <svg class="Rectangle_1">
      <rect id="Rectangle_1" rx="4" ry="4" x="0" y="0" width="185" height="50"></rect>
    </svg>
    <div id="Sign_up">
      <span style="font-family:Helvetica;font-style:normal;font-weight:normal;font-size:18px;color:rgba(77,79,92,1);display:inherit;">Sign up</span>
    </div>
    <svg viewBox="12.5 0 183.5 0.5" class="Path_1">
      <path id="Path_1" d="M 12.5 0 L 196 0"></path>
    </svg>
  </div>
</div>

【讨论】:

  • 谢谢我在需要居中时使用它。如果浏览器能够在浏览器之间完美居中,那么它就知道文本内容边界框。如果他们可以应用这个来允许文本对齐到它的垂直像素位置,它将提供更多的一致性。如果我或某人可以在画布上绘制字体,然后读取第一个非透明垂直像素的像素位置,那么某人可以手动找出大写高度,然后设置使用该偏移量在每个浏览器中准确设置垂直位置。跨度>
【解决方案4】:

不同的浏览器以不同的方式处理小数定位。处理小数像素不在 CSS 规范中,所以即使现在一切都正确定位,它可能会在浏览器更新后再次中断。如果您删除所有小数像素值并添加line-height:1,它应该可以工作。

如果这不起作用,试试这个,让我知道你看到了什么(我不使用 Safari 或 FF)。检查每个浏览器中的span,该工具应突出显示一个矩形。查看矩形的顶部是否没有接触到线条或文本的顶部是否没有接触到矩形的顶部。在 Chrome 中,文本的顶部没有碰到矩形的顶部,所以解决方法是line-height:1

【讨论】:

    【解决方案5】:

    看到这个问题和答案: WebKit vs Mozilla vertical alignment of font glyphs in box

    基本上,CSS 允许您调整文本元素的位置,但实际字母与元素的位置取决于字体和浏览器。您不能直接修改它,这意味着,理论上,您无法真正确定字母本身的实际位置。

    CSS 为您提供间接访问,例如使用 vertical-align,您可以将文本与父文本对齐。因此,根据值,元素将相对于实际字母定位。例如:

    div {
      font-size: 20px;
      line-height: 1.2;
      border-top: solid lightgray 1px;
      font-family: arial;
    }
    
    div span {
      display: inline-block;
      background-color: lightblue;
      border-top: solid red 1px;
    }
    
    .topalign span {
      vertical-align: top;
    }
    
    .bottomalign span {
      vertical-align: bottom;
    }
    <div class="topalign">
      <span style="font-family: 'helvetica neue'; ">Helvetica N</span>
      <span style="font-family: 'arial'; font-size: 30px">Arial</span>
      <span style="font-family: 'Times new roman';  ">Times NR</span>
      <span style="font-family: 'Tahoma'; font-size: 15px;">Tahoma</span>
    </div>
    <div class="bottomalign">
      <span style="font-family: 'helvetica neue'; ">Helvetica N</span>
      <span style="font-family: 'arial'; font-size: 30px">Arial</span>
      <span style="font-family: 'Times new roman';  ">Times NR</span>
      <span style="font-family: 'Tahoma'; font-size: 15px;">Tahoma</span>
    </div>

    你也可以使用line-height,它会改变文本元素的高度而不改变字体大小,这意味着你可以或多或少地控制你想要放置字母的位置。但同样,不同的字体/浏览器会呈现不同的效果。您仍然没有精确定位字母。例如:

    div {
      font-size: 30px;
      line-height: 1.2;
      border-top: solid lightgray 1px;
      font-family: arial;
    }
    
    div span {
      display: inline-block;
      background-color: lightblue;
      border-top: solid red 1px;
    }
    
    .topalign span {
      vertical-align: top;
    }
    <div class="topalign">
      <span style="font-family: 'helvetica neue'; ">Helvetica N</span>
      <span style="font-family: 'arial'; line-height: 1.5;">Arial</span>
      <span style="font-family: 'Times new roman';  line-height: 0.5;">Times NR</span>
      <span style="font-family: 'Tahoma'; ">Tahoma</span>
    </div>

    因此,理论上,您无法精确定义实际字母的确切位置。它不能是显式的,因此会导致跨浏览器的不一致。

    话虽如此,您指出的情况似乎是带有 Helvetica 字体的 Firefox 错误。 Helvetica 的字母定位与其他字体或其他浏览器不一致。当您与 Helvetica NeueArial 进行比较时尤其明显,它们应该或多或少相同。见:

    div {
      font-size: 30px;
      line-height: 1.2;
      border-top: solid lightgray 1px;
      font-family: arial;
    }
    
    div span {
      display: inline-block;
      background-color: lightblue;
      border-top: solid red 1px;
    }
    
    .topalign span {
      vertical-align: top;
    }
    <div class="topalign">
      <span style="font-family: 'helvetica';  ">Helvetica </span>
      <span style="font-family: 'helvetica neue'; ">Helvetica N</span>
      <span style="font-family: 'arial'; ">Arial</span>
    </div>

    即使您无法明确说明字母位置,您仍然可以期待一定程度的一致性。通常,在顶部和底部有一个或多或少相等的正常且连贯的填充。它可能因字体而异,也因浏览器而异,但在 Firefox 中呈现 helvetica 的方式肯定看起来像一个错误(至少对我来说,也许是有原因的,但我不明白为什么)。

    因此,如果您可以将 Helvetica 替换为 Helvetica Neue,则可以使用 line-height 来定位字母与元素并实现你想要什么。例如,通常大约 0.75 的 line-height 将与大写字母的顶部和底部齐平,这意味着通过定位元素,您可以定位字母。比如这样:

    * {
      margin: 0;
      padding: 0;
    }
    #btn_signup {
      opacity: 1;
      position: absolute;
      width: 185px;
      height: 50px;
      left: 10px;
      top: 10px;
      overflow: visible;
    }
    #Rectangle_1 {
      opacity: 1;
      fill: transparent;
      stroke: rgb(67, 66, 93);
      stroke-width: 1px;
      stroke-linejoin: miter;
      stroke-linecap: butt;
      stroke-miterlimit: 4;
      shape-rendering: auto;
    }
    .Rectangle_1 {
      position: absolute;
      overflow: visible;
      width: 185px;
      height: 50px;
      left: 0px;
      top: 0px;
    }
    #Sign_up {
      opacity: 1;
      position: absolute;
      left: 58px;
      top: 16px;
      box-sizing: border-box;
      margin: 0;
      padding: 0;
      overflow: visible;
      width: 63px;
      white-space: nowrap;
      text-align: center;
    }
    #Path_1 {
      opacity: 1;
      fill: rgba(0,0,0,0);
      stroke: rgb(112, 112, 112);
      stroke-width: 0.5px;
      stroke-linejoin: miter;
      stroke-linecap: butt;
      stroke-miterlimit: 4;
      shape-rendering: auto;
    }
    .Path_1 {
      overflow: visible;
      position: absolute;
      top: 16.5px;
      left: 1px;
      width: 183.5px;
      height: 0.5px;
      transform: matrix(1,0,0,1,0,0);
    }
    <div id="A5">
      <div id="btn_signup">
        <svg class="Rectangle_1">
          <rect id="Rectangle_1" rx="4" ry="4" x="0" y="0" width="185" height="50"></rect>
        </svg>
        <div id="Sign_up">
          <span style="font-family:Helvetica neue;font-style:normal;font-weight:normal;font-size:18px;color:rgba(77,79,92,1);display:inherit;line-height: 0.75;">Sign up</span>
        </div>
        <svg viewBox="12.5 0 183.5 0.5" class="Path_1">
          <path id="Path_1" d="M 12.5 0 L 196 0"></path>
        </svg>
      </div>
    </div>

    【讨论】:

    • 那么您是说我们需要一种新样式来确保文本的边界框在大写高度处与其容器元素的边缘对齐,以确保它在浏览器和字体中看起来一致?你会怎么称呼这个新样式名称?
    • 确实,似乎没有任何工具或标准可以精确定位字母。部分渲染依赖于未暴露的字体信息——至少这是我的理解。也许有一天,像字形对齐规则这样的东西可以让我们将字母对齐到父元素的顶部、底部或中间。这将解决你提到的问题。但这可能会导致许多其他问题......
    猜你喜欢
    • 2023-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-07
    • 1970-01-01
    • 2013-08-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多