压缩文本以适应 CSS

Posted

技术标签:

【中文标题】压缩文本以适应 CSS【英文标题】:Squeeze text to fit in CSS 【发布时间】:2020-01-17 07:44:21 【问题描述】:

我有一个方形的 Bootstrap 按钮“墙”,下面有一个字体很棒的图标和两行文本 (<span>)。有时,每行的文本可能太长,所以自然换行。我想阻止这种情况。但是,要求必须显示全文。我也不想通过放大单个图块来破坏图块布局。

因此,我的想法是使用 CSS transform: scaleX(?) 来压缩文本以防万一。但我没有参考文本的实际宽度。另外,瓦片的 with 是基于相对单位的,所以我不能使用任何固定的像素值。

这是我当前的 css declamation:

<style>
    .flex-container .btn-lg 
        width: 20vmin;
        height: 20vmin;
        margin: 8px;
        font-size: 3.5vmin;
        word-wrap: break-word;
        white-space: normal;
    

    .btn-tile > * 
        display: flex;
        justify-content: center;
    
</style>

<div data-bind="foreach: $data.entries" class="flex-container">
    <button class="btn btn-secondary btn-lg btn-tile storageType-3" data-bind="click: e, class: 'storageType-' + d.type">
        <i class="fas fa-ramp-loading" data-bind="class: d.icon"></i>
        <span data-bind="text: d.desc1"></span>
        <span data-bind="text: d.desc2" style=" /* Experimental */
            transform: scaleX(.8);
            white-space: nowrap;
        ">This text is way too long</span>
    </button>
</div>

如果文本 desc1desc2 太长,则应应用 scaleX,以便它们适合固定大小的按钮。

这甚至可以用纯 CSS 实现,还是我需要用 javascript 遍历图块,读取实际宽度并计算这样的缩放因子?

顺便说一句,我正在使用淘汰赛绑定。

编辑:

我做了一些实验,但仍然无法计算出正确的比例因子。对于较长的文本,正确的因子应该在 0.3 左右。但它返回 0.477。

1 / $('.btn-tile').first().children().last()[0].scrollWidth * ($('.btn-tile')[0].offsetWidth)

【问题讨论】:

您可以在跨度text.length &gt; 10 &amp;&amp; '.shrink' 上放置一个条件类,并以这种方式在 CSS 中调整文本的大小。缺点显然是它不是动态的,但它会给你两个快速简单的样式选择 @JasonMcFarlane 谢谢你的建议。但我需要一个适用于各种长度文本的解决方案。 【参考方案1】:

这个想法是使用溢出元素中scrollWidthclientWidth 的差异来计算适合整个父元素的理想缩放比例,并将其作为scaleX 变换应用于溢出元素。

不要忘记将变换原点设置在对象的左侧,因为它在右侧溢出。

不幸的是,我认为您不能在纯 CSS 中执行此操作,因为您需要计算 scrollWidth 和 clientWidth。但这里有一个最小的例子来说明如何做到这一点:

els = document.querySelectorAll(".possibly-scaled");
for (let el of els) 
    let xScale = el.clientWidth / el.scrollWidth;
    if (xScale < 1)  
        el.style.transform = "scaleX(" + xScale + ")";
    
.fixed-width 
    font-size: 30px;
    margin: 8px;
    padding: 4px;
    text-align: center;
    background-color: yellow;

    /* necessary styling */
    width: 80px;
    white-space: nowrap; 


.possibly-scaled 
    /* necessary styling */
    display: block;
    transform-origin: 0 0;
<div class="fixed-width">
    <span class="possibly-scaled">OK</span>
</div>
<div class="fixed-width">
    <span class="possibly-scaled">Good</span>
</div>
<div class="fixed-width">
    <span class="possibly-scaled">Fantastic!</span>
</div>
<div class="fixed-width">
    <span class="possibly-scaled">Amazingly, this also fits.</span>
</div>

【讨论】:

这正是我想要的。非常感谢!我现在唯一要解决的就是如何使用 knockout.js 来实现这一点,因为固定宽度的元素是动态生成的。 当你生成一个新元素时,你是否有某种回调函数被调用?如果是这样,请在该回调中使用 for 循环中的代码(el = 新元素)。 并非如此。我使用 knockout.js,所有内容都是数据绑定的。我已经在找活动了。幸运的是,所有按钮都是从同一个模板生成的,所以可能有一个 init 处理程序之类的。 我找到了解决方案。 Knockout 在模板绑定中发出 afterRender 事件。我刚刚编写了一个全局视图模型方法,它的计算与您的示例完全相同。 knockoutjs.com/documentation/… @AndréReichelt 您可以改用 jQuery 的 .each(callback);,但在内部这只是另一个 for 循环。不过它更符合 jQuery 风格的代码。有关详细信息,请参阅 jQuery 文档。【参考方案2】:

对于即

var x, i;
        x = document.querySelectorAll(".possibly-scaled");
        for (i = 0; i < x.length; i++) 
            //x[i].style.backgroundColor = "red";
            let xScale = x[i].clientWidth / x[i].scrollWidth;
            console.log('aaa' + xScale);
            if (xScale < 1)
                x[i].style.transform = "scaleX(" + xScale + ")";
        

【讨论】:

非常感谢!

以上是关于压缩文本以适应 CSS的主要内容,如果未能解决你的问题,请参考以下文章

css 图片高度怎么设置才不会变形,被压缩

前段性能-静态资源,资源压缩

web优化汇总 简

动态宽度大小以适应堆栈视图中的控件

如何组织 css 和 js 文件的压缩和打包以加快网站速度?

用 CSS 扩展文本框以适应其内容?