如何解析CSS字体缩写格式

11

我需要将CSS的字体缩写格式解析成单独的组件(字体系列、字体大小、字重等)。这种缩写格式看起来相当复杂。以下是两个示例:

10px sans-serif
bold italic small-caps 1em/1.5em verdana,sans-serif

在我开始编写解析器之前,是否已经存在可以使用的解析器(最好是用JavaScript编写的)?


2
为什么需要这样做?浏览器内置了解析器可以完成此操作 - 将您的“font”属性字符串应用于临时元素并读取单独的属性不是更容易吗? - thirtydot
我同意thirtydot的观点,你甚至可以从开发者工具或firebug中复制解析后的CSS。 - Ivan Ivanic
1
我考虑过,但它不起作用。当设置“字体”时,其他属性如fontSize和fontFamily仍为空。也许在你的浏览器中可以工作,但我的Chrome不支持它。 - kayahr
你需要精确的值吗?例如,使用 24px(或任何实际的 px 值)代替 1.5emline-height 是否可接受?你介意使用像 jQuery 这样的 JavaScript 库吗? - thirtydot
我的问题比较通用,因此使用临时DOM元素并使用jQuery的css()函数可能会被接受为答案,但我更喜欢不需要临时DOM元素的解决方案。 - kayahr
4个回答

11

以下是一种"使用jQuery的css()函数和临时DOM元素"的解决方案:

http://jsfiddle.net/thirtydot/tpSsE/2/

var $test = $('<span />');
$test.css('font', 'bold italic small-caps 1em/1.5em verdana,sans-serif');

alert($test.css('fontWeight'));
alert($test.css('fontStyle'));
alert($test.css('fontVariant'));
alert($test.css('fontSize'));
alert($test.css('lineHeight'));
alert($test.css('fontFamily'));


1
我认为你会发现 $test 指向 body 元素(你的示例删除了 body 元素)。你需要使用 var $test = $('<span />').appendTo('body')。 :) - alex
1
顺便说一下,为了使这个工作正常,不必将$test元素插入DOM(第一行的.appendTo('body')部分)。因此,您也不再需要$test.remove()语句。这并不是什么大问题,只是更加简洁,可能会带来非常小的性能提升。 - Bill Dami
直截了当且高效的回答。+1 - Brice Coustillas

9

纯粹的自由范围Javascript版本:

var parsedStyleForCSS = function(cssString){
    var el = document.createElement("span");
    el.setAttribute("style", cssString);

    return el.style; // CSSStyleDeclaration object
};

var parsedStyle = parsedStyleForCSS("font: bold italic small-caps 1em/1.5em verdana,sans-serif");

console.log(parsedStyle["fontWeight"]); // bold
console.log(parsedStyle["fontStyle"]); // italic
console.log(parsedStyle["fontVariant"]); // small-caps
console.log(parsedStyle["fontSize"]); // 1em
console.log(parsedStyle["lineHeight"]); // 1.5em
console.log(parsedStyle["fontFamily"]); // verdana, sans-serif

如果您想使用完整样式表进行类似操作,请参考以下答案:在JavaScript / jQuery中解析CSS

8
这是我刚刚创建的字体解析器函数,以下是我的尝试,请帮忙看看是否适用于所有字体缩写格式的特殊情况。
function parseFont(font)
{
    var fontFamily = null,
        fontSize = null,
        fontStyle = "normal",
        fontWeight = "normal",
        fontVariant = "normal",
        lineHeight = "normal";

    var elements = font.split(/\s+/);
    outer: while (element = elements.shift())
    {
        switch (element)
        {
            case "normal":
                break;

            case "italic":
            case "oblique":
                fontStyle = element;
                break;

            case "small-caps":
                fontVariant = element;
                break;

            case "bold":
            case "bolder":
            case "lighter":
            case "100":
            case "200":
            case "300":
            case "400":
            case "500":
            case "600":
            case "700":
            case "800":
            case "900":
                fontWeight = element;
                break;

            default:
                if (!fontSize)
                {
                    var parts = element.split("/");
                    fontSize = parts[0];
                    if (parts.length > 1) lineHeight = parts[1];
                    break;
                }

                fontFamily = element;
                if (elements.length)
                    fontFamily += " " + elements.join(" ");
                break outer;
        }
    }

    return {
        "fontStyle": fontStyle,
        "fontVariant": fontVariant,
        "fontWeight": fontWeight,
        "fontSize": fontSize,
        "lineHeight": lineHeight,
        "fontFamily": fontFamily
    }
}

+1,经过几次快速测试,对于有效的输入来说似乎没问题。 - thirtydot


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接