Wrong size of canvas when set by JavaScript [duplicate] - javascript

I was testing html5 canvas element, and wish my canvas to be full screen in the display area. But I found if I set the canvas height to window.innerHeight, the scroll bar will be shown up. I tried and found need to set the height to 5 pixel less, the scroll bar will disappear, but unfortunately it left a white border below the canvas. If it's a div element, everything is fine.
The code I'm using to test is:
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<script type="text/javascript">
function load() {
var o = document.getElementById('canvas');
if (o) {
o.width = window.innerWidth;
o.height = window.innerHeight - 5;
}
o = document.getElementById('div');
if (o) {
o.style.width = window.innerWidth + 'px';
o.style.height = window.innerHeight + 'px';
}
}
</script>
<style type="text/css">
* {
margin: 0;
padding: 0;
}
body {
background-color: white;
}
#canvas {
background-color: blue;
}
#div {
background-color: green;
}
</style>
</head>
<body onload="load();">
<canvas id="canvas"></canvas>
<!--div id="div"></div-->
</body>
</html>
I've cleared the body margin and padding.
I test it on Chrome 8.0.552, and also it acts same on Firefox 3.6.13 but 4 pixel less is fine.
Anything I missed? Any suggestions will be really appreciated. Thanks a lot.

By default canvas, unlike div, is display: inline; so it gets set to vertical-align: baseline;. You can take either of the following approaches to make things naturally fill the window.innerHeight:
#canvas {
background-color: blue;
vertical-align: top;
}
Or:
#canvas {
background-color: blue;
display: block;
}

Related

How do I get a parent div to resize when the children do?

I'm running into this problem with a program I'm working on and I can't figure out the solution. Basically I have a webapp, on initial render the entire page is height X. There is a background color, and that color covers the full height of the page.
Moments after the initial render, data is fetched asynchronously and added to the page. The data causes the total height of the page to get larger. Unfortunately, only the original height of the page shows the background color, below that the background becomes white.
On further investigation, I've discovered this is due to a parent div not resizing when the child div does. Basically, the div getting elements added to it by the asynchronous data loading grows in height, but the parent wrapping around it (and the one that has the background color) does not.
During my investigation, I have found a partial solution: set the "height" to "auto". The problem with this solution is when the page initially loads, the background color is only applied to the part of the page with actual content, rather than filling the screen. So if I have the height at "auto", the color is screwed up when the page first loads before correcting itself after the items are added, and if the height is "100%" then the color is screwed up after the items are added.
I've put together a barebones HTML file that re-creates the issue:
<!DOCTYPE html>
<html>
<head>
<title>Layout Test</title>
<style>
* {
margin: 0;
padding: 0;
}
html {
height: 100%;
margin: 0;
padding: 0;
}
body {
margin: 0;
padding: 0;
height: 100%;
}
#root {
background-color: cyan;
height: 100%;
}
#root > h1 {
text-align: center;
}
</style>
</head>
<body>
<div id="root">
<h1>Layout Test</h1>
<div id="container"></div>
</div>
<script>
setTimeout(() => {
const container = document.querySelector('#container');
for (let i = 0; i < 100; i++) {
const h1 = document.createElement('h1');
h1.textContent = 'Hello';
container.appendChild(h1);
}
}, 1000);
</script>
</body>
</html>
You could set min-height: 100vh; on the #root element CSS so that it is always at least the height of the viewport.
Setting the a min-height of 100% on the #root, instead of a height, seems to do the trick:
<!DOCTYPE html>
<html>
<head>
<title>Layout Test</title>
<style>
* {
margin: 0;
padding: 0;
}
html {
height: 100%;
margin: 0;
padding: 0;
}
body {
margin: 0;
padding: 0;
height: 100%;
}
#root {
background-color: cyan;
min-height: 100%;
}
#root > h1 {
text-align: center;
}
</style>
</head>
<body>
<div id="root">
<h1>Layout Test</h1>
<div id="container"></div>
</div>
<script>
setTimeout(() => {
const container = document.querySelector('#container');
for (let i = 0; i < 100; i++) {
const h1 = document.createElement('h1');
h1.textContent = 'Hello';
container.appendChild(h1);
}
}, 1000);
</script>
</body>
</html>
You could use height: fit-content; and width: fit-content; on the parent element

How to position a p5.js canvas inside a div container? [duplicate]

This question already has answers here:
How to put p5.js canvas in a html div
(4 answers)
Closed 4 months ago.
So far I’ve got the p5.js canvas size to react to its parent div container size using document.getElementById("divName").offsetWidth and .offsetHeight but I haven’t managed to work out why it is not sharing its position as well. Here’s a simplified version of my app.
p5.js:
var sketchWidth;
var sketchHeight;
function setup() {
sketchWidth = document.getElementById("square").offsetWidth;
sketchHeight = document.getElementById("square").offsetHeight;
createCanvas(sketchWidth, sketchHeight);
}
function draw() {
background(0,0,255);
}
function windowResized() {
sketchWidth = document.getElementById("square").offsetWidth;
sketchHeight = document.getElementById("square").offsetHeight;
resizeCanvas(sketchWidth, sketchHeight);
}
HTML:
<html>
<body>
<div id="squareContainer">
<div id="square">
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.0.0/p5.min.js"></script>
<script src="square.js"></script>
</div>
</div>
</body>
<style>
body {
background-color: black;
}
#squareContainer {
display: flex;
width: 50%;
height: 50%;
margin: 0 auto;
background-color: white;
}
#square {
box-sizing: border-box;
width: 80%;
height: 80%;
margin: auto;
background-color: red;
}
</style>
</html>
And here is a screenshot of what I’m currently rendering. As you can see, the blue square (my p5.js code) has the same dimensions as the red square (the div) but I would like it to also be overlapping at the same position.
See the documentation of createCanvas a p5.Renderer. Set the the container as the renders parent():
let renderer = createCanvas(sketchWidth, sketchHeight);
renderer.parent("square");

