I want to create an HTML page with:
I want this square to be as big as possible, expanding to fill the area not taken up by the navigation pane.
I have a JavaScript solution for this (see below and as a jsFiddle), but I'm hoping that it is possible to do this as a CSS only solution.
<!DOCTYPE html>
<html lang=en>
<head>
<style>
html, body {
margin: 0;
height: 100%;
background-color: #fff;
}
nav {
height: 100%;
width: 96px;
background-color: #666;
}
main {
position: absolute;
background-color: #000;
color: #fff;
}
</style>
</head>
<body>
<nav>
Navigation
</nav>
<main>
This should be square
</main>
<script>
;(function createSquareArea() {
var main = document.querySelector("main")
var nav = document.querySelector("nav")
var navWidth = nav.getBoundingClientRect().width
var debounceDelay = 100
var timeout
window.onresize = windowResized
maintainRatio()
function windowResized() {
if (timeout) {
window.clearTimeout(timeout)
}
timeout = window.setTimeout(maintainRatio, debounceDelay)
}
function maintainRatio() {
timeout = 0
var windowHeight = window.innerHeight
var mainWidth = window.innerWidth - navWidth
var minDimension = Math.min(windowHeight, mainWidth)
var left = (mainWidth - minDimension) / 2 + navWidth
var top = (windowHeight - minDimension) / 2
main.style.left = left + "px"
main.style.top = top + "px"
main.style.width = minDimension + "px"
main.style.height = minDimension + "px"
}
})()
</script>
</body>
</html>
JSFiddle: https://jsfiddle.net/ymzq6zm0/7/
HTML
<nav>
Navigation
</nav>
<main>
<div class="sc">
This should be square
</div>
</main>
CSS
html, body {
margin: 0;
height: 100%;
background-color: #fff;
}
.wrapper {
display: flex;
align-items: center;
height: 100%;
}
nav {
float: left;
height: 100%;
width: 96px;
background-color: #666;
}
main {
float: left;
width: calc(100% - 96px);
height: 100vmin;
max-height: calc(100vw - 96px);
}
.sc {
margin: 0 auto;
background-color: #000;
color: #fff;
height: 100vmin;
width: 100vmin;
max-width: 100%;
max-height: calc(100vw - 96px);
}
Our main objective here is to:
.sc
.sc
vertically center.sc
is always a sqaure.sc
responsiveThe square is highly responsive as it changes its height and width according to the window's or view port's height and width. We need to use vw
(viewport's width) and vmin
(lowest value between viewport's height and width). Read more about these units here: https://css-tricks.com/viewport-sized-typography/
To make .sc
a square, we need to make sure its width and height are always equal. Since the ratio of height and width of viewport is not always the same, we need to find out the lowest value between these two and assign them to .sc
which can be done using the vmin
unit mentioned above.
The square should always remain centered in the remaining area after the navigation on the left, never cross the remaining area and resize accordingly.
This can be accomplished the following codes:
nav {
float: left;
height: 100%;
width: 96px;
background-color: #666;
}
main {
float: left;
width: calc(100% - 96px);
height: 100vmin;
max-height: calc(100vw - 96px);
}
.sc {
margin: 0 auto;
background-color: #000;
color: #fff;
height: 100vmin;
width: 100vmin;
max-width: 100%;
max-height: calc(100vw - 96px);
}
main
is the remaining area after nav. We make sure of this by using the calc
property to subtract the nav
width from 100%.
The .sc
is placed inside main
and we have added the extra max-width
and max-height
properties to make sure .sc
always resizes itself according to main
.
max-height: calc(100vw - 96px);
property of .sc
is always equal to width: calc(100% - 96px);
property of main
. They both calculate the same values.
By adding max-width: 100%;
to .sc
we make sure it's maximum width is equal to that of main
.
Now since, both the max-height
and max-width
along with width and height of .sc
remain the same, it will always be a square.
At the end we put both nav
and main
inside .wrapper
which is a flexbox and has align-items: center;
property. This will ensure that the square is always vertically centered with respect to the nav
.