如何在 Photoshop 中测量/转换 CSS 文本边距/填充?

Posted

技术标签:

【中文标题】如何在 Photoshop 中测量/转换 CSS 文本边距/填充?【英文标题】:How to measure/convert CSS text margin/padding in the Photoshop? 【发布时间】:2018-06-05 16:20:25 【问题描述】:

如何从 Photoshop 中获取 CSS 文本边距/填充?

如何将 Photoshop 中文本的距离转换为 CSS 边距/填充?

与 Photoshop 中文本元素(段落)的距离与 CSS 中的边距/填充不对应。例如,使用智能指南测量距离:

都是因为在距离计算中不使用线高。因此,我找到的第一个建议是使用公式

margin_in_CSS = distance_in_PS - (line-height - font-size) / 2

或更短:

CSS = PS - (line-height - font-size) / 2

这是从一些明显的边框(线)到文本元素的距离。对于我们分别使用的两段之间的距离:

CSS = PS - (line-height_1 - font-size_1) / 2 - (line-height_2 - font-size_2) / 2

随着字体大小的增加,很明显这个公式是不够的。 Photoshop中线条的实际高度(通过选择工具获得)甚至小于字体大小!

虽然 photoshop 仍然认为元素的高度大约等于字体大小,但这并不影响到它的距离:(。例如,在属性选项卡上:

我计算出线条的真实高度和字号的差异在顶部大约是30%15%和文本的底部(我并不是说这是 100% 正确的!)。现在我使用公式

CSS = PS - (0.15 * font-size + (line-height - font-size) / 2)

或在两个段落之间:

CSS = PS - (0.15 * font-size_1 + (line-height_1 - font-size_1) / 2)
         - (0.15 * font-size_2 + (line-height_2 - font-size_2) / 2)

同样,我们不能依靠 Photoshop 正确定义多行段落的高度。但是这里的情况比较简单,CSS中段落的真实高度会是:

height = line-height * num_of_lines

问题是,有没有更简单的方法?О_о

对不起我的英语^_^


更新,更短的公式:

文字边框

CSS = PS - (line-height - 0.7 * font-size) / 2

文字文字

CSS = PS - (line-height_1 - 0.7 * font-size_1) / 2
         - (line-height_2 - 0.7 * font-size_2) / 2

更新

现在正在开发用于在 Adob​​e 论坛 (link) 上正确计算距离的脚本。目前,该脚本可以计算与标准(自动)行高为 120% 的文本行的边界框的距离。


更新

不管是用带尖文本还是段落文本,结果边界框高度不等于文本行高(前导)

【问题讨论】:

【参考方案1】:

如何将 Photoshop 中文本的距离转换为 CSS 边距/填充?

文本的实际生成字形(图像中的粉红色边框)将具有不同的高度,其中包含以下内容:

" [空白] = 根本没有字形 ... 一个 一个 QQ q

边距和内边距不应从文本本身测量,而是从文本行的边界(或 CSS 中的 line-height)测量。

在上面的例子中:

65px 是文本行的实际高度(或 CSS 中的 line-height),(文本换行时与两个文本基线的距离)以及计算边距/填充时使用的值。最终结果是,无论文本元素的内容如何,​​从其基线到它后面的元素的距离都应该保持不变,基于line-height、(底部)margin 和(底部)padding(和,当然,在下一个元素的上边距和内边距上)。

简而言之,PS 不会减少边距。 只是它们不是从文本字形的边界框计算出来的(可能因内容而异),但来自文本行的边界框。

.psd 转换为 html 时要考虑的另一件事是,在 HTML 中你有 collapsing margins。简而言之,从两个垂直相邻的边距中,只会保留最大的一个。如果另一个是负数,将从正数中扣除,如果两个都是负数,则应用最大值。

【讨论】:

PS 中的距离是从字符的边界框计算出来的,至少使用智能指南 - 再次检查第一个屏幕截图。那就是问题所在。而在 CSS 中,距离是从 text linebounding box 计算出来的...所以问题是如何从 bounding box 的PS中的文本行??? 我相信你错了。 PS中的距离也是从line-box计算出来的。要在 PS 中获取行框,您可以将文本转换为段落文本,它的框将默认为文本行。如果您说的是真的,那么 line-height 会因内容而异,但事实并非如此。 不,我想我是对的。请用屏幕截图检查我的最后一次更新。不管是用尖头文字还是段落文字,结果边界框高度不等于文字行高(line-height =leading)【参考方案2】:

终于,测量垂直距离的脚本完成了! 它可以正确计算 CSS 图层之间的垂直距离,其中一个或两个都是文本图层。

这是 Adob​​e 论坛上的链接 - A script for measuring the distance between two elements?

// version no CS6 or no effects

var old_units = app.preferences.rulerUnits;    
app.preferences.rulerUnits = Units.PIXELS;    

try  app.activeDocument.suspendHistory("Get Text Bounds", "var bounds = get_selected_layers_bounds()")  catch(e)  alert(e);   

try  executeAction( charIDToTypeID( "undo" ), undefined, DialogModes.NO );  catch(e)  alert(e);   

app.preferences.rulerUnits = old_units;    

if (bounds)    
        
    if (bounds.length == 2)    
            
        var distance = 0;

        if (bounds[0].bottom <= bounds[1].top) distance = bounds[1].top - bounds[0].bottom;    
        else if (bounds[1].bottom <= bounds[0].top) distance = bounds[0].top - bounds[1].bottom;    

        else  alert("Intersecting layers")    

        var distance_in_css = distance - (bounds[0].leading - 1.2*bounds[0].size)/2 - (bounds[1].leading - 1.2*bounds[1].size)/2;

        alert("distance = " + distance + "\ndistance_in_css = " + distance_in_css);
            
    else    
        alert("More then 2 selected layers")     

        
else     
    alert("There is no selected layers")     

/////////////////////////////////////////////////////////////////////////////////////////////////    
function get_selected_layers_bounds()    
        
    try     
        var ref = new ActionReference();    

        ref.putProperty( charIDToTypeID( "Prpr" ), stringIDToTypeID( "targetLayers" ) );    
        ref.putEnumerated( charIDToTypeID("Dcmn"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt") );    
        var desc = executeActionGet(ref);    

        if (!desc.hasKey( stringIDToTypeID("targetLayers") ) ) return null;    

        var n = 0;    
        try  activeDocument.backgroundLayer  catch (e)  n = 1;     

        desc = desc.getList( stringIDToTypeID("targetLayers"));    

        var len = desc.count;    

        var selected_bounds = new Array();    

        for (var i = 0; i < len; i++)    
                
            try     
                    
                var r = new ActionReference();    
                r.putIndex( charIDToTypeID( "Lyr " ), desc.getReference(i).getIndex() + n);    

                var ret = executeActionGet(r);    

                var size    = 0;
                var leading = 0;

                if (ret.hasKey(stringIDToTypeID("textKey")))  
                      
                    var textStyleRangeList = ret.getObjectValue(stringIDToTypeID("textKey")).getList(charIDToTypeID("Txtt" ));

                    if (textStyleRangeList.count > 1)  alert("More than one textStyleRange in layer", "Oops!!"); 

                    var textStyle = textStyleRangeList.getObjectValue(0).getObjectValue(charIDToTypeID("TxtS" ));

                    var auto_leading = textStyle.getBoolean(stringIDToTypeID("autoLeading"));

                    size = textStyle.getUnitDoubleValue(stringIDToTypeID("size"));
                    leading = auto_leading?size*1.2:textStyle.getUnitDoubleValue(stringIDToTypeID("leading"));

                    var s = ret.getObjectValue(stringIDToTypeID("textKey")).getString(charIDToTypeID("Txt " ));  
                    s = s.replace(/^./gm, String.fromCharCode(0x2588));  

                    var d1 = new ActionDescriptor();  
                    d1.putReference( charIDToTypeID( "null" ), r );  

                    var d2 = new ActionDescriptor();  
                    d2.putString( charIDToTypeID( "Txt " ), s);  

                    d1.putObject( charIDToTypeID( "T   " ), charIDToTypeID( "TxLr" ), d2 );  

                    executeAction( charIDToTypeID( "setd" ), d1, DialogModes.NO );  

                    ret = executeActionGet(r);    
                      


                // var bounds = ret.getObjectValue(stringIDToTypeID("bounds"));  // use this in CS6 or when you want to take into account the effects    

                var bounds = ret.getObjectValue(stringIDToTypeID("boundsNoEffects")); // in CS6 does not work    

                var obj =  
                          left   : bounds.getUnitDoubleValue(stringIDToTypeID("left")),    
                          top    : bounds.getUnitDoubleValue(stringIDToTypeID("top")),    
                          right  : bounds.getUnitDoubleValue(stringIDToTypeID("right")),    
                          bottom : bounds.getUnitDoubleValue(stringIDToTypeID("bottom")),
                          size   : size,
                          leading: leading,
                          ;    

                    selected_bounds.push(obj);    
                

                catch (e)  alert(e); return null;     
                

            return selected_bounds;    
            

    catch (e)  alert(e); return null;     

脚本应保存为 *.js 或 *.jsx 文件(例如,distance.js)在 Photoshop 文件夹 - C:\Program Files\Adobe\Adobe Photoshop CC 2017\Presets\Scripts

它将在 Photoshop 菜单 - 文件 > 脚本 > 距离中可用

【讨论】:

【参考方案3】:

没关系,psd 是为了显示网站完成后的外观,您必须考虑字体大小,例如对于段落文本,如果 psd 中的字体大小为 14 pt 且网格为 1200px(引导程序),则您必须以浏览器的纵横比转换字体(引导程序中现在默认为 16px)并相应地计算,如 psd 中的 14pt 等于 14px + (14 * 0.16%)px 在浏览器中以及相应的其他所有内容,与行高类似。 另外,如果您想设置与 psd 相同的字体大小,如果我们的 psd 字体大小为 14pt 段落,则由您为 html 选择 14px。

【讨论】:

以上是关于如何在 Photoshop 中测量/转换 CSS 文本边距/填充?的主要内容,如果未能解决你的问题,请参考以下文章

Safari css 宽度过渡不适用于不同的单位测量

如何以 css px 或 rem 计算 Photoshop 字母间距?

CSS学习12-PS的基本操作

如何测量浏览器中的 CSS 解析和渲染时间?

CSS 样式转换与 svg 转换

如何获取要发布到 Gravity Forms 的 html/css 表单?