I am creating a page to show enlarged views of a photographs. I want the page show a header at the top, a footer at the bottom, and the image of the photograph filling in all of the space between the the header and the footer. The photographs have varying sizes and may have landscape or portrait orientation. I have no difficulty sizing the width to the viewport. I have no problem doing this if the page only contains the image and nothing else. Despite searching, reading, and trial and error I cannot discern how to size the content vertically to meet this guideline. For example:
<header>
<h1>Some header stuff</h1>
<p>Such as a navigation bar at the top of the viewport.</p>
</header>
<main>
<h1>Image</h1>
<p>An image that should fill up the space in between</p>
xxxxxxxxxxxxx<br />
xxxxxxxxxxxxx<br />
xxxxxxxxxxxxx<br />
xxxxxxxxxxxxx<br />
xxxxxxxxxxxxx<br />
</main>
<footer>
<h1>Some footer stuff</h1>
<p>Such as a logo, link to privacy page etc.</p>
</footer>
Perhaps this is not possible. Any ideas?
The layout is actually totally possible, but requires some slight modification to your HTML. You will want to wrap your <header>
, <main>
and <footer>
element in a wrapper div, which is set to display: flex; flex-direction: column
, so that they will use CSS flexbox to perform space-filling layout requirements.
Then, in the <main>
element, you do the same CSS flexbox trick. However, you should wrap your <img>
element with a <div>
, which is set to grow to whatever space that is available.
So far, your layout will look like this:
<div class="wrapper">
<header><!-- Header content --></header>
<main>
<!-- More content -->
<div class="image">
<img src="..." />
</div>
</main>
<footer><!-- Footer content --></footer>
</div>
Your <img>
element is then set to position itself absolutely, covering its parent <div>
completely, and taking advantage of object-fit: cover
to size itself to fill all space while preserving aspect ratio.
Here is a proof-of-concept example. However, you might want to view it on full page (or check this JSFiddle), since the code snippet inline preview is too small to demonstrate the layout:
html, body {
height: 100%;
padding: 0;
margin: 0;
background-color: #fff;
}
.wrapper {
display: flex;
flex-direction: column;
height: 100%;
}
header, footer {
background-color: steelblue;
color: #eee;
}
main {
flex: 1 1 100%;
display: flex;
flex-direction: column;
height: 100%;
}
.image {
flex: 1 1 100%;
position: relative;
}
img {
display: block;
width: 100%;
height: 100%;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
object-fit: cover;
}
<div class="wrapper">
<header>
<h1>Some header stuff</h1>
<p>Such as a navigation bar at the top of the viewport.</p>
</header>
<main>
<h1>Image</h1>
<p>An image that should fill up the space in between</p>
<div class="image">
<img src="https://images.unsplash.com/photo-1586109803336-c02797ffdcc0?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=634&q=80" />
</div>
</main>
<footer>
<h1>Some footer stuff</h1>
<p>Such as a logo, link to privacy page etc.</p>
</footer>
</div>