13

UPDATE: Before reading into this post and saying you need more code to replicate the issue, the simple question I am asking is:

"Have you ever had to remove and re-apply a CSS property on an element in order for that style to apply when that property was already on that element and should have been working by default? If so, what was your solution or did you know what was ultimately causing the problem?"

UPDATE 2: I'm not 100% sure but this may only be an issue with the font-size property and it being changed dynamically using Javascript. The CSS for the outer and/or inner elements that are being re-sized in Javascript works as it should, this problem seems to only occur with font sizing, in particular. Perhaps the surrounding HTML's CSS doesn't catch font-size on memory intensive style changes (like our resize function). Just a guess.


The rest of this post is a means to clarify what I am talking about.

This problem might be exclusive to Chrome. To clarify, our app is used internally by our sales team and the project was specced out to focus exclusively on Chrome, both for development and field use. Already, the styling is totally off when opening this in other browsers, since we've only had to create our CSS to be Chrome-compliant (how I got so lucky to land such a position, I don't know, haha).

I've only encountered this issue a few times in my coding career which I believe to be a bug in CSS but could just be a rare bug between Javascript making style changes in the DOM and parent container CSS not adapting to the change due to possible memory constraints or slight processing lag between Javascript applying a style to the HTML and the CSS not updating to accomdate. I think this is an important question as I think every front-end web developer has or will come across this at some point in their career.

Situation

To put it as short as possible, we have a container inside our body that we use Javascript to size to a 16:9 aspect ratio relative to the window size. Took a screenshot of the entire window. As you can see, we have the inner container sizing proportionally inside our browser window (the black area, which is the body). The inner container is where all the content for our app displays:

enter image description here

Our CSS is built using percentages, wherever possible. We built a 'resizeUI' function that's mainly used to change the font-sizes based on the current width/height ratio of the inner screen, though there are other elements in that function that get re-sized too, on window re-size. The window always re-sizes perfectly and anything needing specific sizing based on the inner window's width/height pixel ratio works as expected, with the child elements' percentage-based CSS adjusting appropriately. But....

The Problem

When the browser window is re-sized by clicking and dragging (incremental re-sizing) everything on the page re-sizes perfectly. However, when the window size changes drastically, and instantly, fullscreen (Maximize) to small (Restore Down), or visa versa, the font-sizes in the top menu will change BUT the CSS of the parent li will not adjust to accommodate the new font-size unless I un-check (remove) it's padding attribute and recheck it (add it back in). When I do that, it works fine. The li container really just has a padding:1% and, thus, normally adjusts it's size correctly based on the inner span's size which changes with the font re-sizes.

The parent li should automatically adjust to the change of the inner span font-size. I'm positive of this because the parent li container will automatically re-size itself when I modify the menu's font-sizes or text lengths, on the fly, in the inspector.

Here's what it normally looks like either on load or with incremental window size changes:

enter image description here

And here is what it looks like when I go from a small window size to full-screen using Maximize:

enter image description here

My (hacky) Fix

Only way I've gotten this to work is to remove the padding for the <li> elements at the top of the re-size function, then re-apply it at the bottom of the re-size function AFTER the line that re-sizes the font. However, this works 50% of the time. Only when placing a 100ms timeout at the bottom of the re-size function to re-apply the padding have I gotten it to work 100% of the time now.

To help, here's a very basic code example of what i'm working with. The ul sizes automatically to it's inner elements:

Relevant HTML

<ul>
  <li class="menu-items><span>Item 1</span></li>
  <li class="menu-items><span>Item 2</span></li>
  <li class="menu-items><span>Item 3</span></li>
  <li class="menu-items><span>Item 4</span></li>
  <li class="menu-items><span>Item 5</span></li>
</ul>

Relevant CSS

ul {
  position:absolute;
  top:0;
  right:2%;
  text-align:center;
}
.menu-items {
  padding: 1%;
}

Relevant Javascript

What works about 1/2 the time

function resizeUI(){
  $('.menu-items').css('padding','0');
  //Random other elements being re-sized
  $('.menu-items span').css('font-size', properRatio + "px");
  //More elements being resized
  $('.menu-items').css('padding','1%');
}

Works every time

function resizeUI(){
  $('.menu-items').css('padding','0');
  //Random other elements being re-sized
  $('.menu-items span').css('font-size', properRatio + "px");
  //More elements being re-sized
  setTimeout(function(){  
    $('.menu-items').css('padding','1%');
  }, 100);
}

Ultimate Question

Has anyone else encountered similar issues when working with CSS that should adapt to the re-sizing of an element? I sense it's a memory issue or bug between Javascript and CSS, given that having to set a timeout is the only reliable way I have gotten it to work 100% of the time, and, again, this ONLY occurs on a vast, instant change in window size (Maximize to Restore down, or visa versa) but not on manual, smaller, incremental resizing. Sorry for such a verbose post/question but I have encountered this weird bug a few times before with having to remove and reapply a CSS attribute to get it to work properly and I have no doubt other developers have too.

