Resync "offsetWidth" value on browser resize
P粉463811100
P粉463811100 2024-03-29 17:24:18
0
1
470

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粉463811100
P粉463811100

reply all(1)
P粉920835423

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.

Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template