Why does html child element disappears when rotating element in Webkit? - css

I am trying to rotate a container div in html so that all of it's child elements rotate with it.
document.addEventListener('DOMContentLoaded', function() {
var img = document.createElement('img');
var ctx = document.getElementById('canvas').getContext('2d');
var n = 73; // -58
var elContainer = document.getElementById('container');
var elDegrees = document.getElementById('degrees');
var setAngle = function(n) {
elContainer.style.transform = ''.concat('rotate(', n, 'deg)');
elDegrees.innerHTML = n;
}; // /setAngle()
document.getElementById('btnUp').addEventListener('mousedown', function() {
n++;
setAngle(n);
});
document.getElementById('btnDown').addEventListener('mousedown', function() {
n--;
setAngle(n);
});
img.onload = function() {
ctx.drawImage(img, 0, 0, 640, 360);
};
img.src = 'https://blog.codepen.io/wp-content/uploads/2012/06/Made-For-Codepen.png';
setAngle(n);
});
* {
box-sizing: border-box;
overflow: hidden;
}
#root {
position: relative;
width: 250px;
height: 150px;
}
#container {
position: absolute;
top: 0;
left: 0;
overflow: hidden;
width: 250px;
height: 150px;
transform-origin: center center 0px;
transform: rotate(90deg);
transform-style: preserve-3d;
background-color: #000000;
}
#child {
background-color: #00ff00;
position: absolute;
box-sizing: border-box;
overflow: hidden;
top: 60px;
left: 60px;
padding: 10px;
z-index: 2;
}
#canvas {
display: block;
width: 250px;
height: 150px;
position: absolute;
box-sizing: border-box;
overflow: hidden;
top: 0;
left: 0;
z-index: 1;
}
<div id="root">
<div id="container">
<div id="child">
TEXT ELEMENT
</div>
<canvas id="canvas" style="" width="640" height="360"></canvas>
</div>
</div>
<button id="btnDown">-1 degree</button>
<button id="btnUp">+1 degree</button>
<span id="degrees"></span> degrees
<p>
In Chrome or Safari, if the container is rotated greater than 73 degrees or less than -58 degrees, to absolute positioned child div with text disappears. Why?
</p>
For some reason when the container div is rotated past 73 degrees or -58 degrees in Chrome or Safari, the child div element disappears behind the canvas element. This happens with both canvas elements and video elements. This problem does not happen in Firefox.

Have you tried putting the same webkit rotation on the child too? And possibly floating the child might help. Not 100% sure. Or, you may need to specify which browsers you are using within the webkit.

Related

How to Circumscribe a square in a circle CSS [duplicate]

