jQuery font size wrong result

Tags: , , ,



I am trying to write a script to help disabled people to read the site. On a button click, I’d like to increase all font-size in my page. However the script sets wrong values. The code is the following:

$('main *').each((index, item) => {
    let current = parseInt($(item).css('font-size'));
    let increased = current * 1.2;

    $(item).css({
        fontSize: increased + 'px'
    });

})

However, it give me back totally wrong increased number. For example when the current font size was 14px sometimes it gives back 26px or 32px or 38px; The current value is get by the css() function, so it doesn’t depend on the css file, it gets the computed value. When I try to log the current and increased value, it is fine. Something goes wrong, when I try to set it to the element.

Answer

Your solution is flawed because your code is going to adjust every element that is nested since you are using * as a selector. Below is a simple example showing how nesting will cause each layer to increase.

$('.main *').each((index, item) => {
    let current = parseInt($(item).css('font-size'));
    let increased = current * 1.2;

    $(item).css({
        fontSize: increased + 'px'
    });

})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="main">
  <p>One</p>
  <div>
    <p>Two</p>
  </div>
  <div>
    <div>
      <p>Three</p>
    </div>
  </div>
  <div>
    <div>
      <div>
        <p>Four</p>
      </div>
    </div>
  </div>
  <div>
    <div>
      <div>
        <div>
          <p>Five</p>
        </div>
      </div>
    </div>
  </div>

So the code selects the element and increases the size. It selects the child, increases it size, selects that child’s child and the next child….. So you are blowing up quickly.

So for your solution it would have to be somehow more restrictive on what you would update. Without knowing the html/css it is hard to know how things have font sizes applied. You would have to do something that would say X element has a font applied. That is not really the best idea.

A bad solution is to set a hardCoded value on every element.

$('.main *').css('font-size', function () { return $(this).css('font-size') });


$("button").on("click", function() {
  $('.main *').each((index, item) => {
    let current = parseInt($(item).css('font-size'));
    let increased = current * 1.2;

    $(item).css({
      fontSize: increased + 'px'
    });

  })
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button>Bigger</button>
<div class="main">
  <p>One</p>
  <div>
    <p>Two</p>
  </div>
  <div>
    <div>
      <p>Three</p>
    </div>
  </div>
  <div>
    <div>
      <div>
        <p>Four</p>
      </div>
    </div>
  </div>
  <div>
    <div>
      <div>
        <div>
          <p>Five</p>
        </div>
      </div>
    </div>
  </div>

A typical solution for this is using REM in CSS so all the values will increase based off a size you set on the html root.

$('button').on('click', function() {
  const html = $('html');
  const current = parseInt(html.css('font-size'));
  const increased = current * 1.2;
  html.css({
    fontSize: increased + 'px'
  });
});
#one { font-size: 1.5rem; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button>bigger</button>
<div class="main">
  <h1>Hello</h1>
  <p id="one">One (styled)</p>
  <div>
    <p>Two</p>
  </div>
  <div>
    <div>
      <p>Three</p>
    </div>
  </div>
  <div>
    <div>
      <div>
        <p>Four</p>
      </div>
    </div>
  </div>
  <div>
    <div>
      <div>
        <div>
          <p>Five</p>
        </div>
      </div>
    </div>
  </div>


Source: stackoverflow