Skip to content

Lack of test coverage for parsing ranged @font-face descriptors #57834

@AtkinsSJ

Description

@AtkinsSJ

Specifically, font-weight, font-style, and font-width can take a pair of values to define a range that the @font-face should be used for. As far as I can tell, WPT tests only cover matching, in css/css-fonts/matching, and those are fairly limited. There aren't tests for parsing these inside @font-face at all, only as style properties.

Locally I'm using this. (test() runs the function when the dom content loads.) I don't think this is exhaustive but it's already shown some differences between Chromium and Firefox. Specifically, Chromium doesn't like normal or bold appearing in the two-value syntax.

<!DOCTYPE html>
<style>
    @font-face {
        font-family: Two numbers;
        src: local('not-a-real-font-i-promise');
        font-weight: 100 200;
    }
    @font-face {
        font-family: Two numbers reversed;
        src: local('not-a-real-font-i-promise');
        font-weight: 200 100;
    }
    @font-face {
        font-family: Two keywords;
        src: local('not-a-real-font-i-promise');
        font-weight: bold normal;
    }
    @font-face {
        font-family: Two keywords reversed;
        src: local('not-a-real-font-i-promise');
        font-weight: normal bold;
    }
    @font-face {
        font-family: Number and keyword;
        src: local('not-a-real-font-i-promise');
        font-weight: normal 700;
    }
    @font-face {
        font-family: Number and keyword again;
        src: local('not-a-real-font-i-promise');
        font-weight: bold 300;
    }
    @font-face {
        font-family: Two numbers filling the range;
        src: local('not-a-real-font-i-promise');
        font-weight: 1 1000;
    }
    
    /* The following are invalid, and should return 'normal' */
    @font-face {
        font-family: Invalid too many;
        src: local('not-a-real-font-i-promise');
        font-weight: 100 100 100;
    }
    @font-face {
        font-family: Invalid relative lighter;
        src: local('not-a-real-font-i-promise');
        font-weight: lighter;
    }
    @font-face {
        font-family: Invalid relative bolder;
        src: local('not-a-real-font-i-promise');
        font-weight: bolder;
    }
    @font-face {
        font-family: Invalid relative;
        src: local('not-a-real-font-i-promise');
        font-weight: lighter bolder;
    }
    @font-face {
        font-family: Invalid out of range;
        src: local('not-a-real-font-i-promise');
        font-weight: 0 20000;
    }
</style>
<script src="../include.js"></script>
<script>
    test(() => {
        document.fonts.forEach(font => {
            println(`${font.family}: ${font.weight}`);
        });
    });
</script>

Chromium:

Two numbers: 100 200
Two numbers reversed: 200 100
Two keywords: normal
Two keywords reversed: normal
Number and keyword: normal
Number and keyword again: normal
Two numbers filling the range: 1 1000
Invalid too many: normal
Invalid relative lighter: normal
Invalid relative bolder: normal
Invalid relative: normal
Invalid out of range: normal

Firefox:

Two numbers: 100 200
Two numbers reversed: 200 100
Two keywords: bold normal
Two keywords reversed: normal bold
Number and keyword: normal 700
Number and keyword again: bold 300
Two numbers filling the range: 1 1000
Invalid too many: normal
Invalid relative lighter: normal
Invalid relative bolder: normal
Invalid relative: normal
Invalid out of range: normal

I've only got to font-weight so far, but it seems likely there are other inconsistencies worth testing.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions