How to print a canvas image at 100% page width? - javascript

My project needs to print out a canvas image that can be smaller or greater than the page width. I want the printout to maintain the canvas size if it is smaller than page width and scale if the canvas image is larger than page width. How do I accomplish this?
Here is an example of the canvas image being too big for the printed page (It needs to be shrunk to fit):
var canvas = document.getElementById("canvas1");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas.width, canvas.height);
html {height:100%; overflow:hidden;}
#main-container {height:100%; padding:; margin:0;
display: flex;
flex-direction: column;
}
body {height:100%; padding:0; margin:0;
display: flex;
flex-direction: column;
}
header {
background:aqua;
flex: 0 0 100px;
}
section {background:blue;
flex: 1;
display: flex;
flex-direction: row;
overflow:auto;
}
article {
background:blanchedalmond;
flex: 3;
}
nav {
background:coral;
flex: 1;
order: -1;
/*start flex settings*/
display:flex;
flex-direction: column;
justify-content: space-betweeen;
-webkit-justify-content: space-between;
/*end flex settings*/
}
.nav-bottom-container {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: flex-start;
}
.nav-item-top{
overflow-y:auto;
}
.nav-bottom-item-left {
background:deeppink;
order:1;
border-color:red;
border-style: solid;
flex-grow:1;
cursor: pointer;
text-align:center;
}
.nav-bottom-item-right {
background:dodgerblue;
order:0;
border-color:blue;
border-style: solid;
flex-grow:1;
cursor: pointer;
text-align:center;
}
aside {background:#ddd;
flex: 0 0 200px;
}
footer {background:#888;
flex: 0 0 100px;
}
.item-text{
font-size:1vmax;
padding:1em;
}
canvas{ border: 1px solid black; }
#container {
display: flex; /* establish flex container */
flex-direction: column; /* make main axis vertical */
justify-content: center; /* center items vertically, in this case */
align-items: center; /* center items horizontally, in this case */
cursor:move;
}
.print-this-only{
}
#media print {
html,
body {
height:100%;
overflow:hidden;
display:block;
background-color: yellow;
}
.print-this-only {
background-color: yellow;
/*
height: 100%;
width: 100%;
position: fixed;*/
top: 0;
left: 0;
margin: 0;
}
.no-print,
.no-print * {
display: none !important;
}
.printOnly {
display: block;
}
}
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title> Shrink Canvas to Fit Printed Page </title>
</head>
<body ng-app="ui.bootstrap.demo" ng-controller="DropdownController as vm">
<div id="main-container">
<header class="no-print">fixed height header <button onclick="window.print();" class="no-print">Print Canvas</button></header>
<section>
<article id="id"><div id="container" >
<div id="container" class="print-this-only"style="position:relative">
<canvas height="1000px" width="2000px" id="canvas1">
</canvas>
<img src="http://s.cdpn.io/3/kiwi.svg"
style="position: absolute;
left: 0px;
top:0px;
z-index: 2;
width: 100px;
" />
<img src="http://s.cdpn.io/3/kiwi.svg"
style="position: absolute;
left: 150px;
top:0px;
z-index: 2;
width: 100px;
" />
<img src="http://s.cdpn.io/3/kiwi.svg"
style="position: absolute;
left: 1700px;
top:150px;
z-index: 2;
width: 100px;
" />
</>
</div></article>
<nav class="no-print">
<div class="nav-item-top">
<div class="item-text">
sample
</div>
<div class="item-text">
sample this is a much longer sample text it goes on for a little bit here and there.
</div>
<div class="item-text">
this is the end of the line and the end of the universe.
</div>
<div ng-show=vm.showNav>Right</div>
<div ng-hide=vm.showNav>Left</div>
</div>
<div class="nav-bottom-container">
<div class="nav-bottom-item-right" ng-click="vm.showNav=!vm.showNav">Right</div>
<div class="nav-bottom-item-left" ng-click="vm.showNav=!vm.showNav">Left</div>
</div>
</nav>
</section>
</div>
</body>
</html>
Here is an example of the canvas being smaller than page width and appropriately scaled:
var canvas = document.getElementById("canvas1");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas.width, canvas.height);
html {height:100%; overflow:hidden;}
#main-container {height:100%; padding:; margin:0;
display: flex;
flex-direction: column;
}
body {height:100%; padding:0; margin:0;
display: flex;
flex-direction: column;
}
header {
background:aqua;
flex: 0 0 100px;
}
section {background:blue;
flex: 1;
display: flex;
flex-direction: row;
overflow:auto;
}
article {
background:blanchedalmond;
flex: 3;
}
nav {
background:coral;
flex: 1;
order: -1;
/*start flex settings*/
display:flex;
flex-direction: column;
justify-content: space-betweeen;
-webkit-justify-content: space-between;
/*end flex settings*/
}
.nav-bottom-container {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: flex-start;
}
.nav-item-top{
overflow-y:auto;
}
.nav-bottom-item-left {
background:deeppink;
order:1;
border-color:red;
border-style: solid;
flex-grow:1;
cursor: pointer;
text-align:center;
}
.nav-bottom-item-right {
background:dodgerblue;
order:0;
border-color:blue;
border-style: solid;
flex-grow:1;
cursor: pointer;
text-align:center;
}
aside {background:#ddd;
flex: 0 0 200px;
}
footer {background:#888;
flex: 0 0 100px;
}
.item-text{
font-size:1vmax;
padding:1em;
}
canvas{ border: 1px solid black; }
#container {
display: flex; /* establish flex container */
flex-direction: column; /* make main axis vertical */
justify-content: center; /* center items vertically, in this case */
align-items: center; /* center items horizontally, in this case */
cursor:move;
}
.print-this-only{
}
#media print {
html,
body {
height:100%;
overflow:hidden;
display:block;
background-color: yellow;
}
.print-this-only {
background-color: yellow;
/*
height: 100%;
width: 100%;
position: fixed;*/
top: 0;
left: 0;
margin: 0;
}
.no-print,
.no-print * {
display: none !important;
}
.printOnly {
display: block;
}
}
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title> Shrink Canvas to Fit Printed Page </title>
</head>
<body ng-app="ui.bootstrap.demo" ng-controller="DropdownController as vm">
<div id="main-container">
<header class="no-print">fixed height header <button onclick="window.print();" class="no-print">Print Canvas</button></header>
<section>
<article id="id"><div id="container" >
<div id="container" class="print-this-only"style="position:relative">
<canvas height="400px" width="400px" id="canvas1">
</canvas>
<img src="http://s.cdpn.io/3/kiwi.svg"
style="position: absolute;
left: 0px;
top:0px;
z-index: 2;
width: 100px;
" />
<img src="http://s.cdpn.io/3/kiwi.svg"
style="position: absolute;
left: 150px;
top:0px;
z-index: 2;
width: 100px;
" />
<img src="http://s.cdpn.io/3/kiwi.svg"
style="position: absolute;
left: 200px;
top:150px;
z-index: 2;
width: 100px;
" />
</>
</div></article>
<nav class="no-print">
<div class="nav-item-top">
<div class="item-text">
sample
</div>
<div class="item-text">
sample this is a much longer sample text it goes on for a little bit here and there.
</div>
<div class="item-text">
this is the end of the line and the end of the universe.
</div>
<div ng-show=vm.showNav>Right</div>
<div ng-hide=vm.showNav>Left</div>
</div>
<div class="nav-bottom-container">
<div class="nav-bottom-item-right" ng-click="vm.showNav=!vm.showNav">Right</div>
<div class="nav-bottom-item-left" ng-click="vm.showNav=!vm.showNav">Left</div>
</div>
</nav>
</section>
</div>
</body>
</html>

One way to do it is to wrap the canvas into container, than calculate everything in percents of parent element width. So first in HTML:
<div class="canvas_container">
<canvas height="1000px" width="2000px" id="canvas1"></canvas>
</div>
Than add in CSS:
#media print {
#container {
display: block; /* Cannot be flex here */
}
.canvas_container {
max-width: 100%;
padding-bottom: 50%; /* Canvas is 2000x1000, this will set the height to 50% of width */
position: relative;
}
canvas{
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
width: 100%;
}
}
Than each of your images position gotta be in percent, also the width gotta be in percents:
<img src="http://s.cdpn.io/3/kiwi.svg"
style="
position: absolute;
left: 0;
top: 0;
z-index: 2;
width: 5%;
"
/>
<img src="http://s.cdpn.io/3/kiwi.svg"
style="
position: absolute;
left: 7%;
top: 0;
z-index: 2;
width: 5%;
"
/>
<img src="http://s.cdpn.io/3/kiwi.svg"
style="
position: absolute;
left: 85%;
top: 15%;
z-index: 2;
width: 5%;
"
/>
Complete code below:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title> Shrink Canvas to Fit Printed Page </title>
<style>
html {
height: 100%;
overflow: hidden;
}
#main-container {
height: 100%;
padding: ;
margin: 0;
display: flex;
flex-direction: column;
}
* {
box-sizing: border-box;
}
body {
height: 100%;
padding: 0;
margin: 0;
display: flex;
flex-direction: column;
}
header {
background: aqua;
flex: 0 0 100px;
}
section {
background: blue;
flex: 1;
display: flex;
flex-direction: row;
overflow: auto;
}
article {
background: blanchedalmond;
flex: 3;
}
nav {
background: coral;
flex: 1;
order: -1;
/*start flex settings*/
display: flex;
flex-direction: column;
justify-content: space-betweeen;
-webkit-justify-content: space-between;
/*end flex settings*/
}
.nav-bottom-container {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: flex-start;
}
.nav-item-top {
overflow-y: auto;
}
.nav-bottom-item-left {
background: deeppink;
order: 1;
border-color: red;
border-style: solid;
flex-grow: 1;
cursor: pointer;
text-align: center;
}
.nav-bottom-item-right {
background: dodgerblue;
order: 0;
border-color: blue;
border-style: solid;
flex-grow: 1;
cursor: pointer;
text-align: center;
}
aside {
background: #ddd;
flex: 0 0 200px;
}
footer {
background: #888;
flex: 0 0 100px;
}
.item-text {
font-size: 1vmax;
padding: 1em;
}
canvas {
border: 1px solid black;
}
#container {
display: flex;
/* establish flex container */
flex-direction: column;
/* make main axis vertical */
justify-content: center;
/* center items vertically, in this case */
align-items: center;
/* center items horizontally, in this case */
cursor: move;
}
.print-this-only {}
#media print {
html,
body {
height: 100%;
overflow: hidden;
display: block;
background-color: yellow;
}
#container {
display: block;
}
.canvas_container {
max-width: 100%;
padding-bottom: 50%;
position: relative;
}
canvas {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
width: 100%;
}
.print-this-only {
background-color: yellow;
/*
height: 100%;
width: 100%;
position: fixed;*/
top: 0;
left: 0;
margin: 0;
}
.no-print,
.no-print * {
display: none !important;
}
.printOnly {
display: block;
}
}
</style>
</head>
<body ng-app="ui.bootstrap.demo" ng-controller="DropdownController as vm">
<div id="main-container">
<header class="no-print">fixed height header
<button onclick="window.print();" class="no-print">Print Canvas</button>
</header>
<section>
<article id="id">
<div id="container">
<div id="container" class="print-this-only" style="position:relative">
<div class="canvas_container">
<canvas height="1000px" width="2000px" id="canvas1"></canvas>
</div>
<img src="http://s.cdpn.io/3/kiwi.svg" style="
position: absolute;
left: 0;
top: 0;
z-index: 2;
width: 5%;
" />
<img src="http://s.cdpn.io/3/kiwi.svg" style="
position: absolute;
left: 7%;
top: 0;
z-index: 2;
width: 5%;
" />
<img src="http://s.cdpn.io/3/kiwi.svg" style="
position: absolute;
left: 85%;
top: 15%;
z-index: 2;
width: 5%;
" />
</div>
</article>
<nav class="no-print">
<div class="nav-item-top">
<div class="item-text">
sample
</div>
<div class="item-text">
sample this is a much longer sample text it goes on for a little bit here and there.
</div>
<div class="item-text">
this is the end of the line and the end of the universe.
</div>
<div ng-show=vm.showNav>Right</div>
<div ng-hide=vm.showNav>Left</div>
</div>
<div class="nav-bottom-container">
<div class="nav-bottom-item-right" ng-click="vm.showNav=!vm.showNav">Right</div>
<div class="nav-bottom-item-left" ng-click="vm.showNav=!vm.showNav">Left</div>
</div>
</nav>
</section>
</div>
<script>
var canvas = document.getElementById("canvas1");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas.width, canvas.height);
</script>
</body>
</html>

