Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URLs added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Auto Save

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                <main>
  <h1>Variable Font Demo</h1>
  
  <p>
    This expirement is meant to allow a reader to play around with assorted settings for a typeface to potentially make it easier to read. In particular, I am using this as the first step in exploring the kinds of font traits an author can tweak to make content easier to read for users with dyslexia.
  </p>
  
  <p>
    This pen is for my post <cite><a href="http://adrianroselli.com/2018/08/variable-fonts-and-dyslexia.html">Variable Fonts and Dyslexia</a></cite>. Go read it to understand how it can help users with dyslexia.
  </p>
  
  <p>
    The font is <a href="https://github.com/Manuel87/NobotoFlex">Noboto Flex</a>. I am not using all the features of the font as some of them do not appear to contribute directly to readability. Chrome/Blink, Edge browsers only.
  </p>
  
  <h2>Generic Text from Wikipedia</h2>

  <p>
    OpenType variable fonts are an adaptation of Apple's TrueType GX font variations to OpenType, with integration into key aspects of the OpenType format including OpenType Layout tables and both TrueType and CFF glyph outline formats. It also surpasses
    TrueType GX by providing better interoperability between different fonts and between variable fonts and font-formatting specification such as are found in Cascading Style Sheets. The technology allows software to access any design instance for a continuous
    range of designs defined within the font. When a specific design instance has been selected, the glyph outlines or other data values for that design instance are computed as font data is being processed during text layout and rasterization.
  </p>
  <p>
    The technology uses interpolation and extrapolation mechanisms that have been supported in font-development tools and used by font designers for many years. In that paradigm, the font designer creates a variable design, but then chooses specific instances
    to generate as static, non-variable fonts that get distributed to customers. With variable fonts, however, the font produced and distributed by the font designer can have built-in variability, and the interpolation mechanisms can now be built into
    operating systems and Web browsers or other applications, with specific design instances selected at time of use.
  </p>
  <p>
    One of the key benefits of the technology is that it can significantly reduce the combined size of font data whenever multiple styles are in use. On the Web, this may allow a site to use more font styles while at the same time reducing page load times.
    A further benefit is that it give access to a continuous range of style variations, which can provide benefits for responsive design.
  </p>
  <p>
    The technology has been compared to Adobe's multiple master fonts (MM fonts) technology, also from the 1990s, which used on-the-fly generation of font designs from master files by interpolation and extrapolation. Multiple master fonts, however, required
    the user to generate a specific "instance" of the font for particular variation-axis values before it could be used. This is not required for OpenType variable fonts, however: named or arbitrary design instances can be selected and used on demand.
  </p>
</main>