HaulinOats
  • 3,628
  • 4
  • 21
  • 24
  • Does exactly the same thing happen in all browsers? – Pointy Feb 15 '16 at 17:54
  • 3
    I guess that may another function is overwriting the value. At least in chrome, you can right-click the item and set a break point on `Attributes modification`. Maybe you can use the debugger to check, which functions are modifying the style attribute of this element. – Michael Walter Feb 15 '16 at 17:56
  • 3
    You need to post a minimum code snippet that reproduce the issue, or else all we can do is guess – Asons Feb 15 '16 at 18:02
  • @Pointy I think I need to modify my post to state this is Chrome specific. This is an internal app used by the sales team in our company. They are expected/required to use Chrome, and that is what we test in, exclusively. It has allowed us to focus on a single browser and not have to spend the extra resources for cross-browser compatibility. Opening in Firefox, the app is botched, and I can't even get it to open in IE11. This is likely an issue with Chrome itself, and considering it's what I've always used, personally, for development, that might explain why I've had this problem before. – HaulinOats Feb 15 '16 at 18:17
  • 1
    Let me also recommend to **not** build against a certain browser, build against a standard ... or else you might end up as IE only solutions did, where suddenly nothing works on the latest versions – Asons Feb 15 '16 at 18:31
  • @LGSon Our app code is pretty complex but the menu issue is fairly simple. I updated my post to show just the relevant code. – HaulinOats Feb 15 '16 at 18:34
  • @Brett84c The code you provided doesn't reproduce the issue, which means no one can help you, unless they have the same set up themselves. Also, in my experience, doing CSS stuff with script should be avoided at all cost, as CSS is very good at doing that itself. – Asons Feb 15 '16 at 18:41
  • Have you tried setting a margin on the `span` instead of padding on the `li` ... or make `span` fill the entire `li` (`display: inline-block;width: 100%; height: 100%;`) and use padding on the `span`? – Asons Feb 15 '16 at 18:43
  • Does the timeout of zero milliseconds also work? – Shomz Feb 15 '16 at 18:46
  • Setting margin on the span instead of padding on the li still didn't fix it. I know my code doesn't replicate the issue. I think it's likely a memory issue with Javascript. I'm working with code built by a former developer who used the re-size function to re-size everything. All of MY code in other pages/parts of our app uses CSS percentage-based styling of everything unless JS styling is necessary, mainly only on font re-sizing. – HaulinOats Feb 15 '16 at 18:52
  • Ultimately, this post is really simply asking "have you ever had an issue of having to remove and re-apply a CSS property on an element in order to get it to work? If so, what was your solution or did you know what was ultimately causing the problem?" – HaulinOats Feb 15 '16 at 18:54

2 Answers2

1

The padding is actually working. Each unit (div or whatever you are using) is overlapping the one previous evenly because you are over 100% of the view width in total. They are being built from left to right and when it gets to the end of the max size allowed, they will all equally push over the ones previous. Also padding affects elements inside of the div and will not affect divs outside of itself. So they are all the correct size but you have not established a rule that would stop divs from overlapping. Margin can do that but if they are over 100% of the desired size you will have to deal with over flow in some way. You can try to use auto for padding, but margin may be better. Otherwise you will have to play with the sizes and percentages to make it fit to the max allowed width. Checkout the CSS Box Model here.

  • That still doesn't explain why removing the padding then re-adding it fixes the issue. If everything works fine on initial load or incremental re-sizing, this tells me there's a memory problem in my re-size function or there's a bug in CSS that won't adapt to the size of the spans after the font-size changes, which it does, normally. Honestly, I think this is ultimately just a bug since it only occurs on an instant size change between a very small window and full-screen. – HaulinOats Mar 09 '16 at 18:15
  • Perfect I just read in on of your other responses that everyone using the app has to use chrome. You can use flexbox to solve the issue. Take out the padding and add: `.parentElement{ display: flex; justify-content: center; align-content: center; }` see [this](https://css-tricks.com/snippets/css/a-guide-to-flexbox/) on CSS tricks for more – Clark Ozanne Mar 10 '16 at 00:56
0

Have you ever had an issue of having to remove and re-apply a CSS property on an element in order for that style to apply when it was already there and should have been working by default?

Yes: https://stackoverflow.com/a/34245989/1529630

What was your solution?

Unsetting the styles and resetting them immediately after didn't work, probably because the browser hadn't updated the page yet, and then it detected that I resetted so at the end it did nothing.

Unsetting and resetting in a timeout worked, but caused annoying blinks.

In my case, the solution was removing the element and inserting it back immediately.

window.addEventListener('resize', function() {
  // Force a rerender
  var parent = element.parentNode,
      next = element.nextSibling;
  parent.removeChild(element);
  parent.insertBefore(element, next);
});

Warning: this will force the browser to do layout, paint and composite operations, which is expensive.

Community
  • 1
  • 1
Oriol
  • 274,082
  • 63
  • 437
  • 513
  • Eh, removing and re-adding the elements to the DOM is not an option. The way the DOM and all it's data-attributes and event listeners are being populated and applied, upon load, is rather complex but I was recently tasked with diving into that code to fix menu sizing issues that were revealing themselves when adding new languages. I went in and greatly simplified the HTML while maintaining the menu's functionality while also making the menu size more dynamically. Manually resetting (removing and re-adding) the `padding` attribute works, in my case, the problem lies within... – HaulinOats Feb 15 '16 at 20:24
  • ... re-sizing the fonts in Javascript and the CSS not automatically adapting to the new change. – HaulinOats Feb 15 '16 at 20:25
  • 1
    Why is it not an option? Removing and reinserting the element doesn't remove its even listeners, properties, nor internal states (if that is what's worrying you). Note I'm not replacing the element with a clone, I'm just inserting the same element back. – Oriol Feb 15 '16 at 20:43
  • My current timeout solution is less expensive and simpler, just from a code maintainability standpoint. It works, was just hoping for something less hacky. I appreciate you giving me your solution, just would like to know if anyone figured out what is going on underneath that's causing this issue to begin with. Again, this ONLY happens on major, instant window size changes, not incremental, manual window sizing. I don't even need the timeout on incremental sizing, it's just on big size changes. It's a very weird and rare issue. – HaulinOats Feb 15 '16 at 21:07