In your print styles, you can add overflow: hidden to .print-this-only and add this to the canvas:
.print-this-only canvas {
max-width:100%;
max-height: 100%;
display: block;
}
Now you can constrain the canvas. Note that for the third image in the canvas you have left: 1700px (changed it to right: 0 for the demo below) - the position values for these images need to be in percentages for the scaling to be proper.
var canvas = document.getElementById("canvas1");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas.width, canvas.height);
html {
height: 100%;
overflow: hidden;
}
#main-container {
height: 100%;
padding: ;
margin: 0;
display: flex;
flex-direction: column;
}
body {
height: 100%;
padding: 0;
margin: 0;
display: flex;
flex-direction: column;
}
header {
background: aqua;
flex: 0 0 100px;
}
section {
background: blue;
flex: 1;
display: flex;
flex-direction: row;
overflow: auto;
}
article {
background: blanchedalmond;
flex: 3;
}
nav {
background: coral;
flex: 1;
order: -1;
/*start flex settings*/
display: flex;
flex-direction: column;
justify-content: space-betweeen;
-webkit-justify-content: space-between;
/*end flex settings*/
}
.nav-bottom-container {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: flex-start;
}
.nav-item-top {
overflow-y: auto;
}
.nav-bottom-item-left {
background: deeppink;
order: 1;
border-color: red;
border-style: solid;
flex-grow: 1;
cursor: pointer;
text-align: center;
}
.nav-bottom-item-right {
background: dodgerblue;
order: 0;
border-color: blue;
border-style: solid;
flex-grow: 1;
cursor: pointer;
text-align: center;
}
aside {
background: #ddd;
flex: 0 0 200px;
}
footer {
background: #888;
flex: 0 0 100px;
}
.item-text {
font-size: 1vmax;
padding: 1em;
}
canvas {
border: 1px solid black;
}
#container {
display: flex;
/* establish flex container */
flex-direction: column;
/* make main axis vertical */
justify-content: center;
/* center items vertically, in this case */
align-items: center;
/* center items horizontally, in this case */
cursor: move;
}
.print-this-only {}
#media print {
html,
body {
height: 100%;
width: 100%;
margin: 0;
overflow: hidden;
display: block;
background-color: yellow;
}
.print-this-only {
background-color: yellow;
top: 0;
left: 0;
margin: 0;
overflow: hidden;
/* ADDED */
}
/* ADDED */
.print-this-only canvas {
max-width: 100%;
max-height: 100%;
display: block;
}
.no-print,
.no-print * {
display: none !important;
}
.printOnly {
display: block;
}
}
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title> Shrink Canvas to Fit Printed Page </title>
</head>
<body ng-app="ui.bootstrap.demo" ng-controller="DropdownController as vm">
<div id="main-container">
<header class="no-print">fixed height header <button onclick="window.print()" class="no-print">Print Canvas</button></header>
<section>
<article id="id">
<div id="container">
<div id="container" class="print-this-only" style="position:relative">
<canvas height="1000px" width="2000px" id="canvas1">
</canvas>
<img src="http://s.cdpn.io/3/kiwi.svg" style="position: absolute;
left: 0px;
top:0px;
z-index: 2;
width: 100px;
" />
<img src="http://s.cdpn.io/3/kiwi.svg" style="position: absolute;
left: 150px;
top:0px;
z-index: 2;
width: 100px;
" />
<img src="http://s.cdpn.io/3/kiwi.svg" style="position: absolute;
right: 0;
top:150px;
z-index: 2;
width: 100px;
" />
</div>
</div>
</article>
<nav class="no-print">
<div class="nav-item-top">
<div class="item-text">
sample
</div>
<div class="item-text">
sample this is a much longer sample text it goes on for a little bit here and there.
</div>
<div class="item-text">
this is the end of the line and the end of the universe.
</div>
<div ng-show=vm.showNav>Right</div>
<div ng-hide=vm.showNav>Left</div>
</div>
<div class="nav-bottom-container">
<div class="nav-bottom-item-right" ng-click="vm.showNav=!vm.showNav">Right</div>
<div class="nav-bottom-item-left" ng-click="vm.showNav=!vm.showNav">Left</div>
</div>
</nav>
</section>
</div>
</body>
</html>
The same demo for a smaller canvas:
var canvas = document.getElementById("canvas1");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "blue";
ctx.fillRect(0, 0, canvas.width, canvas.height);
html {
height: 100%;
overflow: hidden;
}
#main-container {
height: 100%;
padding: ;
margin: 0;
display: flex;
flex-direction: column;
}
body {
height: 100%;
padding: 0;
margin: 0;
display: flex;
flex-direction: column;
}
header {
background: aqua;
flex: 0 0 100px;
}
section {
background: blue;
flex: 1;
display: flex;
flex-direction: row;
overflow: auto;
}
article {
background: blanchedalmond;
flex: 3;
}
nav {
background: coral;
flex: 1;
order: -1;
/*start flex settings*/
display: flex;
flex-direction: column;
justify-content: space-betweeen;
-webkit-justify-content: space-between;
/*end flex settings*/
}
.nav-bottom-container {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
align-items: flex-start;
}
.nav-item-top {
overflow-y: auto;
}
.nav-bottom-item-left {
background: deeppink;
order: 1;
border-color: red;
border-style: solid;
flex-grow: 1;
cursor: pointer;
text-align: center;
}
.nav-bottom-item-right {
background: dodgerblue;
order: 0;
border-color: blue;
border-style: solid;
flex-grow: 1;
cursor: pointer;
text-align: center;
}
aside {
background: #ddd;
flex: 0 0 200px;
}
footer {
background: #888;
flex: 0 0 100px;
}
.item-text {
font-size: 1vmax;
padding: 1em;
}
canvas {
border: 1px solid black;
}
#container {
display: flex;
/* establish flex container */
flex-direction: column;
/* make main axis vertical */
justify-content: center;
/* center items vertically, in this case */
align-items: center;
/* center items horizontally, in this case */
cursor: move;
}
.print-this-only {}
#media print {
html,
body {
height: 100%;
width: 100%;
margin: 0;
overflow: hidden;
display: block;
background-color: yellow;
}
.print-this-only {
background-color: yellow;
top: 0;
left: 0;
margin: 0;
overflow: hidden;
/* ADDED */
}
/* ADDED */
.print-this-only canvas {
max-width: 100%;
max-height: 100%;
display: block;
}
.no-print,
.no-print * {
display: none !important;
}
.printOnly {
display: block;
}
}
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title> Shrink Canvas to Fit Printed Page </title>
</head>
<body ng-app="ui.bootstrap.demo" ng-controller="DropdownController as vm">
<div id="main-container">
<header class="no-print">fixed height header <button onclick="window.print();" class="no-print">Print Canvas</button></header>
<section>
<article id="id">
<div id="container">
<div id="container" class="print-this-only" style="position:relative">
<canvas height="400px" width="400px" id="canvas1">
</canvas>
<img src="http://s.cdpn.io/3/kiwi.svg" style="position: absolute;
left: 0px;
top:0px;
z-index: 2;
width: 100px;
" />
<img src="http://s.cdpn.io/3/kiwi.svg" style="position: absolute;
left: 150px;
top:0px;
z-index: 2;
width: 100px;
" />
<img src="http://s.cdpn.io/3/kiwi.svg" style="position: absolute;
left: 200px;
top:150px;
z-index: 2;
width: 100px;
" />
</div>
</div>
</article>
<nav class="no-print">
<div class="nav-item-top">
<div class="item-text">
sample
</div>
<div class="item-text">
sample this is a much longer sample text it goes on for a little bit here and there.
</div>
<div class="item-text">
this is the end of the line and the end of the universe.
</div>
<div ng-show=vm.showNav>Right</div>
<div ng-hide=vm.showNav>Left</div>
</div>
<div class="nav-bottom-container">
<div class="nav-bottom-item-right" ng-click="vm.showNav=!vm.showNav">Right</div>
<div class="nav-bottom-item-left" ng-click="vm.showNav=!vm.showNav">Left</div>
</div>
</nav>
</section>
</div>
</body>
</html>

