Search code examples
cssreactjsscale

How to use CSS transform: scale(); to fit child div to parent div responsively in react?


I am really stuck. My div contains fixed size divs, texts and images with a lot of pixel based positioning. How can I just wrap them in another div and make them scale to fit the wrapper?

This might be very similar: https://css-tricks.com/scaled-proportional-blocks-with-css-and-javascript/


Solution

  • Using @Gershom's snippet, but keeping aspect ratio

    let scaledWrapper = document.getElementsByClassName('scaled-wrapper')[0];
    
    let applyScaling = scaledWrapper => {
      
      // Get the scaled content, and reset its scaling for an instant
      let scaledContent = scaledWrapper.getElementsByClassName('scaled-content')[0];
      scaledContent.style.transform = 'scale(1, 1)';
      
      let { width: cw, height: ch } = scaledContent.getBoundingClientRect();
      let { width: ww, height: wh } = scaledWrapper.getBoundingClientRect();
      
    //  let scaleAmtX = ww / cw;
    //  let scaleAmtY = wh / ch;
      let scaleAmtX = Math.min(ww / cw, wh / ch);
      let scaleAmtY = scaleAmtX;
      
      
      scaledContent.style.transform = `scale(${scaleAmtX}, ${scaleAmtY})`;
            
    };
    
    applyScaling(scaledWrapper);
    
    // ---- The rest of the code is just for the demonstration ui ----
    let change = () => {
      let w = parseInt(wInp.value);
      let h = parseInt(hInp.value);
      if (!isNaN(w)) scaledWrapper.style.width = `${w}px`;
      if (!isNaN(h)) scaledWrapper.style.height = `${h}px`;
      scaledWrapper.getElementsByClassName('scaled-content')[0].innerHTML = textInp.value;
      applyScaling(scaledWrapper);
    };
    
    let wInp = document.createElement('input');
    wInp.setAttribute('placeholder', 'input parent width in px');
    wInp.addEventListener('input', change);
    wInp.value = '100';
    document.body.appendChild(wInp);
    
    let hInp = document.createElement('input');
    hInp.setAttribute('placeholder', 'input parent height in px');
    hInp.addEventListener('input', change);
    hInp.value = '100';
    document.body.appendChild(hInp);
    
    let textInp = document.createElement('input');
    textInp.setAttribute('placeholder', 'input text content');
    textInp.addEventListener('input', change);
    textInp.value = 'abc';
    document.body.appendChild(textInp);
    .wrapper-wrapper {
      box-sizing: border-box;
      border: solid 2px blue;
      position: relative;
    }
    .scaled-wrapper {
      position: relative;
      width: 100px; height: 100px;
      outline: 1px solid red;
      z-index: 1;
    }
    .scaled-content {
      box-sizing: border-box;
      display: inline-block;
      transform-origin: 0 0;
      background-color: #ffd0d0;
      z-index: -1;
    }
    <div class="wrapper-wrapper">
      <div class="scaled-wrapper">
        <div class="scaled-content">abc</div>
      </div>
    </div>

    scaled maintaining aspect ratio