<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>CSS Fonts Module Level 4: parsing font with valid values</title> <link rel="help" href="https://drafts.csswg.org/css-fonts-4/#font-prop"> <meta name="assert" content="font supports the full grammar '[ [ <'font-style'> || <font-variant-css2> || <'font-weight'> || <font-stretch-css3> ]? <'font-size'> [ / <'line-height'> ]? <'font-family'> ] | caption | icon | menu | message-box | small-caption | status-bar'."> <script src="/resources/testharness.js"></script> <script src="/resources/testharnessreport.js"></script> <script src="/css/support/parsing-testcommon.js"></script> </head> <body> <div id="target"></div> <script> 'use strict'; // Firefox and Edge 18 serialize these as supplied. // Blink and Safari have implementation-dependent or platform-dependent serializations. function test_system_font(keyword) { test(() => { const target = document.getElementById('target'); const previousValue = 'italic xx-large/0px fantasy'; target.style.font = previousValue; target.style.font = keyword; const readValue = target.style.getPropertyValue('font'); assert_not_equals(readValue, '', 'font should be set'); assert_not_equals(readValue, previousValue, 'font should be updated'); target.style.font = previousValue; target.style.font = readValue; assert_equals(target.style.getPropertyValue('font'), readValue, "serialization should round-trip"); }, keyword + ' should be a supported system font.'); } test_system_font('caption'); test_system_font('icon'); test_system_font('menu'); test_system_font('message-box'); test_system_font('small-caption'); test_system_font('status-bar'); // values other than normal const generate_style = (() => { const alternatives = [ 'italic', 'oblique' ]; let counter = 0; return () => alternatives[counter++ % alternatives.length]; })(); // value other than normal const generate_variant = () => 'small-caps'; // values other than normal const generate_weight = (() => { const alternatives = [ 'bold', 'bolder', 'lighter', '100', '900' ]; let counter = 0; return () => alternatives[counter++ % alternatives.length]; })(); // values other than normal const generate_stretch = (() => { const alternatives = [ 'ultra-condensed', 'extra-condensed', 'condensed', 'semi-condensed', 'semi-expanded', 'expanded', 'extra-expanded', 'ultra-expanded' ]; let counter = 0; return () => alternatives[counter++ % alternatives.length]; })(); const generate_size = (() => { const alternatives = [ // <absolute-size> 'xx-small', 'medium', 'xx-large', // <relative-size> 'larger', 'smaller', // <length-percentage> '10px', '20%', 'calc(30% - 40px)', ]; let counter = 0; return () => alternatives[counter++ % alternatives.length]; })(); const generate_line_height = (() => { const alternatives = [ null, 'normal', '1.2', 'calc(120% + 1.2em)' ]; let counter = 0; return () => alternatives[counter++ % alternatives.length]; })(); const generate_family = (() => { const alternatives = [ 'serif', 'sans-serif', 'cursive', 'fantasy', 'monospace', 'Menu', '"FB Armada"' ]; let counter = 0; return () => alternatives[counter++ % alternatives.length]; })(); function test_specific(prefix) { let parts = []; let canonical = []; let style = null; let variant = null; let weight = null; let stretch = null; for (let entry of prefix) { if (entry === 'style') { style = generate_style(); parts.push(style); } else if (entry === 'variant') { variant = generate_variant(); parts.push(variant); } else if (entry === 'weight') { weight = generate_weight(); parts.push(weight); } else if (entry === 'stretch') { stretch = generate_stretch(); parts.push(stretch); } else { // normal parts.push('normal'); } } if (style) canonical.push(style); if (variant) canonical.push(variant); if (weight) canonical.push(weight); if (stretch) canonical.push(stretch); const size = generate_size(); const lineHeight = generate_line_height(); if (lineHeight) { parts.push(size + '/' + lineHeight); if (lineHeight === 'normal') canonical.push(size); else canonical.push(size + ' / ' + lineHeight); } else { parts.push(size); canonical.push(size); } const family = generate_family(); parts.push(family); canonical.push(family); test_valid_value('font', parts.join(' '), canonical.join(' ')); } function test_various(prefix) { test_specific(prefix); if (prefix.length === 4) return; const alternatives = [ 'normal', 'style', 'variant', 'weight', 'stretch' ]; for (let alternative of alternatives) { if (alternative === 'normal' || !prefix.includes(alternative)) test_various(prefix.concat(alternative)); // else we would have two styles or two variants, etc. } } test_various([]); </script> </body> </html>