Task:
Keep a vertical list of thumb nails. Thumb nails must scale with window dimensions. Thumb nails are contained in a div the dimensions of which are given using vw, vh. On every resize, a Javascript function recomputes width and height of all thumb nails so that a fixed number of them appears in the visible area of the div and is as big as possible. To keep the thumb nails' vertical spacing constant, the height of the visible thumb nails is added up, increased by a factor and assigned to the div's height.
Problem:
When making the window very narrow, vertical space between the thumb nails is getting bigger and bigger. The values calculated for hFit and hTotal (see Javascript code below) seem to be incorrect and lead to unwanted overlay or too big vertical spacing of the thumb nails.
Details:
The entire layout is as follows:
An outmost div (.content-area) controls vertical alignment of the entire control (centered). A child of .content-area (.content-control) controls the layout of the actual list (.content-data) plus a close button (.close-btn-area) that will appear left of that list.
Code:
CSS:
.content-area
{
position: absolute;
left: 2vw;
top: 5vh;
width: 30vw;
height: 90vh;
display: flex;
flex-direction: column;
align-items: start;
justify-content: center;
list-style: none;
opacity: 0.0;
}
.content-control
{
position: relative;
margin: 0 0 0 0;
display: flex;
flex-direction: row;
align-items: start;
justify-content: flex-start;
overflow: hidden;
}
.content-data
{
position: relative;
margin: 0 0 0 0;
padding: 0 0 0 0;
width: auto;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
overflow: hidden;
}
#thumbs-content
{
margin: 1vmin 1vmin 1vmin 1vmin;
height: 78vh;
font-family: 'Alegreya Sans SC', Verdana, sans-serif;
font-variant: small-caps;
overflow: hidden;
color:#404040;
}
.thumb-size
{
margin: 1vmin 0;
width: 16vw;
height: 12vh;
display: flex;
justify-content: center;
align-items: center;
}
.close-btn-area
{
margin: 1vmin 1vmin 1vmin 1vmin;
width: 4vh;
height: 4vh;
display: flex;
align-items: start;
justify-content: flex-start;
cursor: pointer;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-o-user-select: none;
-ms-user-select: none;
user-select: none;
}
.close-btn
{
width: 4vh;
height: 4vh;
border: 0;
}
HTML:
<div class="content-area" id="thumbs-area">
<div class="content-control" id="thumbs-control">
<div class="close-btn-area" id="close-thumbs">
<a><img class="close-btn" id="close-btn-thumbs" src="close-btn-inverted-128x128.png">
</div>
<div class="content-data" id="thumbs-data">
<article id="thumbs-content">
<div class="thumb-size"><img class="thumb" id="thumb1" src="img1.jpg"></div>
<div class="thumb-size"><img class="thumb" id="thumb2" src="img2.jpg"></div>
<div class="thumb-size"><img class="thumb" id="thumb3" src="img3.jpg"></div>
<div class="thumb-size"><img class="thumb" id="thumb4" src="img4.jpg"></div>
<div class="thumb-size"><img class="thumb" id="thumb5" src="img5.jpg"></div>
<div class="thumb-size"><img class="thumb" id="thumb6" src="img6.jpg"></div>
<div class="thumb-size"><img class="thumb" id="thumb7" src="img7.jpg"></div>
<div class="thumb-size"><img class="thumb" id="thumb8" src="im8.jpg"></div>
<div class="thumb-size"><img class="thumb" id="thumb9" src="im9.jpg"></div>
<div class="thumb-size"><img class="thumb" id="thumb10" src="img10jpg"></div>
<div class="thumb-size"><img class="thumb" id="thumb11" src="img11.jpg"></div>
</article>
</div>
</div>
</div>
JavaScript:
const nVisibleThumbs = 6;
var nTopThumb = 0;
var nThumbCount = 11; // simplified; will be computed in the actual code
var nThumbScale = 0.9;
function RecalcThumbsLayout ()
{
var elem = $('#thumbs-content');
var w = elem.width ();
var h = Math.round (elem.height () * nThumbScale);
var hFit = 0;
var wFit = 0;
var hTotal = 0;
for (i = 1; i <= nThumbCount; i = i + 1)
{
var idStr = "#thumb" + i;
var ar = Math.min (1.5, $(idStr).prop ('naturalWidth') / $(idStr).prop ('naturalHeight'));
var ph = Math.round (h / nVisibleThumbs * 0.9);
var pw = Math.round (Math.min (ph * ar, w * 0.9));
ph = Math.floor (pw / ar); // considers portrait format images
$(idStr).css ("width", pw);
$(idStr).css ("height", ph);
hTotal += ph;
if ((i > nTopThumb) && (i <= nTopThumb + nVisibleThumbs))
hFit += ph;
if (wFit < pw)
wFit = pw;
}
wFit *= 1.25; // compensate for scaling above
hFit *= 1.25; // compensate for scaling above
$('#thumbs-data').css ('width', wFit + 'px');
$('#thumbs-data').css ('height', hFit + 'px');
elem.css ('height', hTotal + 'px');
}
Demonstration:
To see the unwanted effect, you can go here: http://www.brockart.de/S, click on "Schmuck" and then horizontally resize the browser window.
Questions:
HTML allows one to reduce vertical space, using something like p { margin-top: -20px; } or such as shown in number of places on the net. For example how-to-reduce-the-space-between-p-tags.
Use the line-height property in CSS to do so. Browsers by default will create a certain amount of space between lines to ensure that the text is easily readable. For example, for 12-point type, a browser will place about 1 point of vertical space between lines.
To give to space between two divs, just add display: flex in the parent element. Then add an justify-content: space-between after adding this you will see a space between two divs.
So <spacer size="32"></spacer> will create 32px of vertical space. You can use the spacer inside of your element to provide more space or between elements.
You might get it without JS and with a simpler HTML and CSS (flexboxes and excessive containers look unnecessary).
Since
Keep a vertical list of thumb nails. ... a fixed number of them appears in the visible area of the div
Horizontal resize should not affect the thumbnails size to maintain the images aspect ratio.
So all we need is to calculate and set image height depending on the desired number of visible thumbnails.
Run the snippet below in fullscreen and resize the window:
.content {
position: absolute;
left: 2vw;
top: 5vh;
height: 90vh;
}
.thumbs {
height: 100%;
padding: 0 1rem;
overflow-y: auto;
}
.thumbs img {
display: block;
box-sizing: border-box;
/*
since we need to fit 6 images,
set img height = 1/6 of the container height
*/
height: 16.667%;
width: auto;
border: solid 1vh transparent;
}
.close-btn {
float: left;
width: .9em;
height: .9em;
border: solid .15em;
border-radius: 55%;
color: #fff;
background: #000;
box-shadow: 0 0 2px #000;
text-align: center;
font: 400 2rem/.9 sans-serif;
}
<div class="content">
<a class="close-btn">×</a>
<div class="thumbs">
<img src="https://picsum.photos/400/200/?1">
<img src="https://picsum.photos/400/200/?2">
<img src="https://picsum.photos/400/200/?3">
<img src="https://picsum.photos/400/200/?4">
<img src="https://picsum.photos/400/200/?5">
<img src="https://picsum.photos/400/200/?6">
<img src="https://picsum.photos/400/200/?7">
<img src="https://picsum.photos/400/200/?8">
<img src="https://picsum.photos/400/200/?9">
<img src="https://picsum.photos/400/200/?0">
<img src="https://picsum.photos/400/200/?a">
<img src="https://picsum.photos/400/200/?b">
</div>
</div>
Replace your .thumb-size
.thumb-size
{
margin: 1vmin 0;
width: 16vw;
height: 12vh;
display: flex;
justify-content: center;
align-items: center;
}
To
.thumb-size
{
margin: 1vmin 0;
width: 16vw;
height: auto;
display: flex;
justify-content: center;
align-items: center;
}
it will be worked as expected
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With