three.js dom element makes the whole page gets larger

I'm trying to build a 3D viewer with three.js, that has full height but leaves space for a side panel. The vertical layout works as expected, but as soon as I append the render's dom element, a horizontal scroll bar appears.
Attached is a minimal working example. I would expect to just see the (black) canvas element and the red body. But after v.append(renderer.domElement), the page gets larger (filled with blue, html element) and a horizontal scroll bar appears. It seems the page is larger than its body.
See https://jsfiddle.net/5jnvt4jh.
Has anybody an idea, what may be happening there? I couldn't find any margin or padding with Chrome and Firefox. Thanks :).
MWE
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<style>
html {
background-color: blue;
}
body {
margin: 0px;
height: 100vh;
background-color: red;
}
#viewer {
height: 100%;
width: 80vw;
background-color: green;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/86/three.min.js"></script>
</head>
<body>
<div id="viewer"></div>
<script>
var v = document.getElementById('viewer');
var renderer = new THREE.WebGLRenderer();
v.append(renderer.domElement);
renderer.setSize(v.clientWidth, v.clientHeight);
</script>
</body>
</html>
Change style of body to:
body {
margin: 0px;
height: 100vh;
background-color: red;
overflow:hidden;
}
jsfiddle: https://jsfiddle.net/raushankumar0717/5jnvt4jh/2/

CSS keeping image ratio, not working with Chrome

So the main idea is to keep this black image in the top left corner (with a ratio 16:9) and fill the remaining space with a "tomato" div. the solution I had found works fine on FF and even IE but breaks under Chrome and Opera (webkit). I'm not entirely sure what do I need to change..
Here's a link to jsfiddle (it doesn't work there well, so I'm adding the whole code below as well).
<!DOCTYPE html>
<html lang="en">
<head>
<style>
.body{ margin: 0px; }
.container {
position: fixed;
height: 100%;
width: 100%;}
.imgHor {width:100%; display:block;}
.moreSpaceHor {width: 100%;}
.lessSpaceHor {
background: tomato;
height: 100%;}
.imgVer { height: 100%; }
.moreSpaceVer {display: inline; float:top;}
.lessSpaceVer {
#top: 100%;
width: 100%;
float:top;
height:100%;
display: inline;
background: tomato;
position:absolute;
}
</style>
<script>
var timeout=-1;
function manageResizing(){
window.clearTimeout(timeout);
timeout=setTimeout(resizeView,128);
}
function resizeView(){
var img=document.getElementById("imgResizer");
var typeOrient = (9*window.innerWidth > 16*window.innerHeight);
var typeClass = img.className =="imgVer";
//if class and orientation are the same -> quit
if(typeOrient == typeClass) return;
var mSpace=document.getElementById("moreSpace");
var lSpace=document.getElementById("lessSpace");
img.className = typeClass ? "imgHor" : "imgVer";
lSpace.className = typeClass ? "lessSpaceHor" : "lessSpaceVer";
mSpace.className = typeClass ? "moreSpaceHor" : "moreSpaceVer";
}
</script>
</head>
<body class="body" onload="manageResizing();" onresize="manageResizing();">
<div class="container">
<div id="moreSpace" class="moreSpaceHor">
<div style="position:fixed; top:0px; color:white;">PIOTR</div>
<img class="imgHor" id="imgResizer" src="http://oi62.tinypic.com/j9vsj7.jpg"></img>
</div>
<div id="lessSpace" class="lessSpaceHor">KOZAK</div>
</div>
</body>
</html>
//edit
Some more info, it kind of work on Chrome/Opera, it breaks when you try to resize horizontally.. although when you refresh the window it's back as it should be :/
I get an output similar to yours by calling the javascript outside of an onReady() block. Make sure the javascript is called after the document has loaded.
Ok it's been solved now, I followed the idea here about attaching a new method responsible for making Chrome to redraw the page:
Force DOM redraw/refresh on Chrome/Mac
var forceRedraw = function(element){...}
Now it's fine among all browsers.

CSS Relative Position/Normal Position Question

According to w3schools, the relative position value is defined as follows.
relative - The element is positioned relative to its normal position, so "left:20" adds 20 pixels to the element's LEFT position.
I know that I can get the DOM object of whatever I positioned relatively and using that, I can get the left or top position w/ respect to the origin.
My question is, how can I get the "normal" position?
Thanks,
mj
Maybe, I misunderstand your question, but wouldn't this just be simple subtraction of the relative offset?
"normal" position is where the element will be positioned with left:0; top:0;. You can get this position by substracting the offset from the current position (tested in Chrome):
<!DOCTYPE html>
<html>
<head>
<title>Example</title>
<style type="text/css">
#container { width: 100px; height: 100px; margin: 100px auto; border: 1px solid red; }
#item { position: relative; top: 10px; left: 10px; width: 80px; height: 80px; border: 1px solid green; }
</style>
<script type="text/javascript">
window.onload = function () {
var container = document.getElementById('container');
var item = document.getElementById('item');
var computed = window.getComputedStyle(item);
item.innerHTML = 'Normal: (' + (item.offsetLeft - parseInt(computed.left))
+ ', ' + (item.offsetTop - parseInt(computed.top) + ')');
};
</script>
</head>
<body>
<div id="container"><div id="item"></div></div>
</body>
</html>
to normal position just set position value to: static
position:static

Categories

Resources