Related

Why is the closing X not displayed if the navbar is opened?

I've tried now quite a time to figure out, why the closing symbol (X) is not displayed if I open my navbar.
If it is closed, everything seems fine.
In the Google Chrome dev tools the icon is still on the page, but in front-end it is not visible.
My environment:
macOS Monterey
VS Code with Live Preview extension
Google Chrome
Is there something I don't see?
Here is my index.html file (I know, the JavaScript should be in an own file ;-P):
section {
background-color: blue;
padding: 20px;
/* height: 40px; */
display: flex;
justify-content: space-between;
align-items: center;
}
img {
height: 30px;
width: auto;
}
.toggle-box a img {
filter: invert(1);
}
.img.menu.hide {
display: none;
}
img.close {
display: none;
}
img.close.show {
display: flex;
/* z-index: 9999; */
}
nav.navigation {
display: none;
}
nav.navigation.active {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: blue;
/* z-index: 1111; */
}
nav.navigation.active a {
padding: 20px;
color: #ffffff;
font-size: 20px;
font-weight: bold;
text-decoration: none;
}
.phone-logo a img {
filter: invert(1);
}
<section>
<div class="toggle-box">
<a onclick="showMenu()" href="#">
<img class="menu" src="menu-outline.svg" />
<img class="close" src="close-outline.svg" />
</a>
</div>
<nav class="navigation">
Sec 1
Sec 2
Sec 3
Sec 4
</nav>
<div class="phone-logo">
<a href="#">
<img src="call-outline.svg" />
</a>
</div>
</section>
<script>
function showMenu() {
document.querySelector(".menu").classList.toggle("hide");
document.querySelector(".close").classList.toggle("show");
document.querySelector(".navigation").classList.toggle("active");
}
</script>
</body>
Elements which fall later in the document have a higher stacking order, meaning that they're layered over earlier elements. You can rearrange your markup to resolve that.
section {
background-color: blue;
padding: 20px;
/* height: 40px; */
display: flex;
justify-content: space-between;
align-items: center;
}
img {
height: 30px;
width: auto;
}
.toggle-box a img {
filter: invert(1);
}
.img.menu.hide {
display: none;
}
img.close {
display: none;
}
img.close.show {
display: flex;
/* z-index: 9999; */
}
nav.navigation {
display: none;
}
nav.navigation.active {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: blue;
/* z-index: 1111; */
}
nav.navigation.active a {
padding: 20px;
color: #ffffff;
font-size: 20px;
font-weight: bold;
text-decoration: none;
}
.phone-logo a img {
filter: invert(1);
}
<section>
<nav class="navigation">
Sec 1
Sec 2
Sec 3
Sec 4
</nav>
<div class="toggle-box">
<a onclick="showMenu()" href="#">
<img class="menu" src="menu-outline.svg" />
<img class="close" src="close-outline.svg" />
</a>
</div>
<div class="phone-logo">
<a href="#">
<img src="call-outline.svg" />
</a>
</div>
</section>
<script>
function showMenu() {
document.querySelector(".menu").classList.toggle("hide");
document.querySelector(".close").classList.toggle("show");
document.querySelector(".navigation").classList.toggle("active");
}
</script>
</body>
It's just a matter of z-index for the .toggle-box.
section {
background-color: blue;
padding: 20px;
/* height: 40px; */
display: flex;
justify-content: space-between;
align-items: center;
}
img {
height: 30px;
width: auto;
}
.toggle-box a img {
filter: invert(1);
}
.img.menu.hide {
display: none;
}
img.close {
display: none;
}
img.close.show {
display: flex;
/* z-index: 9999; */
}
nav.navigation {
display: none;
}
nav.navigation.active {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: blue;
/* z-index: 1111; */
}
nav.navigation.active a {
padding: 20px;
color: #ffffff;
font-size: 20px;
font-weight: bold;
text-decoration: none;
}
.phone-logo a img {
filter: invert(1);
}
.toggle-box {
z-index: 1;
}
<section>
<div class="toggle-box">
<a onclick="showMenu()" href="#">
<img class="menu" src="menu-outline.svg" />
<img class="close" src="close-outline.svg" />
</a>
</div>
<nav class="navigation">
Sec 1
Sec 2
Sec 3
Sec 4
</nav>
<div class="phone-logo">
<a href="#">
<img src="call-outline.svg" />
</a>
</div>
</section>
<script>
function showMenu() {
document.querySelector(".menu").classList.toggle("hide");
// document.querySelector(".close").classList.toggle("show");
document.querySelector(".navigation").classList.toggle("active");
}
</script>
</body>

