[英]Scale fixed-width font to fit constant number of characters on a line
我有一个基于websocket的终端会话。 我希望增加字体大小以填充div,使其总是80个字符宽。 这样做的最佳方法是什么? 我喜欢它,如果只有CSS这样做的方式,但我已经在使用jQuery,所以一个vanilla javascript或jQuery解决方案也会很好。
对于支持小数字体大小或CSS text-rendering: geometricPrecision
浏览器text-rendering: geometricPrecision
,您可以获得固定宽度的字体,以完全适合任何边界。
在此屏幕截图中,第四行正好是80个字符:
对于不支持小数字体大小的浏览器,不可能始终使x字符适合给定的宽度。
这是12px
字体的相同文本:
...并使用13px
字体:
使用12px字体,最长的行是83个字符,所以它太小了。 使用13px字体,最长的行是77个字符,所以它太大了。
在这种情况下,您必须缩小或加宽容器以匹配字体:
下面的代码使用一种word-wrap: break-word;
的方式在宽度不同的div中放置一个80个字符的宽跨度word-wrap: break-word;
。 它使用getClientRects()
来确定二进制搜索的上限和下限,从而对二进制搜索最佳字体大小。
如果浏览器不支持小数字体大小,它会调整容器的宽度以匹配字体大小。
然后移除跨度。
$('div').each(function() {
var x= $('<span>'+Array(80).join('x')+'</span>').appendTo(this),
lo= 0.1,
hi= 50,
mid;
do {
mid= (lo+hi)/2;
$(this).css({
fontSize: mid
});
if(x[0].getClientRects().length > 1) {
hi= mid;
}
else {
lo= mid;
}
} while(Math.abs(hi-lo)>0.001);
while(x[0].getClientRects().length === 1) {
$(this).css({
width: '-=1'
});
}
while(x[0].getClientRects().length === 2) {
$(this).css({
width: '+=1'
});
}
x.remove();
});
在Chrome,IE,Firefox,Safari和Opera中测试过。
这是一个基于CSS的例子,基于8472的答案:
div,textarea{
width:100%;
max-width: 100%;
box-sizing: border-box;
-moz-box-sizing: border-box;
font-family: "Lucida Console", Monaco, monospace;
font-size: 1.99vw; /* The text overflows in safari using (int)2 */
white-space: nowrap;
overflow-x:hidden;
/* styling */
background:#09f;
min-height: 100px;
margin-bottom: 30px;
}
它是如何工作的?
要获得正确的字体大小,请将160除以每行所需的字符数减去0.01。
http://jsfiddle.net/mb2L4mee/1/
在Chrome,FF和Safari中测试过。
一种方法是计算固定font-size
大小的80字符行font-size
并在resize
事件上注册函数以根据终端大小调整font-size
大小。
<div id="terminal">
<div class="text">
Some text
</div>
</div>
function scale(lineWith) { /* lineWidth based on 80char 10px font-size */
var ratio = $('#terminal').width() / lineWith;
$('.text').css('font-size', (10 * ratio) + 'px');
}
$(window).resize(function(){
scale(lineWith)
});
演示: http : //jsfiddle.net/44x56zsu/
这似乎在Chrome中调整得非常好(Versión39.0.2171.99m)
但我不认为可以调整font-size
以适合所有浏览器的容器大小,因为十进制值是四舍五入的。 字体大小测试: http : //jsfiddle.net/ahaq49t1/
某些浏览器中的此舍入问题会阻止使用字体属性进行精确调整。
在限制范围内,它可能在纯CSS中。 如果您知道div将占据视口的分数,则可以根据视图端口宽度缩放字体。
.terminal {font-size: 1vw;}
会导致字体大小(垂直)相当于视图端口的1%。 由于等宽字体也具有固定的宽高比,因此宽度取决于字体的宽高比和视口大小。
不确定这是否是最优雅的解决方案,它还需要更多的抛光。 但你可以测量字体。 创建一个隐藏的度量栏,以查看字体的宽度(以像素为单位)。 填充所需的字符数量(此处使用20作为演示用途):
<span id="measureBar">12345678901234567890</span>
继续增加度量栏的字体大小,找到仍然不比div宽的最大宽度:
$( function() { var $measureBar = $('#measureBar'); var $console = $('#console'); $measureBar.css('font-size', '1px'); for (i = 1; $measureBar.width() <= $console.width(); i++) { $measureBar.css('font-size', i + 'px'); } $console.css('font-size', (i - 1) + 'px'); } )
#console { background-color: black; color: white; } #measureBar { display: none; } #measureBar, #console { font-family: courier; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <span id="measureBar">12345678901234567890</span> <div id="console">12345678901234567890 Text that should be twenty characters wide.</div>
我面临着非常相似的要求,并提出了一个相当直接的解决方案。 一旦我得到一些停机时间,我将围绕这个示例代码编写一个jQuery插件。
正如在这里的一些其他答案中提到的,关键是使用em作为字体大小的单位。 此外,为了在所有(现代)浏览器中实现类似的布局,对于必须处理各种固定宽度字体的解决方案,标尺方法是我发现的最可靠的方法。
function fixieRemeasure() { var offset = document.getElementById("fixie").offsetWidth, ruler = (document.getElementById("fixieRuler").offsetWidth * 1.01), fontSize = (offset / ruler); document.getElementById("fixie").style.fontSize = fontSize + "em"; } function fixieInit(columns) { document.getElementById("fixieRuler").innerText = new Array(columns + 1).join("X").toString(); fixieRemeasure(); } (function () { fixieInit(80); window.onresize = function () { fixieRemeasure(); }; } ());
#fixie { padding: 0 2px 0 6px; font-size: 1em; background-color: #000; color: #0F0; } #fixieRuler { font-size: 1em; visibility: hidden; }
<code id="fixieRuler"></code> <div id="fixie"> <pre>+------------------------------------------------------------------------------+ | | | ,%%%, | | ,%%%` %==-- | | ,%%`( '| | | ,%%@ /\\_/ | | ,%.-"""--%%% "@@__ | | %%/ |__`\\ | | .%'\\ | \\ / // | | ,%' > .'----\\ | [/ | | < <<` || | | `\\\\\\ || | | )\\\\ )\\ | | ^^^jgs^^"""^^^^^^""^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | ASCII Art: http://www.chris.com/ascii/index.php?art=animals/horses | +------------------------------------------------------------------------------+</pre> </div>
这只是一个概念证明,并且有一些相当明显的问题。主要是,resize方法被连续调用,应该替换为onResizeEnd之类的东西,并在生产使用之前正确附加到DOM。 为了组件化,我使用类选择器而不是id,并且还可以动态地插入/移除标尺元素。
希望能帮助到你。
UPDATE
我基于这个示例代码在github上创建了一个新项目fixie.js 。 在性能和模块化方面仍有一些工作要做,但它在所有浏览器中都运行良好,我相信它提供了最简单的方法,用最少量的样板代码来解决问题。
唯一的要求是为em中的pre元素设置font-size,并为它们提供格式为'fixie_ COLS '的类名:
<pre class="fixie_80">I'll be 80 columns</pre>
要遵循的jQuery和webcomponent实现。 这是麻省理工学院的许可,欢迎任何贡献: https : //github.com/dperish/fixie.js
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.