1

I made a function to match the width of some elements in a loop where they will expand themselves up to the maximum wide element.

// Function: Match width
var _so20170704_match_width = function( item ) {
    var max_item_width = 0;

    item.each(function(index) {
        max_item_width = Math.max( max_item_width, parseInt( $(this).width() ) );
    });

    // might not necessary
    // but taking time, to keep the elements' default width intact
    // while looping through 'em
    setTimeout(function() {
        item.width(max_item_width);
    }, 100);
}

I called it like below:

_so20170704_match_width( $('.match-width') );

It's working just as expected.

Problem

Problem is, not all the page refresh is okay. On some page refreshes the .width() somehow behaving like it's taking the .outerWidth() or like so. Because the set width's working a bit wider.

With a console.log($(this).width()) and console.log(max_item_width) the values I got are like below:

+====================+=======+
|                ×   |   ✓   |
+====================+=======+
| this_item:    177  |  152  |
| max_width:    177  |  152  |
+--------------------+-------+
| this_item:    174  |  150  |
| max_width:    177  |  152  |
+--------------------+-------+
| this_item:    229  |  196  |
| max_width:    229  |  196  |
+--------------------+-------+
| this_item:    265  |  232  |
| max_width:    265  |  232  |
+====================+=======+
| max_width:    265  |  232  |
+====================+=======+

Here, × denotes "Not working width identification", and denotes "Working width identification".

Why the .width() is varying on the same element on some of the page refresh? If I press Ctrl + F5 to clear cache and refresh, it's a ×. And after that, if I continuously refresh the page with F5 only, it's a . I kept the page idle for some time, then I pressed F5, but it's a ×.

Why?

What I tried

It's even behaving the same whether I change the calculation to a manual one:

if( parseInt( $(this).width() ) > max_item_width ) {
    max_item_width = parseInt( $(this).width() );
}

And I also took time setting the width by replacing 100 with 1000, but the behavior is same.

Edit: Fiddle

jQuery(document).ready(function($) {

  // Function: Match width
  var _so20170704_match_width = function(item) {
    var max_item_width = 0;

    item.each(function(index) {
      max_item_width = Math.max(max_item_width, parseInt($(this).width()));
    });

    // might not necessary
    // but taking time, to keep the elements' default width intact
    // while looping through 'em
    setTimeout(function() {
      item.width(max_item_width);
    }, 100);
  }

  _so20170704_match_width($('.package-title'));
  
});
*,
 :after,
 :before {
  box-sizing: border-box;
}

body {
  font-family: 'Roboto Condensed', Arial, Helvetica, sans-serif;
  font-size: 14px;
  line-height: 1.428571429;
  color: #333;
}

h2 {
  margin-top: 20px;
  margin-bottom: 10px;
  font-weight: 500;
  line-height: 1.1;
}

.package-title {
  color: #fff;
  background-color: #414142;
  border: 1px solid #fed307;
  border-radius: 10px;
  padding: 1px 15px 13px;
  display: inline-block;
  position: relative;
  font-size: 28px;
  z-index: 9;
}

.package-subtitle {
  display: block;
  position: absolute;
  bottom: 0;
  left: 100px;
  padding: 1px 5px;
  font-size: 14px;
  background-color: #fed307;
  color: #414142;
  font-family: 'Roboto Condensed', Arial, Helvetica, sans-serif;
  font-weight: 400;
}
<link href="https://fonts.googleapis.com/css?family=Roboto+Condensed|Roboto:700" rel="stylesheet"> 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<article class="package-holder">
  <h2 class="package-title">Package 1 Title<span class="package-subtitle">Package 1 Subtitle</span></h2>
</article>

<article class="package-holder">
  <h2 class="package-title">Package 2<span class="package-subtitle">Package 2 Subtitle</span></h2>
</article>

<article class="package-holder">
  <h2 class="package-title">Package 3 Ttl<span class="package-subtitle">Package 3 Subtitle</span></h2>
</article>

<article class="package-holder">
  <h2 class="package-title">Package 4 Title Larger<span class="package-subtitle">Package 4 Subtitle</span></h2>
</article>

Suspect: Embedded Font

While making the fiddle, I suspected that, the font embedding might causing the issue. I tried, disabling all the @font-face declarations in my code, and then when I's refreshing (by any ways) it's performing perfect.

So the issue noted is:
On cache clear the font embed refreshes itself and the jQuery function detects the widths with default fonts (width: 265 confirmed with default font). But then the condensed embedded font loaded up, and the width shrunken a bit. And that's causing the issue.

Mayeenul Islam
  • 4,532
  • 5
  • 49
  • 102

1 Answers1

0

Okay, while making the Fiddle after the suggestion of @MehulJoshi, I suspected that, the embedded condensed font's causing the issue. So I's looking for a way to check whether all the fonts are loaded or not.

With the help of this StackOverflow thread I changed the following line of code:

_so20170704_match_width( $('.match-width') );

with the code below:

document.fonts.ready.then(function () {
    _so20170704_match_width( $('.match-width') );
});

Please read the attached SO thread before using this. It's a new feature, and works Chrome 35+ and Firefox 41+.

The way to solve the issue is:

  • When all the embedded fonts are ready (this is crucial)
  • Check for widths
  • Get the max width
  • Set the max width
Mayeenul Islam
  • 4,532
  • 5
  • 49
  • 102