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

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>

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>

CSS scale+animation blurs the image in Chrome

I have a large element that has multiple animated (rotating) images, and you can zoom in and out on the entire div (which changes its scale transform). However, if an image element is created while the div is zoomed out, when I zoom back in I can see that the image is very blurry, as if it the image was downscaled when the element was created. A possible workaround would be to hide & show the image every time I zoom, but that doesn't sound like the best solution.
Here's a snippet demonstrating the issue (fiddle). Click on the first link to get a blurred image (sometimes only breaks on the second click), and on the second link to get a good image.
$(".try-1").click(function() {
$(".image").remove();
$(".pos").css("transform", "scale(0.4)").append("<div class=\"image\"></div>");
setTimeout(() => {
$(".pos").css("transform", "scale(1.4)");
}, 500)
});
$(".try-2").click(function() {
$(".image").remove();
$(".pos").css("transform", "scale(1.4)").append("<div class=\"image\"></div>");
});
.clicky {
color: #00f;
cursor: pointer;
}
.clicky:hover {
text-decoration: underline;
}
.div {
position: relative;
width: 500px;
height: 500px;
background: #000;
}
.pos {
position: absolute;
left: 250px;
top: 250px;
}
#keyframes rotating-cw {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.image {
position: absolute;
left: -150px;
top: -150px;
width: 300px;
height: 300px;
background: url(http://i.imgur.com/grJ6I3k.png);
background-size: 300px 300px;
animation: rotating-cw 30s linear infinite;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span class="clicky try-1">Create & zoom in</span> | <span class="clicky try-2">Zoom in & create</span>
<div class="div">
<div class="pos">
</div>
</div>
use this:
.pos {
-webkit-perspective: 1000;
position: absolute;
left: 250px;
top: 250px;
}
This can be solved using requestAnimationFrame but a simpler and more straightforward solution is to tell the browser to again initialize the image's container
$(".try-1").click(function() {
$(".image").remove();
$(".pos").css("transform", "scale(0.4)").append("<div class=\"image\"></div>");
setTimeout(() => {
$(".pos").css("transform", "scale(1.4)");
// Here, after we scale up the element again append
// the .image element but first remove it
$(".image").remove();
$(".pos").append("<div class=\"image\"></div>");
}, 500)
});
JsFiddle

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

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.

Positioning a button on top of a canvas

I'm trying to position a font-awesome button on top of a canvas. My current markup:
<li id="container">
<i class="fa fa-plus"></i>
<canvas></canvas>
</li>
The container and the canvas are visible by default. When the user mouse-overs the container, the button also appears. However, it pushes the canvas downward, causing it to spill out of the container:
The container has position: absolute and I don't have any control over that (it's part of a plugin I'm using). I do have full control over the styling of the canvas and the button.
What makes this tricky is that the user can resize the container, and the button has to remain on the top center of it at all times. Currently that works fine, but I can't get it to also appear on top of the canvas.
Hover to see i.
*,
*:before,
*:after {
box-sizing: inherit;
}
html {
box-sizing: border-box;
}
html,
body {
height: 100%;
margin: 0;
padding: 0;
}
body {
background-color: #F72F4E;
}
#container {
position: absolute;
width: 50vmin;
height: 50vmin;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
background: rgba(0,0,0,.2);
}
#container:hover i {
opacity: 1;
transition: opacity .2s ease-out;
}
#container i {
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: 3;
text-align: center;
opacity: 0;
transition: opacity .2s ease-in;
}
#container canvas {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 100%;
border: 5px solid green;
}
<li id="container">
<i class="fa fa-plus">i</i>
<canvas></canvas>
</li>
Have you tried to utilize the z-index?
If you don't know what it is you can read up on it here: http://www.w3schools.com/cssref/pr_pos_z-index.asp
Essentially, you will have the button sit on top of all other elements.
Hope this gives some guidance.
Also! Just thought of this, try to mess around with the position property.
http://www.w3schools.com/cssref/pr_class_position.asp
The 'fixed' value will position your button relative to the DOM window, meaning other elements shouldn't have an effect on its position.
Resolved it by changing the font-awesome element to a div and setting its height to 0. It's z-index was already larger than that of the canvas.

div height and width 100% follows page screen size not the element size inside

I have
<div id=overlay>
<div></div>
</div>
the height and width of the outer div is set to 100%.
What happens here is, the 100% refers to the size of the element inside (inside div).
I have a dynamically changing element on inside div, and I wanted to be my outer div got the size of the page screen.
NOTE that these div (outer and inside) are a popup element. So I wanted to cover all other elements behind the popup that's why I need the 100% of the page behind.
this is my css for the outer div
#overlay {
visibility: hidden;
position: absolute;
left: 0px;
top: 0px;
width:100%;
height:100%;
min-height: 100%;
min-width: 100%;
height: auto !important;
width: auto !important;
text-align:center;
z-index: 1000;
background-image:url(template/popup-bg.png);
}
my js
function overlay(e)
{
el = document.getElementById("overlay");
el.style.visibility = (el.style.visibility == "visible") ? "hidden" : "visible";
}
Simply change the HTML to this
<div id='overlay' class='hideOverlay'>
<div></div>
</div>
Now on clicking simply change the class.
Change your js to this
function overlay(e)
{
$('#overlay').attr('class', 'showOverlay');
}
Check the following style
.showOverlay
{
background-color: red;
height: 100%;
left: 0;
top: 0;
opacity: 0.2;
position: fixed;
width: 100%;
z-index: 1001;
}
.hideOverlay
{
display:none;
}
Background-color is given just to check the div's visibility. Change it as per your choice.
It is nice to have some opacity for overlays to have a better look and feel effect.
Try to set:
position: absolute;
Something like this...
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;

Resources