I've looked into this a fair bit but can't seem to find a good, solid answer to find how to make a responsive circle around a div element of variable height.
It's easy to make a simple responsive circle using vw units.
<div style="height:20vw; width:20vw"></div>
However, I'm looking to use a min-height of an element and have a circle around this div.
Another way to create a responsive circle is using something like the snippet below, but again I can't adapt this to work for a variable height (again, I can't use vh units as the div will change in height.
.square {
position: relative;
width: 10%;
background: gray;
border-radius: 50%;
}
.square:after {
content: "";
display: block;
padding-bottom: 100%;
}
.content {
position: absolute;
width: 100%;
height: 100%;
}
<div class="square">
<div class="content">
</div>
</div>
I am trying to create something like the below, where the circle will never cut into the corners of the div (with around a 10px padding). I personally was trying to avoid javascript and would have preferred a css only approach, but it seems it's unavoidable. Maybe the only solution is to use a jquery to calculate the height of the element in order to apply this to a wrapper element?
I was playing around with this:
.square {
position: absolute;
top: 50%;
display: inline-block;
left: 50%;
transform: translate(-50%, -50%);
min-height: 100px;
border-radius: 50%;
background: url('https://i.imgur.com/2dxaFs9_d.webp?maxwidth=640&shape=thumb&fidelity=medium');
background-size: 100% 100%;
padding: 20px;
}
.content {
width: 300px;
min-height: 100px;
background: tomato;
}
<div class="square">
<div class="content">
Hello!<br>
<br><br><br>This has a variable height but fixed width<br><br><br>Hello
</div>
</div>
Clip-path can easily do this if you consider solid coloration.
Resize the element and the circle will follow:
.box {
width: 200px;
height: 200px;
overflow: hidden;
resize: both;
background: blue;
box-shadow: 0 0 0 200vmax red;
clip-path: circle(71%);
margin: 100px auto;
}
<div class="box"></div>
Related question to understand the magic number 71%: clip-path:circle() radius doesn't seem to be calculated correctly
To use an image we can consider pseudo elements. You can also rely on calc() to add the offset:
.box {
width: 200px;=
resize: both;
clip-path: circle(calc(71% + 10px));
margin: 100px auto;
position: relative;
font-size:35px;
color:#fff;
}
/* the background layer */
.box::before {
content:"";
position: absolute;
z-index:-1;
top:0;
left:0;
right:0;
bottom:0;
background:blue;
}
/* the image layer */
.box::after {
content:"";
position: fixed; /* to make sure the image cover all the screen */
z-index:-2;
top:0;
bottom:0;
left:0;
right:0;
background:url(https://picsum.photos/id/1015/1000/1000) center/cover no-repeat;
}
<div class="box" contenteditable="true"> Edit this<br>text </div>
I tried my hardest to figure this out with pure css. Though the problem with css I could not figure out how to calculate the diameter of the circle based on the content div size; the length from top left corner to bottom right corner of the variable height div.
I'm not sure if can be done using the calc() css function.
But I did manage to do it with a little jquery (which could easily be changed to pure javascript if you are not using jquery).
See working resizable example below (follow my comments in code)
Note: If you are using internet explorer the resizable demo content div will not resize.
// circumscriber for variable size divs
function circumscriber() {
// for each variable size div on page
$(".variable-size").each(function() {
// get the variable size div content width and height
let width = $(this).outerWidth();
let height = $(this).outerHeight();
// get the diameter for our pefect circle based on content size
let diameter = Math.sqrt(width ** 2 + height ** 2);
// extra 15 pixel circle edge around variable size div
let edge = 15;
// add current circle size width css
$('.circle', this).css({
'width': (diameter + (edge * 2)) + 'px'
})
});
}
// run the circumscriber (you might wana do this on ready)
circumscriber();
// if the window is resized responsively
$(window).on('resize', function() {
circumscriber();
});
// for demo purpose to fire circumscriber when resizing content
// not needed for real thing
$('.content').on('input', function() {
this.style.height = "";
this.style.height = ( this.scrollHeight - 30 ) + "px";
circumscriber();
}).on('mouseup', function() {
circumscriber();
});
/* variable size container to be circumscribed by circle */
/* none of these styles are required, this just to center the variable size div in the window for demo purposes */
.variable-size {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
/* resizable text area for demo */
/* again not needed */
.variable-size .content {
padding: 15px;
background: #fff;
resize: both;
overflow: auto;
color: #000;
border: none;
width: 200px;
font-weight: bold;
}
.variable-size .content:focus {
outline: 0;
}
/* child circle div css */
.variable-size .circle {
position: absolute;
background-image: url('https://i.imgur.com/2dxaFs9_d.webp?maxwidth=640&shape=thumb&fidelity=medium');
background-position: center center;
z-index: -1;
border-radius: 50%;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
transition: all 0.5s ease;
width: 0;
}
/* fast way to make circle height the same as current width */
.variable-size .circle:before {
display: block;
content: '';
width: 100%;
padding-top: 100%;
}
/* demo window css */
HTML,
BODY {
height: 100%;
min-height: 100%;
background: black;
position: relative;
font-family: "Lucida Console", Courier, monospace;
}
<div class="variable-size">
<textarea class="content" rows="1" placeholder="TYPE TEXT OR RESIZE ME ↘"></textarea>
<div class="circle"></div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
See jsfiddle here... https://jsfiddle.net/joshmoto/6d0zs7uq/
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.arc(100, 75, 50, 0, 2 * Math.PI);
ctx.stroke();
Source: https://www.w3schools.com/
You could use flex display and insert empty flex-items around the inner div and use flex-basis to fix their width.
Try this
.square {
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
min-height: 100px;
border-radius: 50%;
background: black;
background-size: 100% 100%;
padding: 20px;
}
.content {
width: 300px;
min-height: 100px;
background: tomato;
}
.emptyDiv {
flex-basis: 120px
}
<div class="square">
<div class="emptyDiv"></div>
<div class="content">
Hello!<br>
<br><br><br>This has a variable height but fixed width<br><br><br>Hello
</div>
<div class="emptyDiv"></div>
</div>

Fix (glue) the position of % values on parent resize

I have a div that sits at 15% width of the screen. On click, that width increases to 100%. It's basically a pop-out content area.
In order to center the icons inside of the original 15% width parent in a nice, responsive manner, they are set as such:
.parent
position: relative;
width: 15%;
.icons;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
This basically creates an aside on the left with an icon toggle. The icons are centered inside of parent. But, when the icon is clicked I resize the parent to slide out and become width: 100%;. All of a sudden, those nice percentage values change relative to the parent and move into the center of the screen. I want to freeze them so they don't move! In other words, I would like them to stay in the position they were in when the parent div was 15%.
Fiddle: https://jsfiddle.net/ra6qa9jf/
The easiest solution would be to remove the icon div from the red box and give it a new parent. Then style the new parent to always have a width of 15% and to have position absolute so that it appears as a layer over the red box. So your new HTML might be:
<div class="parent"></div> //This is the red box, same styling as before
<div class="parent-2"> //This is the new parent container for the icons
<div class="icons">
<i class="fa fa-plus"></i>
</div> //This is the icon, same as before
</div>
And the corresponding new CSS:
.parent-2 {
position: absolute;
width: 15%;
height: 100%;
top: 0px;
left: 0px;
}
Lastly you'd just need to update your javascript so that the onClick listener changed the correct div width:
(function () {
var parent = document.getElementsByClassName('parent')[0];
var icons = document.getElementsByClassName('icons')[0],
toggle = false;
icons.addEventListener('click', function(event) {
toggle = +!toggle;
if (toggle) {
parent.style.width = "100%";
} else {
parent.style.width = "15%";
}
});
}());
Refer code:
(function() {
var parent = document.getElementsByClassName('parent')[0];
var icons = document.getElementsByClassName('icons')[0],
toggle = false;
icons.addEventListener('click', function(event) {
toggle = +!toggle;
if (toggle) {
parent.style.width = "100%";
} else {
parent.style.width = "15%";
}
});
}());
.parent {
position: relative;
width: 15%;
height: 100%;
background-color: red;
transition: width 400ms ease-in-out;
}
.parent-2 {
position: absolute;
width: 15%;
height: 100%;
top: 0px;
left: 0px;
}
.icons {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: white;
font-size: 60px;
}
.icons:hover {
cursor: pointer;
}
body,
html {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"/>
<div class="parent"></div>
<div class="parent-2">
<div class="icons">
<i class="fa fa-plus"></i>
</div>
</div>

CSS square with dynamic height

I need to make a div square. The height of the div is dynamically changing and I want the width to be equal to the height. I have seen a lot of solutions to set the height to be equal to the width (with padding-bottom on pseudo-elements), but I need it the other way arround. Is this possible with pure CSS?
No .... well, there is this trick, where one use a hidden image
div {
display: inline-block;
height: 170px;
background: red;
}
div img {
visibility: hidden;
height: 100%;
}
<div>
<img src="http://placehold.it/50">
</div>
Updated
And here is a script version, that also keep it within the width
Stack snippet
(function (d,t) {
window.addEventListener("resize", throttler, false);
window.addEventListener("load", throttler(), false); /* run once on load to init */
function throttler() {
if ( !t ) {
t = setTimeout(function() {
t = null;
keepSquared(d.querySelector('.container'),
d.querySelector('.squared'));
}, 66);
}
}
function keepSquared(co,el) {
var s = window.getComputedStyle(co, null);
var m = Math.min(
parseFloat(s.getPropertyValue("width")),
parseFloat(s.getPropertyValue("height")));
el.style.cssText =
'width: ' + m + 'px; height: ' + m + 'px;';
}
})(document,null);
html, body {
height: 100%;
margin: 0;
}
.container {
position: relative;
width: 50%;
height: 50%;
top: 50px;
left: 50px;
border: 1px solid black;
box-sizing: border-box;
}
.squared {
background-color: red;
}
<div class="container">
<div class="squared">
</div>
</div>
Note: Since resize events can fire at a high rate, the throttler is used to reduced the rate so the handler doesn't execute expensive operations such as DOM modifications too often.

Overflow hidden with border radius not working in chrome

Not sure whether it is chrome specific bug or what, but when I am transitioning child element on a parent that has overflow hidden with border radius, the overflow is visible, while the transition is in place.
var wrapper = document.getElementsByClassName('wrapper')[0],
img = document.getElementsByTagName('img')[0];
/*
Click anywhere in the bordered area to toggle img
*/
wrapper.addEventListener('click', function() {
if (!img.className) {
img.className = 'hidden';
} else {
img.className = '';
}
}, false);
.wrapper {
overflow: hidden;
border-radius: 60px;
border: 1px solid salmon;
}
img {
width: 100%;
height: auto;
opacity: 1;
transition: opacity 1s ease;
}
.hidden {
opacity: 0;
}
<div class="wrapper">
<img src="http://static.planetminecraft.com/files/resource_media/screenshot/1211/y-you-no-work_1687402.jpg">
</div>
Here's a fiddle demonstrating the issue https://jsfiddle.net/827vuyqb/2/
Any solutions, workarounds for this?
Just position the wrapper element, and give it a z-index:
var wrapper = document.getElementsByClassName('wrapper')[0],
img = document.getElementsByTagName('img')[0];
/*
Click anywhere in the bordered area to toggle img
*/
wrapper.addEventListener('click', function() {
if (!img.className) {
img.className = 'hidden';
} else {
img.className = '';
}
}, false);
.wrapper {
overflow: hidden;
border-radius: 60px;
border: 1px solid salmon;
/*Position and z-index*/
position: relative;
z-index: 1;
}
img {
width: 100%;
height: auto;
opacity: 1;
transition: opacity 1s ease;
}
.hidden {
opacity: 0;
}
<div class="wrapper">
<img src="http://static.planetminecraft.com/files/resource_media/screenshot/1211/y-you-no-work_1687402.jpg">
</div>

How to make Canvas take 100% of remaining space?

Similar to how i want a div to take 100% height, 100% width, or both. i want a Canvas to take 100% width and 100% height:
(Link to JsFiddle for your perusal)
Markup:
<div id="canvasContainer">
<canvas id="myCanvas"></canvas>
</div>
CSS:
html {
width: 100%;
height: 100%;
}
body {
width: 100%;
height: 100%;
margin: 0;
}
#canvasContainer {
width: 100%;
height: 100%;
background-color: green;
}
#myCanvas {
width: 100%;
height: 100%;
}
Javascript:
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(canvas.width, canvas.height);
ctx.stroke();
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo(canvas.width, 0);
ctx.lineTo(0, canvas.height);
ctx.stroke();
Which results in something not taking 100% of browser window:
It works fine if you delete the Canvas:
Downside of that is then i don't have a Canvas.
Sizing a canvas element
If you stretch the canvas using CSS you will stretch the poor canvas which has a default size of 300x150 pixels to the whole screen - imagine you had an image of that size and which you did the same to - will look pretty bad.
Canvas content can not be stretched using CSS (it acts as an image that way). You need to explicitly set the pixel size of the canvas.
This means you will need to get the size of the parent container and set it as a pixel value on the canvas:
First off, to get rid of scroll bars etc.adjust the CSS you have:
body, html {
width: 100%;
height: 100%;
margin: 0;
padding:0;
overflow:hidden;
}
Now modify this rule:
#myCanvas {
background-color: green;
position:fixed;
left:0;
top:0;
}
Now reduce your markup to this only (if you want the canvas covering the whole sceeen you don't need a container other than the window):
<canvas id="myCanvas"></canvas>
Now we can calculate size:
var canvas;
window.onload = window.onresize = function() {
canvas = document.getElementById('myCanvas');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
And that's it.
Working demo (resize the window to see).
you can position absolute with 0 everywere:
canvas {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
Then just look in which element it is positionned, add position: relative to handle the block it covers. In your case probably: #canvasContainer, but maybe body if it's just for a single full screen.
I have had a similar issue in the past. My solution for it was setting overflow: hidden on the html
Fiddle Here
It gets rid of that little bit at the bottom, which if you inspect the pages is just a little bit extra, and not actually the height of the body. If anyone has some insight into what that is I am all ears.
Modified some of the examples here to get mine to work.
JSFiddle: http://jsfiddle.net/FT3pP/1/
JS:
$( document ).ready( function () {
SizeBackground();
} );
function SizeBackground(){
var canvas = $( "canvas#background" )[0];
fitToContainer( canvas );
}
function fitToContainer( canvas ) {
canvas.width = canvas.parentElement.clientWidth;
canvas.height = canvas.parentElement.clientHeight;
}
CSS:
body, html {
margin: 0;
width: 100%;
height: 100%;
padding: 0; }
div .container {
width: 100%;
height: 100%; }
div#pallette {
position: absolute;
top: 1px;
bottom: 1px;
left: 1px;
right: 1px; }
canvas#background {
position: fixed;
left: 0;
top: 0;
background: black; }
HTML:
<body>
<div id="pallette">
<div class="container">
<canvas id="background"></canvas>
<canvas id="middleground"></canvas>
<canvas id="foreground"></canvas>
</div>
<div id="stats"></div>
<div id="chat"></div>
</div>
</body>
Only includes i had:
<!-- Styles Sheets -->
<link href="Scripts/App.min.css" rel="stylesheet" />
<!-- Javascript -->
<script src="Scripts/jquery-2.1.0.min.js"></script>
<script src="Scripts/jquery-ui-1.10.4.min.js"></script>
<script src="Scripts/app.js"></script>

Resources