<aside>
  <form id="FontToggle">
    <h2>Font Settings <button type="button" aria-label="Reset all." onclick="changeAxis('WGHT','140','wght',1);changeAxis('SPAC','80','SPAC',1);changeAxis('HEIG','400','HEIG',1);changeAxis('ASCE','600','ASCE',1);changeAxis('DESC','600','DESC',1);changeAxis('DIAC','0','DIAC',1);changeAxis('MONO','0','MONO',1);changeAxis('CURV','0','CURV',1);this.focus();">&#8634;</button></h2>
    <p>
      <label for="WGHT">Weight <span aria-hidden="true">(currently <output for="WGHT" form="FontToggle" id="WGHTVal">140</output>)</span>:</label>
      <span>
        <span>54</span>
        <input type="range" id="WGHT" step="1" min="54" max="322" value="140" aria-valuemin="54" aria-valuemax="322" aria-valuenow="140" oninput="changeAxis(this.id,value,'wght');">
        <span>322</span>
        <span><button type="button" aria-label="Reset weight." onclick="changeAxis('WGHT','140','wght',1);">&#8634;</button></span>
      </span>
    </p>
    <p>
      <label for="SPAC">Spacing / tracking <span aria-hidden="true">(currently <output for="SPAC" form="FontToggle" id="SPACVal">80</output>)</span>:</label>
      <span>
        <span>0</span>
        <input type="range" id="SPAC" step="1" min="0" max="200" value="80" aria-valuemin="0" aria-valuemax="200" aria-valuenow="80" oninput="changeAxis(this.id,value,'SPAC');">
        <span>200</span>
        <span><button type="button" aria-label="Reset spacing / tracking." onclick="changeAxis('SPAC','80','SPAC',1);">&#8634;</button></span>
      </span>
    </p>
    <p>
      <label for="HEIG">Height <span aria-hidden="true">(currently <output for="HEIG" form="FontToggle" id="HEIGVal">400</output>)</span>:</label>
      <span>
        <span>165</span>
        <input type="range" id="HEIG" step="1" min="165" max="456" value="400" aria-valuemin="165" aria-valuemax="456" aria-valuenow="400" oninput="changeAxis(this.id,value,'HEIG');">
        <span>456</span>
        <span><button type="button" aria-label="Reset height." onclick="changeAxis('HEIG','400','HEIG',1);">&#8634;</button></span>
      </span>
    </p>
    <p>
      <label for="ASCE">Ascenders <span aria-hidden="true">(currently <output for="ASCE" form="FontToggle" id="ASCEVal">600</output>)</span>:</label>
      <span>
        <span>456</span>
        <input type="range" id="ASCE" step="1" min="456" max="1000" value="600" aria-valuemin="456" aria-valuemax="1000" aria-valuenow="600" oninput="changeAxis(this.id,value,'ASCE');">
        <span>1000</span>
        <span><button type="button" aria-label="Reset ascenders." onclick="changeAxis('ASCE','600','ASCE',1);">&#8634;</button></span>
      </span>
    </p>
    <p>
      <label for="DESC">Descenders <span aria-hidden="true">(currently <output for="DESC" form="FontToggle" id="DESCVal">600</output>)</span>:</label>
      <span>
        <span>456</span>
        <input type="range" id="DESC" step="1" min="456" max="1000" value="600" aria-valuemin="456" aria-valuemax="1000" aria-valuenow="600" oninput="changeAxis(this.id,value,'DESC');">
        <span>1000</span>
        <span><button type="button" aria-label="Reset descenders." onclick="changeAxis('DESC','600','DESC',1);">&#8634;</button></span>
      </span>
    </p>
    <p>
      <label for="DIAC">Diacritics distance <span aria-hidden="true">(currently <output for="DIAC" form="FontToggle" id="DIACVal">0</output>)</span>:</label>
      <span>
        <span>0</span>
        <input type="range" id="DIAC" step="1" min="0" max="100" value="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" oninput="changeAxis(this.id,value,'DIAC');">
        <span>100</span>
        <span><button type="button" aria-label="Reset diacritics distance." onclick="changeAxis('DIAC','0','DIAC',1);">&#8634;</button></span>
      </span>
    </p>
    <p>
      <label for="MONO">Monospace <span aria-hidden="true">(currently <output for="MONO" form="FontToggle" id="MONOVal">0</output>)</span>:</label>
      <span>
        <span>0</span>
        <input type="range" id="MONO" step="1" min="0" max="100" value="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" oninput="changeAxis(this.id,value,'MONO');">
        <span>100</span>
        <span><button type="button" aria-label="Reset monospace." onclick="changeAxis('MONO','0','MONO',1);">&#8634;</button></span>
      </span>
    </p>
    <p>
      <label for="CURV">Curvature <span aria-hidden="true">(currently <output for="CURV" form="FontToggle" id="CURVVal">0</output>)</span>:</label>
      <span>
        <span>0</span>
        <input type="range" id="CURV" step="1" min="0" max="100" value="0" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" oninput="changeAxis(this.id,value,'CURV');">
        <span>100</span>
        <span><button type="button" aria-label="Reset curvature." onclick="changeAxis('CURV','0','CURV',1);">&#8634;</button></span>
      </span>
    </p>
    <p>
      <a href="https://s.codepen.io/aardrian/debug/yEZvpr" target="_top">Variable Font Demo Using Amstelvar Alpha</a>
    </p>
  </form>
</aside>
              
            
!

CSS

              
                :root {
  --page-bg: #eee;
}

/* FF Meta Variable Demo Font */
@font-face {
  font-family: "Noboto Flex";
  src: url("https://s3-us-west-2.amazonaws.com/s.cdpn.io/2729/NobotoFlex-VF.ttf")
    format("truetype");
}

body {
  background-color: var(--page-bg);
  font-size: 125%;
  color: #333;
  font-family: "Noboto Flex", sans-serif;
  padding: 0;
  margin: 0;
}