Flexbox scroll overflowing content in an dynamic sized parent

I have a simple menu and content div structure. The menu has no fixed size and can expand depending on its content. The content div underneath should take the available space and scroll its own content if overflowing. Unfortunately, flexbox now behaves in such a way that the content div, due to its flex:1 property, expands according to its content instead of scrolling the content.
Is there a way to preserve the dynamic sizes using flex:1 and also have the content of the content div scroll?
function toggleMenu() {
const menu = document.querySelector(".menu");
if(menu.classList.contains("open")) {
menu.querySelector(".text").innerHTML = "<p> small text </p>";
menu.classList.remove("open");
}else {
menu.querySelector(".text").innerHTML = "<h1> im the menu </h1>";
menu.classList.add("open");
}
}
body {
padding: 0;
margin: 0;
background-color: #17141d;
display: flex;
height: 100vh;
}
.main {
display: flex;
flex-direction: column;
flex: 1;
background-color: grey;
}
.menu {
background-color: blueviolet;
}
.content {
display: flex;
flex: 1;
background-color: aqua;
}
.segment-wrapper {
flex: 1;
display: flex;
background-color: red;
flex-direction: column;
overflow-y: scroll;
padding: 10px;
box-sizing: border-box;
}
.segment {
height: 500px;
background-color: green;
border-radius: 5px;
border: solid 1px black;
width: 100%;
margin-bottom: 10px;
}
<div class="main">
<div class="menu open">
<div class="text"><h1>im the menu</h1></div>
<button onclick="toggleMenu()">Toggle</button>
</div>
<div class="content">
<div class="segment-wrapper">
<div class="segment">
</div>
<div class="segment">
</div>
<div class="segment">
</div>
</div>
</div>
</div>
you are missing
an height on .main to size it according to body or the viewport's height.
overflow on .content, so it overflows, unless you want .main to overflow (which body does already)
and finally flex-shrink:0; on .segment so it doesn't shrink :)
here an example of what i understood you were after:
function toggleMenu() {
const menu = document.querySelector(".menu");
if(menu.classList.contains("open")) {
menu.querySelector(".text").innerHTML = "<p> small text </p>";
menu.classList.remove("open");
}else {
menu.querySelector(".text").innerHTML = "<h1> im the menu </h1>";
menu.classList.add("open");
}
}
body {
padding: 0;
margin: 0;
background-color: #17141d;
display: flex;
height: 100vh;
}
.main {
display: flex;
flex-direction: column;
flex: 1;
background-color: grey;
max-height;100%;
}
.menu {
background-color: blueviolet;
}
.content {
display: flex;
flex: 1;
background-color: aqua;
overflow:auto;
}
.segment-wrapper {
flex: 1;
display: flex;
background-color: red;
flex-direction: column;
overflow-y: scroll;
padding: 10px;
box-sizing: border-box;
}
.segment {
flex-shrink:0;
height: 500px;
background-color: green;
border-radius: 5px;
border: solid 1px black;
width: 100%;
margin-bottom: 10px;
}
<div class="main">
<div class="menu open">
<div class="text"><h1>im the menu</h1></div>
<button onclick="toggleMenu()">Toggle</button>
</div>
<div class="content">
<div class="segment-wrapper">
<div class="segment">
</div>
<div class="segment">
</div>
<div class="segment">
</div>
</div>
</div>
</div>

