现代CSS能否确定文本是否换行?

huangapple go评论71阅读模式
英文:

Can modern CSS determine whether a line of text is wrapped?

问题

我想要在非常大的屏幕上将text-align属性设置为center,而在较小的屏幕上设置为left。有没有纯CSS的方法来检测文本是否会换行?

英文:

Say I have some HTML like this:

<h1>The is a very long title, on small screens it will wrap but not on wider screens</h1>

I want to make the text-align property to center when it's on very large screens and left on smaller ones. Is there any pure CSS way to detect if the text will wrap?

答案1

得分: 2

据我所知(我可能完全错误),不行。你不能仅通过CSS来检测一行是否会换行。

我想不出在没有JavaScript的情况下如何做到这一点,也无法避免一些临时的丑陋瞬间:

要使用JavaScript检查块级元素是否会换行,你可以像下面这样做,基本上临时地使元素没有文本换行,然后检查其计算/渲染大小,并将其与其父元素的宽度进行比较(并根据父元素对文本流动和大小调整发生的方式进行一些其他检查):

function checkWillOverflow(elem) {
  const parent = elem.parentElement;
  const parentStyleMap = parent.getComputedStyleMap();
  if (parentStyleMap.get("width").value === "max-content") {
    return false;
  }
  if (parentStyleMap.get("overflow-x").value === "scroll") {
    return ; // TODO: 这里你需要决定想要发生什么。
  }

  // 此函数假定在样式属性中没有任何东西来覆盖
  //(并且它优先级高于样式规则的任何东西)。
  // 如果有的话,你需要在之后“备份”这些值并在之后恢复它们。
  elem.style.width = "max-content";
  // 将父元素的边框和内边距设置为空,以准备获取仅内容框的计算宽度。
  parent.style.borderWidth = "0";
  parent.style.padding = "0";

  const willOverflow = elem.getBoundingClientRect().width > parent.getBoundingClientRect().width;

  // 撤销样式属性更改
  parent.style.removeProperty("border-width");
  parent.style.removeProperty("padding");

  return willOverflow;
}

你可能还想检查计算样式映射,以在writing-mode为上下模式时执行不同的操作(或者你可能不需要)。

如果你(或者阅读此内容的其他人)实际上并不关心它是否会换行,实际上只想根据视口宽度等条件应用不同的样式,请查看CSS的媒体查询功能

如果你想在涉及元素的大小发生变化时得到更新,你将需要使用ResizeObserver API

英文:

As far as I know (and I may very well be wrong), no. You can't detect whether a line will wrap with CSS alone.

I can't think of a way to do it without JavaScript without some temporary flashes of ugliness either:

To check if a block element will wrap with JavaScript, you could do something like this, which basically temporarily forces the element to have no text wrapping, and then checks its calculated / rendered size and compares it to the width its parent element would have (and does some other checks on how text flows and sizings happen according to the parent element):

function checkWillOverflow(elem) {
  const parent = elem.parentElement;
  const parentStyleMap = parent.getComputedStyleMap();
  if (parentStyleMap.get("width").value === "max-content") {
    return false;
  }
  if (parentStyleMap.get("overflow-x").value === "scroll") {
    return ; // TODO: you need to decide what you want to happen here.
  }

  // this function assumes there is nothing in the style attributes to overwrite
  // (and that anything it takes higher precedence over is in style rules).
  // if there is, you will need to "back up" those values and restore them after.
  elem.style.width = "max-content";
  // set border and padding of parent to empty in preparation to get the
  // calculated width of the content box only.
  parent.style.borderWidth = "0";
  parent.style.padding = "0";

  const willOverflow = elem.getBoundingClientRect().width > parent.getBoundingClientRect().width;

  // undo the style attribute changes
  parent.style.removeProperty("border-width");
  parent.style.removeProperty("padding");

  return willOverflow;
}

You might also want to check the computed style maps to do something different if the writing-mode is a top-bottom one (or you might not).

If you (or someone else reading this) don't actually care whether it will wrap and actually just want different styles based on things like viewport width, check out CSS' media queries feature.

If you want to be updated on changes to the sizing of the element in question, you will need to use the ResizeObserver API.

huangapple
  • 本文由 发表于 2023年2月24日 14:58:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/75553437.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定