main, aside {
  display: block;
  box-sizing: border-box;
  width: 90%;
  max-width: 38em;
  margin: 1em auto;
  padding: 1em 2em;
  line-height: 1.5;
  color: #333;
  background-color: rgba(255, 255, 255, 0.7);
  border-radius: 0.5em;
  /*   font-variation-settings: "wght" 400, "ital" 1; */
}

aside {
  max-width: 20em;
  padding: 0;
  background-color: transparent;
}

h1, h2 {
  font-weight: 600;
}

form {
  font-family: sans-serif;
  font-size: 90%;
  background-color: rgba(255, 255, 255, 0.7);
/*   background-color: var(--page-bg); */
/*   background-image: linear-gradient(to bottom, #f0f0f0, var(--page-bg)); */
  border-radius: 0.2em;
  padding: 1em;
}

input,
button,
textarea,
select {
  font-size: 100%;
  color: #333;
  font-family: "FF Meta VF", sans-serif;
}

form > h2 {
  display: flex;
  align-items: flex-start
}

input[type="range"] {
  width: calc(100% - 4.3em);
  width: 80%;
}

form p {
  margin-top: 2em;
}

form p:first-child {
  margin-top: 0;
}

form p:last-child {
  margin-bottom: 0;
}

form p > span {
  display: flex;
  justify-content: space-between;
}

form p > span > span {
  font-size: 85%;
}

form button {
  background-color: transparent;
  padding: 0.25em 0.5em;
  margin-left: 0.5em;
  border: none;
  border-radius: 50%;
}

form button:focus,
form button:hover {
  color: #eee;
  background-color: #333;
  outline: none;
}

@media screen and (min-width: 50em) {
  body {
    display: grid;
    grid-template-columns: 2fr 1fr;
    grid-gap: 0;
  }
}

/* The animation */

@keyframes TOOLTIP {
  from {
    bottom: 1em;
    background-color: rgba(0,0,0,0);
    border: .05em solid rgba(255,255,255,0);
    color: rgba(255,255,255,0);
    box-shadow: 0 0 0 rgba(0,0,0,1);
  }
  to {
    bottom: 2em;
    background-color: rgba(0,0,0,.85);
    border: .05em solid rgba(255,255,255,1);
    color: rgba(255,255,255,1);
    box-shadow: .15em .15em .5em rgba(0,0,0,1);
  }
}

/* Style for the tool-tip */

button[aria-label] {
  position: relative;
}

button[aria-label]:focus::after,
button[aria-label]:hover::after {
  position: absolute;
  display: block;
  z-index: 1;
  bottom: 2em;
  right: 0;
  width: 6em;
  max-width: 12em;
  padding: .5em .75em;
  border: .05em solid rgba(255,255,255,1);
  border-radius: .2em;
  box-shadow: .15em .15em .5em rgba(0,0,0,1);
  content: attr(aria-label);
  background-color: rgba(0,0,0,.85);
  color: rgba(255,255,255,1);
  font-size: .8rem;
  text-align: left;
  animation: TOOLTIP .1s ease-out 1;
}
              
            
!

JS

              
                var pageMain = document.querySelector('main');
var wghtVal = '"wght" 140';
var spacVal = '"SPAC" 80';
var heigVal = '"HEIG" 400';
var asceVal = '"ASCE" 600';
var descVal = '"DESC" 600';
var diacVal = '"DIAC" 0';
var monoVal = '"MONO" 0';
var curvVal = '"CURV" 0';
setStyles();

function setStyles() {
  pageMain.setAttribute('style','font-variation-settings: ' + wghtVal + ', ' + spacVal + ', ' + heigVal + ', ' + asceVal + ', ' + descVal + ', ' + diacVal + ', ' + monoVal + ', ' + curvVal + ';');
}

function changeAxis(eID,num,axis,fldReset) {
  document.querySelector('#' + eID + 'Val').value = num;
  document.querySelector('#' + eID).setAttribute('aria-valuenow',num);
  tmpVal = '"' + axis + '" ' + num;
  // Open to another approach that allows me to dump eval
  // eval(axis.toLowerCase() +"Val  = tmpVal");
  // Thanks to Aaron Smith for the non-eval fix
  // https://twitter.com/basiphobe/status/1013801568360189952
  new Function(axis.toLowerCase() +"Val  = tmpVal")();
  setStyles();
  if (fldReset == '1') {
    document.querySelector('#' + eID).value = num;
    document.getElementById(eID).focus();
  }
}

              
            
!
999px

Console