How to overlap images using flexbox while maintaing it's ability responsive design

click here to see my code
The goal here is to perfectly overlap the images.
The eyes (blue ovals) should display on the face (peach circle). I'm using chrome as my browser. But hope it will display the same on any browser used.
Like so (minus the nose):
What I tried:
changing the position of the images from relative to absolute (With one image set as absolute I should have been able to move it anywhere I wanted on the page.)
setting align-self: flex-start (Sometimes browsers have weird default setting. I was told this might override a chrome default that was stopping me from moving the image.)
setting align-self: center (This was also an attempt to override a chrome default)
I can't figure out how to overlap the two images let alone add any code to my CSS file that will move the images.
function setDefaultImage(){
var defaultImage = document.getElementById(img_face).src = "https://drive.google.com/file/d/1_seSuUcgJgd5qQTUcreDuYo_zfVpRzsa/view?usp=sharing";
}
.flex-container {
display: flex;
background-color: darkred;
flex-direction: row;
flex-wrap: wrap;
justify-content: center;
}
.flex-container > div {
background-color: black;
margin: 1%;
padding: 5%;
width:38%;
}
img{
align-self: flex-start;
text-align: center;
width: 100%;
}
.img_face{
position: absolute;
top: 0;
z-index: 1;
}
.img_eyes{
position: absolute;
top: 0;
z-index: 2;
}
<!DOCTYPE html>
<html>
<body>
<div class="flex-container">
<div id = "left">
<button type="reset" id="reset" class="button" onclick = setDefaultImage()>Reset</button>
</div>
<div id = "right">
<img id="img_face" src="white_face.png" alt="White Face" >
<img id="img_eyes" src="blue_eyes.png" alt="Blue Eyes" >
</div>
</div>
Here's a couple different approaches with room for tinkering to help your learning. Happy Holidays!
hiUser = (val) => {
const box1 = document.getElementById('box1'),
box2 = document.getElementById('box2'),
blah = `${val}px`;
box1.style.height = blah;
box1.style.width = blah;
box2.style.height = blah;
box2.style.width = blah;
}
div {
display: flex;
align-items: center;
/* default initial values */
height: 100px;
width: 100px;
margin-top: 2rem;
}
span {
background-color: blue;
height: 20%;
width: 10%;
border-radius: 50%;
margin-bottom: 30%;
}
figure, #box1 {
position: relative;
background-color: wheat;
border-radius: 50%;
margin: 0;
}
figure {
height: 100%;
width: 100%;
}
#box1 {
justify-content: space-around;
}
#box1 span {
margin-right: 20%;
}
#box1 span:first-child {
margin-left: 20%;
margin-right: 0;
}
figure:before, figure:after {
content: '';
display: block;
position: absolute;
top: 25%;
background-color: blue;
height: 20%;
width: 10%;
border-radius: 50%;
}
figure:before {
left: 30%;
}
figure:after {
right: 30%;
}
label {
display: block;
margin: 2rem 0 1rem 0;
}
Slide to change size:
<input type="range"
name="fu"
min="0"
max="500"
onchange="hiUser(this.value)"
oninput="hiUser(this.value)">
<label>Flex;</label>
<div id="box1">
<span></span>
<span></span>
</div>
<label>Pseudo;</label>
<div id="box2">
<figure></figure>
</div>

align items on stretch to the center of the parent div

