0

I am trying to add a class to a specific div based on its width, so it is dynamically added or removed as the overall window (and therefore the div, which has a percentage width) resizes.

I've tried using javascript querySelector and offsetWidth to identify the div, but so far it's not working. My method is inspired by this codepen (which gets the window width, so slightly different from what I'm trying to do).

Here's what I have so far:

   var addWideClass = function() {
     var width = document.querySelector('.v65-productGroup-product').offsetWidth;
     if (width < 141) {
       $('.v65-productGroup-product').removeClass('wide');
     } else if (width >= 415) {
       $('.v65-productGroup-product').addClass('wide');
     };
   };
   $(window).resize(function(){
     addWideClass();
   });
   addWideClass();

What do I need to change to have .wide added to .v65-productGroup-product when .v65-productGroup-product > 414px wide?

LNML
  • 35
  • 6
  • Why not definining classes that regard the viewport? Have a look at https://developer.mozilla.org/en/docs/Web/CSS/Media_Queries/Using_media_queries – schlonzo Jun 05 '19 at 10:00
  • What is working so far? can you console.log() the width and if so are you getting the right number. Check these answers for more on offsetWidth vs clientWidth vs innerWidth vs outerWidth https://stackoverflow.com/a/21064102/1376843 https://stackoverflow.com/a/17845094/1376843 – Paddy Hallihan Jun 05 '19 at 10:06
  • 1
    @schlonzo Because viewport width does not equal element width – yunzen Jun 05 '19 at 11:00
  • @schlonzo: what yunzen said, but also, I can't edit the html in this case so if I'm adding classes and then applying media queries to them, I still have to add them with js ... and I may as well just solve the issue directly, is my thought. – LNML Jun 06 '19 at 07:15

3 Answers3

0

The offsetWidth may be cashed or have missed a reflow. Browser vendors may choose how to handle DOM calculations like offsetWidth.

As you say: the overall window (and therefore the div, which has a percentage width) resizes. You can change this row to detect window width instead of div width:

var width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth || screen.width

Then you can have typical device breakpoints. If you really need it to change when div is 141 and 415 pixels you need to use yor mathematic skills to calculate how wide the window has to be from one of these values added to the rest of widths and procentual factors you know of the neigbouring elements.

0

maybe this pen helps:

https://codepen.io/anon/pen/zQXMoz

I basically modified the pen you referred to and added the functionality you wanted to. change the page size to see the effect.

P.S. in your own code, did you mean:

if (width < 414) {

instead of

if (width < 141) {

?

additionally, if you just want to toggle the class on 414px, then this should suffice:

if (width < 414) {
  // remove class
}
else {
  // add class
}
0

I made this demonstration: See it in full page view and change browser width

"use strict";
console.clear();

const addWideClass = function() {
  Array.from(document.getElementsByTagName('span')).forEach(el => {
    const w = el.offsetWidth
    el.style.setProperty('--w', `'${w}'`);
    if (w < 141) {
      el.classList.remove("wide");
    } else if (w >= 415) {
      el.classList.add("wide");
    }
  })
};

window.addEventListener('resize', addWideClass)
addWideClass()
div {
  display: flex;
}
div span {
  box-sizing: border-box;
  padding: 10px;
  --w: '213232';
}
div span:nth-child(1) {
  flex-grow: 2;
  flex-basis: 0;
  background-color: gold;
}
div span:nth-child(2) {
  flex-grow: 3;
  flex-basis: 0;
  background-color: silver;
}
div span:nth-child(3) {
  flex-grow: 4;
  flex-basis: 0;
  background-color: goldenrod;
}
div span.wide {
  border: 10px solid #000;
}
div span:before {
  content: var(--w);
  display: block;
}
<div>
  <span>Lorem ipsum dolor sit amet consectetur adipisicing elit. Tempora similique vitae accusantium repellat nobis architecto unde, exercitationem soluta placeat voluptatum nostrum beatae tenetur ad deleniti voluptate quia quis officia voluptatem.</span>
  <span>At ex velit eligendi ipsam doloribus doloremque laudantium, minus mollitia dicta quis sit nostrum commodi incidunt autem provident vero! Rem distinctio, optio harum deserunt aperiam corporis. Quod maxime eos porro!</span>
  <span>Quaerat, quo adipisci voluptas dolores odio maxime maiores obcaecati repellendus ducimus a cupiditate placeat, fugiat nostrum distinctio quidem nemo rem error laborum ipsam eos dicta corrupti. Nobis iure suscipit saepe.</span>
</div>

P.S. you might want to consider a debounce on the resize event (I used a second as debounce delay to make the effect more ovious. You would rather want a debounce delay of 100 milliseconds or the like)

"use strict";
console.clear();

const addWideClass = function() {
  Array.from(document.getElementsByTagName('span')).forEach(el => {
    const w = el.offsetWidth
    el.style.setProperty('--w', `'${w}'`);
    if (w < 141) {
      el.classList.remove("wide");
    } else if (w >= 415) {
      el.classList.add("wide");
    }
  })
};

// From: https://davidwalsh.name/javascript-debounce-function
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
function debounce(func, wait, immediate) {
  var timeout;
  return function() {
    var context = this,
      args = arguments;
    var later = function() {
      timeout = null;
      if (!immediate) func.apply(context, args);
    };
    var callNow = immediate && !timeout;
    clearTimeout(timeout);
    timeout = setTimeout(later, wait);
    if (callNow) func.apply(context, args);
  };
};


window.addEventListener('resize', debounce(addWideClass, 1000))
addWideClass()
div {
  display: flex;
}
div span {
  box-sizing: border-box;
  padding: 10px;
  --w: '213232';
}
div span:nth-child(1) {
  flex-grow: 2;
  flex-basis: 0;
  background-color: gold;
}
div span:nth-child(2) {
  flex-grow: 3;
  flex-basis: 0;
  background-color: silver;
}
div span:nth-child(3) {
  flex-grow: 4;
  flex-basis: 0;
  background-color: goldenrod;
}
div span.wide {
  border: 10px solid #000;
}
div span:before {
  content: var(--w);
  display: block;
}
<div>
  <span>Lorem ipsum dolor sit amet consectetur adipisicing elit. Tempora similique vitae accusantium repellat nobis architecto unde, exercitationem soluta placeat voluptatum nostrum beatae tenetur ad deleniti voluptate quia quis officia voluptatem.</span>
  <span>At ex velit eligendi ipsam doloribus doloremque laudantium, minus mollitia dicta quis sit nostrum commodi incidunt autem provident vero! Rem distinctio, optio harum deserunt aperiam corporis. Quod maxime eos porro!</span>
  <span>Quaerat, quo adipisci voluptas dolores odio maxime maiores obcaecati repellendus ducimus a cupiditate placeat, fugiat nostrum distinctio quidem nemo rem error laborum ipsam eos dicta corrupti. Nobis iure suscipit saepe.</span>
</div>
yunzen
  • 32,854
  • 11
  • 73
  • 106