I have a centered flexbox parent div, #con, with % width, which has an image(s)-containing div (.block) sandwiched between two padded text divs (#info and #links). How can I force .block img to be a square with side length equal to #con‘s width with JS or CSS? .block could contain 1×1=1 images, 2×2=4 images, etc; thus, background-image is not an option. Imitating the solution here only seems to work if I replace con.width() in the JS with a specific value (e.g. 300px, as shown here with this placeholder image), which is unideal.
var con = $("#con");
$(".block").css("height", con.width(), "width", con.width());
body {
font-size:1rem;
text-align:center;
margin:0;
height:100vh;
display: flex;
align-items: center;
justify-content: center;
overflow:hidden;
}
#con {
width:50%;
max-width:300px;
display:flex;
flex-flow:row wrap;
justify-content:center;
margin:5rem auto;
border:1px solid black;
}
.block {width:100%; overflow:hidden; background:black;}
.block img {
position: relative;
top: 0;
bottom: 0;
left: 0;
right: 0;
object-fit: cover;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<div id="con">
<div id="info">...</div>
<div class="block"><img src="https://dbdzm869oupei.cloudfront.net/img/vinylrugs/preview/60150.png"></div>
<div id="links">...</div>
</div>
>Solution :
You don’t need JS for this: just use aspect-ratio: 1 to force a square aspect ratio. You might want to add display: block to ensure the <img> is not displayed inline (which is the default) as well. See proof-of-concept below:
body {
font-size: 1rem;
text-align: center;
margin: 0;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
#con {
width: 50%;
max-width: 300px;
display: flex;
flex-flow: row wrap;
justify-content: center;
margin: 5rem auto;
border: 1px solid black;
}
.block {
width: 100%;
overflow: hidden;
background: black;
}
.block img {
display: block;
object-fit: cover;
width: 100%;
aspect-ratio: 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<div id="con">
<div id="info">...</div>
<div class="block"><img src="https://dbdzm869oupei.cloudfront.net/img/vinylrugs/preview/60150.png"></div>
<div id="links">...</div>
</div>
If you want to support browsers that do not have aspect-ratio support, you can use a combination of a pseudo-element + padding-bottom hack to set a fixed aspect ratio instead:
body {
font-size: 1rem;
text-align: center;
margin: 0;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
overflow: hidden;
}
#con {
width: 50%;
max-width: 300px;
display: flex;
flex-flow: row wrap;
justify-content: center;
margin: 5rem auto;
border: 1px solid black;
}
.block {
width: 100%;
overflow: hidden;
background: black;
position: relative;
}
.block::before {
width: 100%;
padding-bottom: 100%;
content: '';
display: block;
}
.block img {
display: block;
object-fit: cover;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.7/jquery.min.js"></script>
<div id="con">
<div id="info">...</div>
<div class="block"><img src="https://dbdzm869oupei.cloudfront.net/img/vinylrugs/preview/60150.png"></div>
<div id="links">...</div>
</div>