Search code examples
cssfonts

How do I fix font-stretch property to start working


font-stretch property doesn't work at all. Here is my code:

<!DOCTYPE html>
<html>
 <head>
  <meta charset="utf-8">
  <title>font-stretch</title>
  <style>
   p {
    font-size: 5em;
    font-family: 'Myriad Pro';
   }
  </style>
 </head>
 <body>
  <p>
   <span style="font-stretch: ultra-condensed">P</span>
   <span style="font-stretch: extra-condensed">P</span>
   <span style="font-stretch: condensed">P</span>
   <span style="font-stretch: semi-condensed">P</span>
   <span style="font-stretch: normal">P</span>
   <span style="font-stretch: semi-expanded">P</span>
   <span style="font-stretch: expanded">P</span>
   <span style="font-stretch: extra-expanded">P</span>
   <span style="font-stretch: ultra-expanded">P</span>
  </p>
 </body>
</html> 

I've tried many other fonts and problem still exists. Please help


Solution

  • TL;DR: the browser doesn't care about the intrinsic design of a font file

    Adjust @font-face rules

    Although a browser parses font files and can read "intrinsic" style data from its data records it won't automatically map

    • styles (italic, regular)
    • weights (light, regular, bold etc.)
    • font-stretch (condensed, normal, wide etc.)

    So you need to specify all these font-family variants via @font-face rules

    /* Myriad Pro - width: condensed - weight: 200/light - style:regular */
    @font-face {
      font-family: 'Myriad Pro';
      font-style: normal;
      font-weight: light;
      font-stretch: condensed;
      src: url(MyriadProCondensedLight.woff');
    }
    
    /* Myriad Pro - width: condensed - weight: 700/bold- style:italic*/
    @font-face {
      font-family: 'Myriad Pro';
      font-style: italic;
      font-weight: 700;
      font-stretch: 200%;
      src: url(MyriadProExtendedBold.woff');
    }
    

    Basically you can map any font file to any weight,style or width – and also to any font-family name.
    Since the keyword values (e.g thin, condensed, wide etc.) are not self-explanatory I highly recommend to prefer numeric values to organize different weights or widths.

    Google font's UI is currently still preferring a static/single-weight css output.

    But you can manually force the API to output variable font @font-face rules:

    https://fonts.googleapis.com/css2?family=Inconsolata:wdth,wght@50..200,200..900   
    

    It's important to use '..' as a range delimiter – otherwise you'll get a css containing several static woff2 file urls.

    Besides, google's API uses some user agent detection (a.k.a browser sniffing) to provide backwards compatibility (for browsers that don't support variable fonts).
    This makes perfect sense ... unfortunately, this doesn't work very well: some Browsers like Opera (flawlessly supporting VF) will also receive static fonts.
    (This might also apply to other chromium/blink based browsers)

    As a workaround I recommend, to open the above css URL in firefox. The result should look something like this:

    @font-face {
      font-family: 'Inconsolata';
      font-style: normal;
      font-weight: 200 900;
      font-stretch: 50% 200%;
      src: url(https://fonts.gstatic.com/s/inconsolata/v31/QldKNThLqRwH-OJ1UHjlKGlZ5qg.woff2) format('woff2');
    }
    

    Notice the font-weight and font-stretch property values containing 2 values for a range of weights/widths. This is a good indicator, you've retrieved the correct (variable) rules.

    Example: Inconsolata variable

    @font-face {
      font-family: "Inconsolata";
      font-style: normal;
      font-weight: 200 900;
      font-stretch: 50% 200%;
      src: url(https://fonts.gstatic.com/s/inconsolata/v31/QldKNThLqRwH-OJ1UHjlKGlZ5qg.woff2) format("woff2");
    }
    
    body {
      font-size: 36px;
      font-family: sans-serif;
    }
    
    h2 {
      font-size: 0.5em;
      color: red;
    }
    
    p {
      font-family: Inconsolata;
      transition: 0.8s;
    }
    
    .customMap {
      font-family: sans-serif;
    }
    
    @font-face {
      font-family: "Inconsolata2";
      src: url(https://fonts.gstatic.com/s/robotocondensed/v25/ieVl2ZhZI2eCN5jzbjEETS9weq8-19K7DQ.woff2) format("woff2");
      font-stretch: 50%;
    }
    
    @font-face {
      font-family: "Inconsolata2";
      src: url(https://fonts.gstatic.com/s/roboto/v30/KFOjCnqEu92Fr1Mu51TLBCc6CsQ.woff2) format('woff2');
      font-stretch: 200%;
      font-style: normal;
      font-weight: normal;
    }
    
    .customMap {
      font-family: "Inconsolata2";
      font-style: normal;
    }
    <p style="font-family:sans-serif; font-size:12px">Font-stretch: <input type="range" id="fontStretch" value="50" min="50" max="200" step="5"></p>
    <p style="font-family:sans-serif; font-size:12px">Font-weight: <input type="range" id="fontWeight" value="200" min="200" max="900" step="10"></p>
    <p id="variableTest" style="font-stretch:50%" class="inconsolata variableTest">Hamburgefons</p>
    
    <h2>Variable fonts Example</h2>
    
    <p>
      <span style="font-stretch: ultra-condensed">P</span>
      <span style="font-stretch: extra-condensed">P</span>
      <span style="font-stretch: condensed">P</span>
      <span style="font-stretch: semi-condensed">P</span>
      <span style="font-stretch: normal">P</span>
      <span style="font-stretch: semi-expanded">P</span>
      <span style="font-stretch: expanded">P</span>
      <span style="font-stretch: extra-expanded">P</span>
      <span style="font-stretch: ultra-expanded">P</span>
    </p>
    
    <h2>Static fonts Example (custom fonts to widths mapping)</h2>
    <p class="customMap">
      <span style="font-stretch: 50%">g</span>
      <span style="font-stretch: 200%">g</span>
    </p>
    
    
    <script>
      fontStretch.addEventListener('change', (e) => {
        variableTest.style.fontStretch = e.currentTarget.value + '%';
      });
    
      fontWeight.addEventListener('change', (e) => {
        variableTest.style.fontWeight = e.currentTarget.value;
      })
    </script>