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 reputes 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 puted 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; // pensate for scaling above
hFit *= 1.25; // pensate 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: , click on "Schmuck" and then horizontally resize the browser window.
Questions:
- What do I need to change in the Javascript to make this work?
- Is there a more elegant way to do this with css / html only?
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 reputes 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 puted 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; // pensate for scaling above
hFit *= 1.25; // pensate 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:
- What do I need to change in the Javascript to make this work?
- Is there a more elegant way to do this with css / html only?
- 1 Yeah, in my opinion you are going at this the wrong way. Your having that weird spacing because the .thumb-size divs are not scaling in ratio with their content. You want your JS doing the minimum possible and having CSS do the rest. – Matthew Brent Commented Feb 20, 2018 at 20:59
-
2
Get rid of css height from
thumb-size
class – Munim Munna Commented Feb 21, 2018 at 1:58 - 1 There is no "Schmuck" on that page, the link redirects to homepage – Munim Munna Commented Feb 22, 2018 at 18:39
- Munim Munna, I had changed the location. The link has been fixed. Your reply is part of the solution, although not the entire solution. Anyway, it has led me to the required fixes. So I would like to give the 50 rep to you, but you need to create a full reply here to allow me to do that, and not just a ment to my question. – Razzupaltuff Commented Feb 24, 2018 at 23:46
- Highly suggest looking into CSS Grid and CSS Flexbox. They are, quite literally made for this sort of thing – TheCrzyMan Commented Mar 2, 2018 at 13:41
4 Answers
Reset to default 2 +25You 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
You can use height in terms of percentages (%) so that the child elements will be aligned with respect to parent height. You no need to use JavaScript, you can use pure CSS to make this work.
With the help of some ments here which didn't provide the full solution, but gave me an idea how to create it, I could fix my problem. I am posting an answer to my own question here so that I can leave my question unmodified and highlight the required changes.
There were two related problems:
- Adjusting the thumb nail size to the document size
- Preserving the vertical spacing between the thumb nails (initially, when making the browser window very narrow, the list showed more than the desired amount of thumb nails)
So I simply had to change the CSS as follows:
Make vertical spacing of the thumb nails depend on vh and not vmin (this was a facepalm at myself when I figured that, because that is actually pretty obvious):
.thumb-size { margin: 1vh 1vh; display: flex; justify-content: center; align-items: center; }
Specify thumb nail size in the thumb nail class and simply make it relative by using vh:
.thumb { width: 15vh; height: auto; border: 2px solid #404040; }
With these changes, I could get pletely rid of the Javascript code I tried to properly format the thumb nail list with. The page now quite nicely scales with window dimensions.
For reference, see http://www.brockart.de/S