Font-variation-settings Sliderbar only returning :normal

163 Views Asked by At

I am trying to make slider bars that will change the font-variation-settings of a variable font. I am trying to get these sliders to appear dynamically using PHP so that limits my options a tiny bit.

I've edited the post to remove the PHP.

I have the <h1> tag

<h1 class="variableFont" contenteditable="true" >Some Text Here</h1>

I'm using PHP that checks if it's a variable font and then checks which axis the font has then adds the appropriate sliders.

<p>Weight500</p>
<input type="range" min="0" max="1000" value="500" oninput="updatewght(this.value)">

<script>
     function updatewght(newVal){
     
          // Get the current value of font-variation-settings
          var currentSettings = $('.variableFont').css('font-variation-settings');
 
          // Split the current value into an array of variations
          var currentVariations = currentSettings.split(',');

          // Loop through the variations and change the current value
          for (var i = 0; i < currentVariations.length; i++) {
               if (currentVariations[i].indexOf('wght') >= 0) {
                    currentVariations[i] = "'wght' newVal"; // Change the axis value to whatever
               }
          }

          // Join the variations back into a string and set the new value for font-variation-settings
          var newSettings = currentVariations.join(',');
          $('.variableFont').css('font-variation-settings', newSettings);
     }                         

</script>   

The sliders show up like they should, however when I move them it only ever returns

style="font-variation-settings: normal;"

I think the issue lies in where it splits the font-variation-settings and tries to jam it back together, but I can't figure out where I went wrong.

1

There are 1 best solutions below

3
On BEST ANSWER

The main problem in your script - the css font-variation-settings property value is empty unless you set some default values.

var currentSettings = $('.variableFont').css('font-variation-settings');

You would get different vallues if your text element had some initial values like e.g

.variableFont{ 
    font-variation-settings: "wdth" 100, "wght" 400
} 

function updatewght(newVal) {
  // Get the current value of font-variation-settings
  var currentSettings = $(".variableFont").css("font-variation-settings");

  // Split the current value into an array of variations
  var currentVariations = currentSettings.split(",");

  // Loop through the variations and change the current value
  for (var i = 0; i < currentVariations.length; i++) {
    if (currentVariations[i].indexOf("wght") >= 0) {
      currentVariations[i] = `"wght" ${newVal}`; // Change the axis value to whatever
    }
  }

  // Join the variations back into a string and set the new value for font-variation-settings
  var newSettings = currentVariations.join(",");
  $(".variableFont").css("font-variation-settings", newSettings);
}
/* latin */

@font-face {
  font-family: 'Open Sans';
  font-style: normal;
  font-weight: 300 800;
  font-stretch: 75% 100%;
  src: url(https://fonts.gstatic.com/s/opensans/v34/mem8YaGs126MiZpBA-UFVZ0b.woff2) format('woff2');
}

body {
  font-family: 'Open Sans';
  font-size: 3em;
}

.variableFont {
  font-variation-settings: "wdth" 75, "wght" 300
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p class="variableFont">Weight500</p>
<input type="range" data-axis="wght" min="300" max="800" value="300" oninput="updatewght(this.value)">

Another approach: add data attributes to your sliders to specify the current axis name.

This way you need only only initializing function looping through all range sliders to update the new variation settings.

let vfGroups = document.querySelectorAll(".vf-group");

vfGroups.forEach((group) => {
  let textEl = group.querySelector(".preview");
  let axesRangeSliders = group.querySelectorAll("[data-axis]");
  initVariationSliders(axesRangeSliders, textEl);
});


function initVariationSliders(sliders, targetEl) {
  // collect all variations in object
  let variationObj = {};
  sliders.forEach((slider, i) => {
    // apply variation setting
    if (i === sliders.length - 1) {
      updateVariations(slider, targetEl, variationObj);
    }

    // attach event handler
    slider.addEventListener("input", (e) => {
      updateVariations(e.currentTarget, targetEl, variationObj);
    });
  });

  function updateVariations(slider, targetEl, variationObj) {
    // get axes and values of current element
    let value = slider.value;
    let axis = slider.dataset.axis;
    variationObj[axis] = value;

    // convert object to array
    let variation = Object.keys(variationObj).map((key) =>
      [`"${key}"`, +variationObj[key]].join(" ")
    );
    targetEl.style["font-variation-settings"] = variation.join(",");
  }
}
/* latin */
@font-face {
  font-family: 'Open Sans';
  font-style: normal;
  font-weight: 300 800;
  font-stretch: 75% 100%;
  src: url(https://fonts.gstatic.com/s/opensans/v34/mem8YaGs126MiZpBA-UFVZ0b.woff2) format('woff2');

}

@font-face {
  font-family: 'Advent Pro';
  font-style: normal;
  font-weight: 100 900;
  font-stretch: 100% 200%;
  src: url(https://fonts.gstatic.com/s/adventpro/v20/V8mAoQfxVT4Dvddr_yOwhTqtKA.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0300-0301, U+0303-0304, U+0308-0309, U+0323, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}



.preview{
  font-size: 3em;
}

p{
  margin:0;
}

.open-sans{
    font-family:'Open Sans';
}

.advent-pro{
    font-family:'Advent Pro';
}

.variableFont{
}
<div class="vf-group open-sans">
  <p class="preview">Open Sans</p>
  wght: <input type="range" data-axis="wght" min="300" max="800" value="300">
  wdth: <input type="range" data-axis="wdth" min="75" max="100" value="75">
</div>


<div class="vf-group advent-pro">
  <p class="preview">Advent Pro</p>
  wght: <input type="range" data-axis="wght" min="100" max="900" value="300">
   wdth: <input type="range" data-axis="wdth" min="100" max="200" value="100">
</div>