I tried to create a menu that stretches to full height on mobile screens. For the parent container I use a flexbox with flex-direction column and stretch the items on full screen height.
$(document).ready(() => {
$("#btnMenu").click(() => {
toggleMenu();
});
$(".navbarLink").click(() => {
if ($("#navbarItems").hasClass("activeNavbar")) {
toggleMenu();
}
});
});
function toggleMenu() {
$("#navbarItems").toggleClass("activeNavbar");
toggleMenuBtn();
}
function toggleMenuBtn() {
$("#btnMenu").toggleClass("activeMenuBtn");
}
body {
margin: 0;
}
.link {
text-decoration: none;
}
#navbar {
height: 60px;
top: 0;
padding-left: 200px;
padding-right: 200px;
position: sticky;
background: #1e222a;
}
#navbarItems {
height: 100%;
display: flex;
align-items: center;
}
#logoLink {
display: flex;
align-items: center;
}
#navbarItems .navbarItem:not(:first-child) {
margin-left: 30px;
}
.navbarItem {
background: #1e222a;
}
.navbarLink {
color: #ffffff;
}
.navbarLink:hover {
color: #3abcf3;
}
#btnMenuContainer {
height: 100%;
display: none;
}
#btnMenu {
cursor: pointer;
}
.menuBtnBar {
width: 35px;
height: 5px;
margin: 6px 0;
background-color: #ffffff;
transition: 0.4s;
}
.activeMenuBtn #barTop {
transform: rotate(-45deg) translate(-9px, 6px);
}
.activeMenuBtn #barCenter {
opacity: 0;
}
.activeMenuBtn #barBottom {
transform: rotate(45deg) translate(-8px, -8px);
}
#media(max-width: 1200px) {
#navbar {
padding-left: 150px;
padding-right: 150px;
}
}
#media(max-width: 1100px) {
#navbar {
padding-left: 0;
padding-right: 0;
}
#btnMenuContainer {
display: flex;
align-items: center;
}
#btnMenu {
margin-left: 20px;
}
#navbarItems {
margin-left: 0;
display: none;
}
#navbarItems.activeNavbar {
display: flex;
flex-direction: column;
align-items: stretch;
height: 100vh;
}
#logoLink {
display: inline-block;
}
.navbarItem {
flex: 1 1 100%;
align-items: center;
justify-content: center;
text-align: center;
}
#navbarItems .navbarItem:not(:first-child) {
margin-left: 0;
}
#navbarItems .navbarItem:not(:last-child) {
border-bottom: 1px solid #676767;
}
.navbarLink {
width: 100%;
height: 100%;
display: inline-block;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="navbar">
<div id="btnMenuContainer">
<div id="btnMenu">
<div id="barTop" class="menuBtnBar"></div>
<div id="barCenter" class="menuBtnBar"></div>
<div id="barBottom" class="menuBtnBar"></div>
</div>
</div>
<div id="navbarItems">
<div class="navbarItem">
<a id="logoLink" class="link navbarLink" href="#">
<img class="img" src="https://cdn4.iconfinder.com/data/icons/32x32-free-design-icons/32/Ok.png">
</a>
</div>
<div class="navbarItem">
<a class="link navbarLink" href="#">
Link 2
</a>
</div>
<div class="navbarItem">
<a class="link navbarLink" href="#">
Link 3
</a>
</div>
</div>
</div>
When using align-items: stretch; how can I place the links (and the logo) back to center?
My second question is what can I use for height: 100vh; instead? I would like to keep it dynamic so maybe there is a better way than using a constant number?
It works fine. Check the code snippets and fiddle for further clarification.
Noe all links are center aligned and menu height takes the full height of the space available and there is no scroll any more.
My suggestion is to use 100vh for the height because it better than applying static value since 100vh is dynamic value.
https://jsfiddle.net/Sampath_Madhuranga/4uLb6rsw/7/
$(document).ready(() => {
$("#btnMenu").click(() => {
toggleMenu();
});
$(".navbarLink").click(() => {
if ($("#navbarItems").hasClass("activeNavbar")) {
toggleMenu();
}
});
});
function toggleMenu() {
$("#navbarItems").toggleClass("activeNavbar");
toggleMenuBtn();
}
function toggleMenuBtn() {
$("#btnMenu").toggleClass("activeMenuBtn");
}
body {
margin: 0;
}
.link {
text-decoration: none;
}
#navbar {
height: 60px;
top: 0;
padding-left: 200px;
padding-right: 200px;
position: sticky;
background: #1e222a;
}
#navbarItems {
height: 100%;
display: flex;
align-items: center;
}
#logoLink {
display: flex;
align-items: center;
}
#navbarItems .navbarItem:not(:first-child) {
margin-left: 30px;
}
.navbarItem {
background: #1e222a;
}
.navbarLink {
color: #ffffff;
}
.navbarLink:hover {
color: #3abcf3;
}
#btnMenuContainer {
height: 100%;
display: none;
}
#btnMenu {
cursor: pointer;
}
.menuBtnBar {
width: 35px;
height: 5px;
margin: 6px 0;
background-color: #ffffff;
transition: 0.4s;
}
.activeMenuBtn #barTop {
transform: rotate(-45deg) translate(-9px, 6px);
}
.activeMenuBtn #barCenter {
opacity: 0;
}
.activeMenuBtn #barBottom {
transform: rotate(45deg) translate(-8px, -8px);
}
#media(max-width: 1200px) {
#navbar {
padding-left: 150px;
padding-right: 150px;
}
}
#media(max-width: 1100px) {
#navbar {
padding-left: 0;
padding-right: 0;
}
#btnMenuContainer {
display: flex;
align-items: center;
}
#btnMenu {
margin-left: 20px;
}
#navbarItems {
margin-left: 0;
display: none;
}
#navbarItems.activeNavbar {
display: flex;
flex-direction: column;
align-items: stretch;
height: calc( 100vh - 60px);
}
#logoLink {
display: flex;
justify-content: center;
}
.navbarItem {
flex: 1 1 100%;
align-items: center;
justify-content: center;
text-align: center;
}
#navbarItems .navbarItem:not(:first-child) {
margin-left: 0;
}
#navbarItems .navbarItem:not(:last-child) {
border-bottom: 1px solid #676767;
}
.navbarLink {
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="navbar">
<div id="btnMenuContainer">
<div id="btnMenu">
<div id="barTop" class="menuBtnBar"></div>
<div id="barCenter" class="menuBtnBar"></div>
<div id="barBottom" class="menuBtnBar"></div>
</div>
</div>
<div id="navbarItems">
<div class="navbarItem">
<a id="logoLink" class="link navbarLink" href="#">
<img class="img" src="https://cdn4.iconfinder.com/data/icons/32x32-free-design-icons/32/Ok.png">
</a>
</div>
<div class="navbarItem">
<a class="link navbarLink" href="#">
Link 2
</a>
</div>
<div class="navbarItem">
<a class="link navbarLink" href="#">
Link 3
</a>
</div>
</div>
</div>
Thanks.
Let .navbarLink also have a flex layout.
.navbarItem {
flex: 1 1 100%;
}
.navbarLink {
height: 100%;
width: 100%;
display: flex;
flex-flow: row nowrap;
align-items: center;
justify-content: center;
text-align: center;
}
By the way, here is a great resource that really helped me when I learned to use flexbox layouts. https://css-tricks.com/snippets/css/a-guide-to-flexbox/
Follow this link https://flexboxfroggy.com/ there is a really nice game which will teach you flexbox while playing in no time. After that you will be able to fix your navigation.

How to set div scrollable when content more than size of the page?

I have the next page:
<div id = "menu">
Menu on the left side
</div>
<div id = "header">
Header content of the page
</div>
<div id = "body">
Data Data Data Data Data Data Data
</div>
<div id = "footer">
Additional Information
</div>
Whith Next layout: Menu should be on the left side:
#menu{
background: #244a7c;
padding: 7px 23px 0 7px;
width: 299px;
height: 1000px;
overflow: inherit;
margin-left: 0px;
display: block;
float: left;
}
#header{
display: inline-block;
width: 400px;
border-bottom: 1px solid rgb(238, 238, 238);
}
Body can have different data inside. My problem is:
When content of the body more than user page I want to fix all div except body. Menu should be on the left side, Header should be on the top of the page and footer on the bottom and ONLY body should be scrollable.
Any help, please.
Thanks!
Here's 2 Pure CSS solution
Without fixing any height (header/footer) or width (left column).
I actually prefer the second solution. (even tho he has less browser support)
1 - using CSS tricks
this is a totally responsive design and work well with all browsers (IE10, FF, Chrome, Safari, Opera, mobile browsers)
Working Fiddle
HTML:
<div class="Container">
<div class="Header">
</div>
<div class="HeightTaker">
<div class="Wrapper Container Inverse">
<div>
<div class="Footer">
</div>
</div>
<div class="HeightTaker">
<div class="Wrapper">
<div class="LeftMenu">
</div>
<div class="Content">
</div>
</div>
</div>
</div>
</div>
</div>
CSS:
*
{
margin: 0;
padding: 0;
}
html, body, .Container
{
height: 100%;
}
.Container:before
{
content: '';
height: 100%;
float: left;
}
.HeightTaker
{
position: relative;
z-index: 1;
}
.HeightTaker:after
{
content: '';
clear: both;
display: block;
}
.Wrapper
{
position: absolute;
width: 100%;
height: 100%;
}
.Inverse, .Inverse > *
{
-moz-transform: rotateX(180deg);
-ms-transform: rotateX(180deg);
-o-transform: rotate(180deg);
-webkit-transform: rotateX(180deg);
transform: rotateX(180deg);
}
.LeftMenu
{
height: 100%;
float: left;
}
.Content
{
overflow: auto;
height: 100%;
}
/*For demonstration only*/
p
{
font-size: 1.3em;
}
.Important
{
font-weight: bolder;
color: white;
}
body > .Container
{
text-align: center;
}
.Header
{
background-color: #bf5b5b;
}
.LeftMenu
{
background-color: #bdbe4c;
}
.Content
{
background-color: #90adc1;
}
.Footer
{
background-color: #b5a8b7;
}
2 - using Flex
This layout can also be achieved using flex, but the current browser support is pure.
Here's a Working Fiddle only FF,Chrome,IE10.
HTML: (simpler)
<header>
</header>
<section class="Middle">
<div class="LeftMenu">
</div>
<div class="Content">
</div>
</section>
<footer>
</footer>
CSS:
*
{
margin: 0;
padding: 0;
}
html, body
{
height: 100%;
text-align: center;
}
body
{
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: column;
-ms-flex-direction: column;
flex-direction: column;
}
.Middle
{
-webkit-flex: 1 1 auto;
-ms-flex: 1 1 auto;
flex: 1 1 0;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
overflow: hidden;
}
.Content
{
-webkit-flex: 1 1 auto;
-ms-flex: 1 1 auto;
flex: 1 0 0;
overflow: auto;
}
/*For demonstration only*/
p
{
font-size: 1.3em;
}
.Important
{
font-weight: bolder;
color: white;
}
header
{
background-color: #bf5b5b;
}
.LeftMenu
{
background-color: #bdbe4c;
}
.Content
{
background-color: #90adc1;
}
footer
{
background-color: #b5a8b7;
}
If you set the header, footer & menu position as fixed & leave the body as it is, it should work. Only the body will be scrollable.
#header {
position: fixed;
top: 0;
display: inline-block;
width: 400px;
border-bottom: 1px solid rgb(238, 238, 238);
}
#footer {
position: fixed;
bottom: 0;
}
#menu {
position: fixed;
left: 0;
background: #244a7c;
padding: 7px 23px 0 7px;
width: 299px;
height: 1000px;
}
#body {
margin-left: 300px;
margin-top: <header-height>;
margin-bottom: <footer-height>;
}

Categories

Resources