纯CSS,可根据动态字符数对字体大小做出响应


298

我知道可以使用Javascript轻松解决此问题,但是我只对纯CSS解决方案感兴趣。

我想要一种动态调整文本大小的方法,以使其始终适合固定的div。这是示例标记:

<div style="width: 200px; height: 1em; overflow: hidden;">
  <p>Some sample dynamic amount of text here</p>
</div>

我在想,也许可以通过在ems中指定容器的宽度,并让font-size继承该值来实现?


1
哇等一下 widthin ems东西的指定是相反的。这是width依赖于font-size。@JosephSilber正是我的想法。
2013年

1
我对这个问题很好奇。什么是使用纯CSS解决方案而不是编写简单的javascript函数的驱动器?
奥斯汀·穆林斯

22
造成这种情况的原因仅仅是因为问题存在,而且纯CSS解决方案将是惊人的。考虑仅应用几种样式的可能性,并知道您的动态内容永远不会破坏设计。
DMTintner 2013年

4
以防万一有人偶然发现此问题并且不介意使用JS,这是一个用于执行此操作的插件fittextjs.com
DMTintner 2013年

2
fitText有限制。例如,我只想在宽度超过500像素左右的小屏幕上运行它,就不希望标题变大。这需要编写更多的JavaScript。当您使用JavaScript进行布局时,关注点分离会很快分解。它绝不仅仅是快速的班轮。
哥斯达黎加

Answers:


513

我刚刚发现,使用大众汽车是可能的。它们是与设置视口宽度关联的单位。有一些缺点,例如缺乏对旧版浏览器的支持,但这绝对是认真考虑使用的东西。另外,您仍然可以为旧版浏览器提供后备广告,例如:

p {
    font-size: 30px;
    font-size: 3.5vw;
}

http://css-tricks.com/viewport-sized-typography/https://medium.com/design-ux/66bddb327bb1


30
为此将放弃2次。CSS解决方案取胜!
Mihkel L.

34
专家提示:您可以通过执行操作font-size:calc(100% + 2vw);或类似操作来防止文本变得太小并获得一些控制权。有点min-font-size。浏览器对的支持calc与相似vw
Prinzhorn,2014年

116
赞成,但现在我想知道这是否真的回答了原始问题。我的理解是您的文本长度是动态的,并且您想更改字体大小以始终适合您的宽度div(200px)。这如何解决这个问题?
Floremin 2015年

26
我同意@Floremin的观点。这将根据视口的宽度/高度(而不是文本的宽度/高度的容器)缩放所有字体大小。
MickJuice 2015年

24
@Floremin是正确的,这不能解决问题。这是根据容器宽度而不是字符串长度来计算字体大小,因为它与容器宽度有关
henry

113

CSS3支持与视口相关的新尺寸。但这在android <4.4中不起作用

  1. 3.2vw =视口宽度的3.2%
  2. 3.2vh =视口高度的3.2%
  3. 3.2vmin =小于3.2vw或3.2vh
  4. 3.2vmax = 3.2vw或3.2vh较大

    body
    {
        font-size: 3.2vw;
    }
    

请参阅css-tricks.com / ....,也请参阅caniuse.com /...。

要么

使用媒体查询。最简单的方法是使用%或em尺寸。只需更改基本字体大小,一切都会改变。

@media (max-width: @screen-xs) {
    body{font-size: 10px;}
}

@media (max-width: @screen-sm) {
    body{font-size: 14px;}
}


h5{
    font-size: 1.4em;
}

使用以%或em为单位的尺寸。只需更改基本字体大小,一切都会改变。在上一个版本中,您可以只更改主体字体,而不是每次都更改h1,或者将基本字体大小设置为设备的默认值,并将其全部保留在em中

有关em,px和%的更多信息,请参见kyleschaeffer.com / ....


12
问题是关于相对于容器而不是相对于整个视口的缩放。
Arnaud Weil

6
...而问题是关于根据字符数进行缩放
Bravo


14

唯一的方法可能是为不同的屏幕尺寸设置不同的宽度,但是这种方法非常不准确,您应该使用js解决方案。

h1 {
    font-size: 20px;
}

@media all and (max-device-width: 720px){
    h1 {
        font-size: 18px;
    }
}

@media all and (max-device-width: 640px){
    h1 {
        font-size: 16px;
    }
}

@media all and (max-device-width: 320px){
    h1 {
        font-size: 12px;
    }
}

12

我知道我要解决一个长期存在的问题,但是我有同样的问题,我想补充一点。请不要为此禁止我,我觉得证明这个答案很重要,如果需要,我将其删除。@Joseph Silber是错误的,编码所有可能性实际上是一种可行的方法。原因是因为实际上没有无限的可能性。嗯,从技术上讲,有99%的访客将使用标准分辨率。对于移动设备(这是响应式Web设计的主要原因),这是双重事实,因为大多数移动操作系统在不调整窗口大小的情况下全屏运行应用程序。

另外,由于滚动条的原因,高度几乎无关紧要(在某种程度上,我会立即留下一个超过4或5英尺长的网页,但这基本上是正确的),因此您只需要担心宽度。实际上,您只需要编写以下宽度:240、320、480(适用于较旧的iThings),640、800、1024、1280、1440、1600、1920、2048、2560。 4k,它将使您的图像过分膨胀,将2560尺寸拉伸到100%的宽度在4k显示器上看起来还不错(我已经测试过)。另外,不要像以前的海报所建议的那样烦恼720(720x480)。它的分辨率几乎是数码相机专用的,即使这样也很少见。

