htmlcssfonts

CSS: how to let the children elements' font fallback to its parent's font family?


We're working on a html reader, and the content could be any html. We want to set a default font family if the font set in the content is not available.

For example,

<body style="font-family: A"><div style="font-family: B"></div></body>

If font B is not available, I prefer to use A to render. But we're not able to change the style on div since it's user content.

Or if it's possible to change browser's default fallback font?


Solution

  • Main problem: The browser applies the font-family property according to the most specific CSS rule (In your case the inline style attribute in <div>).

    If the actual font can't be applied (if the font isn't loaded via @font-face rules or not available as a locally installed font) it still applies this CSS rule.

    In other words: the browser won't search for available fonts specified in parent element style rules.

    So there is no way to force the browser to apply/prefer an actually available font for display e.g by traversing the complete CSS to find the best candidate – the cascade and specificity concept of CSS just doesn't work this way.

    Here's an example:

    body{
      font-family: sans-serif;
      font-size: 10vw;
    }
    
    div{
        font-family: 'None existent Sans', 'None existent Slab';
    }
    test
    <div style="font-family: 'None existent Sans'">Div content</div>

    The best you could do to keep the rendered HTML styling to some extent consistent is to override the <div> font styles via a more specific parent rule. E.g by using a more specific selector and/or adding the !important keyword.

    @font-face{
      font-family: Montserrat;
      src: url('https://fonts.gstatic.com/s/montserrat/v24/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCtr6Hw5aXo.woff2') format('woff2')
    }
    
    body, html body * {
      font-family: Montserrat, sans-serif!important;
      font-size: 10vw;
    }
    
    div{
        font-family: 'None existent Sans', 'None existent Slab';
    }
    <p>Hamburgefons</p>
    <div style="font-family: 'None existent Sans'">Div content <div style="font-family: 'None existent Sans'">Sub Div content</div></div>

    Remap font-families to default

    To some extent you may also remap some font-famies to a default font via @font-face

    body {
      font-family: sans-serif;
      font-size: 10vw;
    }
    
    @font-face {
      font-family: 'None existent Sans';
      font-weight: 400;
      src: local('Arial')
    }
    
    div {
      font-family: 'None existent Sans', 'None existent Slab';
    }
    test
    <div style="font-family: 'None existent Sans'">Div content</div>

    This takes for granted you can predict an array of commonly used fonts. At best you are able to replace some undesired font-families (e.g Comic Sans).

    In a perfect world, we would be able to use JS method check() ... From mdn docs:

    Nonexistent fonts If we specify a font that is not in the FontFaceSet and is not a system font, check() returns true, because in this situation we will not rely on any fonts from the set:

    So it's rather useless.