7

How can I resize a div to be the largest possible square within its container using CSS? If it is not possible with CSS, how can it be done with JavaScript?

If the container has height > width I would like the size of the square to width x width. If the container has width > height I would like the size the square to be height x height.

When the dimensions of the container changes the dimensions of the child should adjust accordingly.

I found this answer to be helpful to maintain the aspect ratio of the child. This approach doesn't work when the width of the container is larger than the height as the child overflows the parent as demonstrated in the following snippet.

.flex {
  display: flex;
}

.wide,
.tall {
  flex: none;
  border: 3px solid red;
}

.wide {
  width: 150px;
  height: 100px;
}

.tall {
  width: 100px;
  height: 150px;
}

div.stretchy-wrapper {
  width: 100%;
  padding-bottom: 100%;
  position: relative;
  background: blue;
}

div.stretchy-wrapper>div {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  color: white;
  font-size: 24px;
  text-align: center;
}
<div class="flex">
  <div class="wide">
    <div class="stretchy-wrapper">
      <div>Wide container</div>
    </div>
  </div>
  <div class="tall">
    <div class="stretchy-wrapper">
      <div>Tall container</div>
    </div>
  </div>
</div>
Community
  • 1
  • 1
Sean Kuhlman
  • 502
  • 3
  • 13
  • You can do size calculations in CSS (https://developer.mozilla.org/en-US/docs/Web/CSS/calc), but you won't be able to detect size changes of an element, you would need JS for that because you're basically asking for conditions to be met before something happens and CSS doesn't have that sort of logic. – Waxi Feb 22 '17 at 17:55
  • Which div you want it to be square? what's wrong with your current example? – Stickers Feb 22 '17 at 18:03
  • I want the div descendant (blue box) of .stretchy-wrapper to be square, which it is. In the example, the blue box in the wide container overflows the parent which you can see via the border. – Sean Kuhlman Feb 22 '17 at 18:06
  • 1
    You might be able to use `vmin` https://jsfiddle.net/mkfLjmgz/ but not sure what your real case is. – Stickers Feb 22 '17 at 18:16
  • By giving us the real case we might be able to suggest a proper CSS-based solution – Asons Feb 22 '17 at 18:17
  • In a flex child that can grow or shrink I want to display a 2x2 grid of images drawn on separate canvases. I want the canvas to be square because the images are square. – Sean Kuhlman Feb 22 '17 at 18:24
  • @Pangloss Just saw your solution after posting mine, post it and you have my vote :) – Asons Feb 23 '17 at 11:32
  • Question edited to request a JavaScript solution. – Sean Kuhlman Feb 23 '17 at 21:49
  • I ended up using [Resize Observer](http://rawgit.com/WICG/ResizeObserver/master/index.html) via [this polyfill](https://github.com/que-etc/resize-observer-polyfill) – Sean Kuhlman Feb 27 '17 at 16:37
  • May I ask why use a 2.6kb polyfill when 18 lines of script does the same job? – Asons Mar 01 '17 at 14:43
  • I need to adjust the size when a large panel is added to the page and the size of the image container changes. Solutions here are on window resize, which I assume means the whole browser window. – Sean Kuhlman Mar 03 '17 at 17:35

1 Answers1

0
  • Get width and height of all .stretchy-wrapper and parent of the same using map().
  • Now using a for loop assign max value to it parent.
  • Then $(window).resize call resizeDiv function whenever browser window size changes.

$(document).ready (function () {
  function resizeDiv () { 
    var stretchyWrapper = $(".stretchy-wrapper"),
      sWrapperWidth = stretchyWrapper.map (function () {
        return $(this).width ();
      }),
      sWrapperHeight = stretchyWrapper.map (function () {
        return $(this).height ();
      }),
      container = stretchyWrapper.map (function () {
        return $(this).parent ();
      });
    
    for (var i in container) {
      var maxVal = Math.max (sWrapperWidth[i], sWrapperHeight[i]);
      $(container[i]).css ({"width": maxVal, "height": maxVal});
    }
  }
  resizeDiv ();
  
  $(window).resize (function () {
    resizeDiv ();
  });
});
.flex {
  display: flex;
}

.wide,
.tall {
  flex: none;
  border: 3px solid red;
}

.wide {
  width: 150px;
  height: 100px;
}

.tall {
  width: 100px;
  height: 150px;
}

div.stretchy-wrapper {
  width: 100%;
  padding-bottom: 100%;
  position: relative;
  background: blue;
}

div.stretchy-wrapper>div {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  color: white;
  font-size: 24px;
  text-align: center;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="flex">
  <div class="wide">
    <div class="stretchy-wrapper">
      <div>Wide container</div>
    </div>
  </div>
  <div class="tall">
    <div class="stretchy-wrapper">
      <div>Tall container</div>
    </div>
  </div>
</div>