如果有人使用奇异的分辨率,那么过去15年中制作的几乎所有渲染器都将舍入,例如,如果某人的屏幕宽度为。1100,它将加载1024 CSS规则,您的网站应该不会损坏。这通过尝试创建不必要的响应规则来解决异乎寻常的分辨率问题,除非您使用的网络浏览器过时以至于您的网站可能无法加载,否则您需要为每个可能的设置像素逐个编码的想法很荒谬。无论如何。


1
而现在iPhone
6/6

如果使用SASS或Compass并进入功能,则可能会更容易。一个函数可以为您完成所有CSS工作。一次写入多次使用。
cjbarth

高度几乎无关紧要,直到您将设备侧面旋转90º为止,即
Carvo Loco

但是,这与容器的宽度无关-很容易就有无限的可能性。
mcheah

8

作为参考,一个非CSS解决方案:

下面是一些JS,它根据容器内的文本长度来调整字体大小。

Codepen的代码稍有修改,但思路如下:

function scaleFontSize(element) {
    var container = document.getElementById(element);

    // Reset font-size to 100% to begin
    container.style.fontSize = "100%";

    // Check if the text is wider than its container,
    // if so then reduce font-size
    if (container.scrollWidth > container.clientWidth) {
        container.style.fontSize = "70%";
    }
}

对我来说,当用户在下拉菜单中进行选择时,我会调用此函数,然后填充菜单中的div(这是我发生动态文本的位置)。

    scaleFontSize("my_container_div");

此外,我还使用CSS省略号(“ ...”)截断甚至更长的文本,如下所示:

#my_container_div {
    width: 200px; /* width required for text-overflow to work */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

因此,最终:

  • 短文字:例如“ APPLES”

    充分呈现,漂亮的大字母。

  • 长文本:例如“ APPLES&ORANGES”

    通过上面的JS缩放功能将其缩小70%。

  • 超长文字:例如“苹果,橙子和香蕉...”

    通过上面的JS缩放功能和CSS规则,将比例缩小70%,并用“ ...”省略号截断。

您还可以探索使用CSS字母间距来使文本变窄,同时保持相同的字体大小。


由于用户要求使用纯CSS解决方案而被否决了
AnotherLongUsername

2

正如@DMTinter的评论中提到的那样,OP正在询问字符更改的数量(“数量”)。他还问过CSS,但是正如@Alexander所说,“仅CSS不可能实现”。据我所知,这在目前看来是正确的,因此人们想知道下一个最好的东西似乎也是合乎逻辑的。

我对此并不感到特别自豪,但确实可以。似乎要完成它的代码过多。这是核心:

function fitText(el){
  var text = el.text();
  var fsize = parseInt(el.css('font-size'));
  var measured = measureText(text, fsize);

  if (measured.width > el.width()){
    console.log('reducing');
    while(true){
      fsize = parseInt(el.css('font-size'));
      var m = measureText(text, fsize );
      if(m.width > el.width()){
        el.css('font-size', --fsize + 'px');
      }
      else{
        break;
      }
    }
  }
  else if (measured.width < el.width()){
    console.log('increasing');
    while(true){
      fsize = parseInt(el.css('font-size'));
      var m = measureText(text, fsize);
      if(m.width < el.width()-4){ // not sure why -4 is needed (often)
        el.css('font-size', ++fsize + 'px');
      }
      else{
        break;
      }
    }
  }
}

这是一个JS Bin:http : //jsbin.com/pidavon/edit?html,css, js,console, output
请提出可能的改进建议(我对使用画布来测量文本不太感兴趣...似乎就像太多的开销(?)。

感谢@Pete提供measureText功能:https ://stackoverflow.com/a/4032497/442665


2

此解决方案可能也有帮助:

$(document).ready(function () {
    $(window).resize(function() {
        if ($(window).width() < 600) {
            $('body').css('font-size', '2.8vw' );
        } else if ($(window).width() >= 600 && $(window).width() < 750) {
            $('body').css('font-size', '2.4vw');
        } 
         // and so on... (according to our needs)
        } else if ($(window).width() >= 1200) {
            $('body').css('font-size', '1.2vw');
        }
    }); 
  });

它对我很好!


如何考虑自动换行?
Leif Neland '18


2
calc(42px + (60 - 42) * (100vw - 768px) / (1440 - 768));

使用这个方程式。

对于大于或小于1440和768的任何值,可以给它提供静态值,也可以应用相同的方法。

vw解决方案的缺点是您无法设置缩放比例,例如在1440屏幕分辨率下的5vw可能会变成60px字体大小(即您的想法字体大小),但是当您将窗口宽度缩小到768时,它可能会结束是12px,不是您想要的最小值。使用这种方法,您可以设置上边界和下边界,并且字体将在两者之间进行缩放。


-2

创建一个查找表,该表根据中的字符串长度计算字体大小<div>

const fontSizeLookupTable = () => {
  // lookup table looks like: [ '72px', ..., '32px', ..., '16px', ..., ]
  let a = [];
  // adjust this based on how many characters you expect in your <div>
  a.length = 32;
  // adjust the following ranges empirically
  a.fill( '72px' ,     );
  a.fill( '32px' , 4 , );
  a.fill( '16px' , 8 , );
  // add more ranges as necessary
  return a;
}

const computeFontSize = stringLength => {
  const table = fontSizeLookupTable();
  return stringLength < table.length ? table[stringLength] : '16px';
}

通过经验测试调整和调整所有参数。


对参数的经验测试本质上是时间复杂度为O(log n)的二进制搜索。
让我思考一下

您实际上忘记了调用此函数,还需要使用其属性来访问数组长度。
6

@lukk:感谢您的反馈。立即修复。
让我思考一下
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.