search

Home  >  Q&A  >  body text

Resync "offsetWidth" value on browser resize

I have a horizontal scrolling div with several sub-items. Depending on the width, subitems may be cropped. So you might end up with 4 and 1/2 visible items. Therefore, I use Javascript to force the width to evenly distribute the children.

I used Javascript to detect the width of the .palette and divided it by the number of items I wanted to display (minus the margins) and applied it to each .swatch . Not sure if there's a better/easier way?

If this is the solution, I need some help making it more responsible so that it updates when the window is resized.

  1. I want offsetWidth to update on resize so that the width updates.
  2. Is it possible to use matchMedia to use different values ​​above certain "breakpoints"? This part works!

let palette = document.querySelector('.palette');
let paletteWidth = palette.offsetWidth;
let swatch = document.querySelectorAll('.swatch')

swatch.forEach((item) => {
    if (window.matchMedia("(min-width: 700px)").matches) {
    item.style.width = (paletteWidth - 40) / 5 + "px";
    } else {
    item.style.width = (paletteWidth - 30) / 4 + "px";
    }
});

const handleResize = () => {
    let paletteWidth = palette.offsetWidth;
};

window.addEventListener('resize', handleResize);
.p-card {
  background: #eee;
  box-sizing: border-box;
  display: flex;
  flex-shrink: 0;
  overflow: hidden;
  padding: 30px 15px;
  max-width: 50%;
}

.palette {
  display: flex;
  overflow-x: scroll;
}

.palette__inner {
  display: flex;
  overflow-x: scroll;
  scroll-snap-type: x mandatory;
  scrollbar-width: none; /* Firefox */
  -ms-overflow-style: none; /* IE and Edge */
}

.palette__inner::-webkit-scrollbar {
  display: none;
}

.palette__group {
  display: flex;
  flex-direction: column;
}

.palette__title {
  font-family: "Arial", sans-serif;
  font-size: 11px;
  font-weight: normal;
  margin: 0 10px 10px 0;
  padding: 0;
  position: sticky;
  align-self: flex-start;
  left: 0;
}

.palette__swatches {
  display: flex;
}

.swatch {
  background: red;
  display: flex;
  height: 20px;
  margin-right: 10px;
  scroll-snap-align: start;
  width: 40px;
}
<div class="p-card">

  <div class="palette">
    <div class="palette__inner">
    
       <div class="palette__group">
        <h4 class="palette__title">Classic</h4>
        <div class="palette__swatches">
          <div class="swatch" style="background: red;"></div>
          <div class="swatch" style="background: red;"></div>
          <div class="swatch" style="background: red;"></div>
          <div class="swatch" style="background: red;"></div>
          <div class="swatch" style="background: red;"></div>
          <div class="swatch" style="background: red;"></div>
        </div>    
      </div>
      
      <div class="palette__group">
        <h4 class="palette__title">Matte</h4>
        <div class="palette__swatches">
          <div class="swatch" style="background: blue;"></div>
          <div class="swatch" style="background: blue;"></div>
          <div class="swatch" style="background: blue;"></div>
          <div class="swatch" style="background: blue;"></div>
          <div class="swatch" style="background: blue;"></div>
          <div class="swatch" style="background: blue;"></div>
        </div>     
      </div>
      
      <div class="palette__group">
        <h4 class="palette__title">Glimmer</h4>
        <div class="palette__swatches">
          <div class="swatch" style="background: green;"></div>
          <div class="swatch" style="background: green;"></div>
          <div class="swatch" style="background: green;"></div>
          <div class="swatch" style="background: green;"></div>
          <div class="swatch" style="background: green;"></div>
          <div class="swatch" style="background: green;"></div>
        </div>  
      </div>

    </div>
  </div>

</div>

P粉463811100P粉463811100287 days ago472

reply all(1)I'll reply

  • P粉920835423

    P粉9208354232024-03-30 15:55:14

    The idea is that in your resize callback function, you are just updating the width of the parent element (.palette), not the width of the child element (. swatch).

    Adopt new JS code:

    let palette = document.querySelector('.palette');
    let swatchs = document.querySelectorAll('.swatch')
    
    function setSwatchWidth(n = 5) {
      let paletteWidth = palette.offsetWidth;
      swatchs.forEach((swatch) => {
        swatch.style.width = (
          paletteWidth - (n-1) * 10
        ) / n + "px";
      });
    }
    onload = () => setSwatchWidth();
    onresize = () => setSwatchWidth();
    

    Bonus: I made the function more general so that you can choose how many children you want in the sliding window.

    reply
    0
  • Cancelreply