根据内容(CSS或JS)缩放字体大小

时间:2017-04-22 22:59:16

标签: javascript css font-size

注意,我不是要求根据视口大小缩放字体 - 我的问题不同。

我的HTML / CSS / JS应用程序基本上向用户呈现状态图。屏幕上有一条带有多个按钮的消息。按下每个按钮会导致不同的屏幕 - 依此类推 - 非常简单的概念,的确如此。

每个按钮来自数据库的每个屏幕的文本。

设计是这样的,按钮尺寸是固定的(我不能控制它)。它们的大小足以容纳应用程序可以遇到的任何东西 - 用英语。

最近,我需要添加斯瓦希里语支持 - 突然之间有2个单词,15个英文字符变成5个单词,在斯瓦希里语中有近50个字符 - 而且它不适合按钮。这是相当糟糕的 - 但只有少数这样的长按钮标签。不幸的是,由于它们是动态的(来自数据库),我在预测它将会做什么方面做得不够。

我可以做的是减小字体大小以适应按钮内的文本。使用vwvh等单位无法正常工作,因为无论视口大小如何,文本都应缩放到固定大小的按钮。

我无法想到任何仅限CSS的解决方案。我可以想一下这个问题的几个JS解决方案(例如放置文本,然后继续缩小它直到它适合 - 虽然我不太确定如何确定它适合)。

我不能完全理解这一点。有任何想法吗?我对CSS3和HTML5感到满意,只需要在最新版本的Chrome和Safari中使用它。

2 个答案:

答案 0 :(得分:0)

查看此jsbin:http://jsbin.com/sunamej/1/edit?html,css,js,output

文本根据在white-space: nowrap的虚拟文本容器上进行的计算进行缩放。这允许将文本的总宽度与按钮的宽度进行比较,并按比例缩小。请记住,由于未考虑单词的换行位置存在一些错误。这在很大程度上可以通过包含的误差因子来缓解,但可能需要针对您的应用进行微调。实际上计算一些东西以完全考虑到自动换行的位置将是艰巨的,并且不适合这样的应用程序只有几个单词/行的时间。以下是bin中的代码:

HTML:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
  <button class="btn">
    <span class="dummy-text">
      Testing with some large text that should scale
    </span>
    <span class="text">
      Testing with some large text that should scale
    </span>
  </button>
  <button class="btn">
    <span class="dummy-text">
      Testing with some
    </span>
    <span class="text">
      Testing with some
    </span>
  </button>
  <button class="btn">
    <span class="dummy-text">
      Testing with some large text
    </span>
    <span class="text">
      Testing with some large text
    </span>
  </button>
<script src="https://code.jquery.com/jquery-3.1.0.js"></script>
</body>
</html>

CSS:

.btn {
  /* hardcoded dimens */
  height: 35px;
  width: 75px;
}

.dummy-text {
  /* hide dummy, don't wrap */
  display: none;
  white-space: nowrap;
}

使用Javascript:

console.clear();
// NOTE: use of jQuery is arbitrary; all functions
// are available in vanilla js

function scaleText(btn) {
  // select the dummy text
  var dtxt = btn.find('.dummy-text');
  // select the real text
  var txt = btn.find('.text');

  // get te with of the button and the dummy
  var tw = dtxt.width();
  var bw = btn.width();

  // number of lines of text the button allows
  var lines = 2;
  // factoring in error caused by wrapping; this
  // may need fine tuning for your application
  var err = 0.85;
  // get the fonts scale
  var scale = (bw * lines * err)/tw;

  // get the current font size
  var sz = parseInt(dtxt.css('font-size').replace('px', ''));
  // scale appropiately
  txt.css('font-size', sz * scale + 'px');
}

// apply to each button
var btns = $('.btn');
btns.each(function(i, btn) {
  scaleText($(btn));
});

答案 1 :(得分:0)

Adjust size of an SVG-element to its content启发,它需要更多微调和一种方法将长文本拆分为适当数量的行,如果您可以从文本长度猜测宽度/高度,可以用foreignObject换行......但这是一个可能的开始:

&#13;
&#13;
[...document.getElementsByTagName("svg")].forEach(svg => {
  const bbox = svg.getBBox();
  svg.setAttribute("viewBox", [bbox.x, bbox.y, bbox.width, bbox.height].join(" "));
})
&#13;
button {
  width: 100px;
  height: 50px;
  padding: 0;
}

svg {
  width: 100%;
  height: 100%;
}
&#13;
<button>
  <svg>
    <text>Short</text>
  </svg>
</button>
<button>
  <svg>
    <text>Longer text</text>
    <text y='1em'>split externally</text>
    <text y='2em'>to balanced lines</text>
  </svg>
</button>
&#13;
&#13;
&#13;