I am using Chrome version 41.0.2272.118.
There is a specific DIV on the page where if I change its contents by assigning its innerHTML or innerText then another DIV on the page is corrupted.
The result of the corruption is that the corrupted DIV's right padding is no longer drawn. However the DIV takes up the same space and it has the same width according to the developer tools. Additionally the corrupted DIV's bottom border is still drawn even though there is no div above it.
Oddly even though the div has the same width any text in the div is rewrapped and sentences in it take up more lines.
Changing the innerHTML or innerText of other DIVs on the page does not result in any corruption.
Sometime a later DOM modification can trigger fixing the corrupted DIV so that its right padding is again drawn and it is rewrapped the way it was before it was corrupted.
Here is a small example of the problem:
If an absolute div is within a table
If the content of the absolute div is changed using innerHTML in an asynchronous callback
And this was done before the asynchronous callback `document.body.style.cursor = "progress";
Then all cells in the first column of the table will be painted with the wrong width for the background
HTML:
<table>
<tr>
<td>
<div class="wrapper">
<div id="twoandthree">
<div id="two">two</div>
<div id="three">three</div>
</div>
</div>
</td>
</tr>
</table>
<button id="button">update two</button>
CSS:
#twoandthree {
position:relative;
min-width:80px;
overflow:hidden;
}
#two {
position: absolute;
white-space:nowrap;
display:inline-block;
}
#three {
float: right;
position:relative;
display:inline-block;
}
table {
border-spacing: 10px;
}
.wrapper {
background: lightblue;
}
JavaScript:
var two = document.getElementById("two");
var button = document.getElementById("button");
button.addEventListener('click', function () {
document.body.style.cursor = "progress";
setTimeout(function () {
document.body.style.cursor = "";
two.innerHTML = "aaa";
}, 500);
});
I would appreciate any help with this.
Thank you
Sometimes I notice weird rendering quirks with Chrome as well. Try applying -webkit-transform: translateZ(0) to your CSS force GPU acceleration.
Here is some more info about it: http://aerotwist.com/blog/on-translate3d-and-layer-creation-hacks/
Related
On mouseover I want to move the "imgbox" to a specific absolute position (which might move it on top of the "i" image).
The second image ("newimg") loads, so that part works (including hiding it again in "onmouseout") but it's displayed below everything (like in the HTML code). It seems like setting imgbox.style.left and imgbox.style.top doesn't do anything. If I set "margin" instead, the image is displayed 200px to the right and 200px down from where it originally was (but still below everything else).
What did I miss? How do I move the "imgbox" at runtime with regular Javascript (no JQuery please!)?
function onHoverIn(url) {
var imgbox = document.getElementById("imgbox");
imgbox.style.visibility='visible';
var newimg = document.createElement("img");
newimg.src = url;
var oldimg = document.getElementById("i");
/*if(oldimg.addEventListener){ //Removed so the snippet'll run
oldimg.addEventListener('mouseout',onHoverOut,false);
} else {
oldimg.attachEvent('onmouseout',onHoverOut);
}*/
imgbox.innerHTML='';
imgbox.appendChild(newimg);
imgbox.style.left = '200px';
imgbox.style.top = '200px';
//imgbox.style.marginLeft = '200px';
//imgbox.style.marginTop = '200px';
}
#imgbox {
position : absolute;
border: 1px solid #999;
background : #FFFFFF;
filter: Alpha(Opacity=100);
visibility : hidden;
z-index : 50;
overflow : hidden;
}
<img id="i" src="https://i.pinimg.com/originals/53/02/a4/5302a4c318139bf5753c433b1f4c6aa8.jpg" alt="DP" onmouseover="onHoverIn('https://i.pinimg.com/originals/b2/1b/07/b21b0738ea390fc56a4d3efe76ab88de.jpg')">
<p>Long Teeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeext<br><br><br><br><br>END TEEEEEEEEEEEXT</p>
<div id="imgbox"></div>
Sorry, the images are pretty big, so not sure how well it'll work. I tested the code with Firefox 85.0, Chrome 88, IE and Edge by simply double-clicking the .html file and the positioning doesn't work properly in any of them.
This was quite a bit harder than I thought it would be, made some changes to your code. Hope this still works for you.
NOTE: I implemented an onHoverOut locally and noticed that when I moved my mouse around on the image it would flicker. This happens because the new image is loaded and once moving again the old image registers a onHoverOut (because you hover on top of the new image) which would then remove the new image, at which point the old image registers the onmouseover again and adds the new image. This would keep looping for as long a you move the mouse around.
function onHoverIn(url) {
var imgbox = document.getElementById("imgbox");
imgbox.style.visibility='visible';
var newimg = document.createElement("img");
newimg.src = url;
var oldimg = document.getElementById("i");
if(oldimg.addEventListener){
oldimg.addEventListener('mouseout',onHoverOut,false);
} else {
oldimg.attachEvent('onmouseout',onHoverOut);
}
//imgbox.innerHTML='';
imgbox.appendChild(newimg);
}
function onHoverOut() {
console.log('onHoverOut: not implemented');
}
.article{
width:640px;
padding:0 16px;
}
.image-box{
position:relative;
width:100%;
height:0;
/* 16:9 */
padding-top:56.25%;
overflow:hidden;
}
.image-box img{
position:absolute;
top:0;
width:100%;
}
<div class="article">
<p>content before..</p>
<div id="imgbox" class="image-box">
<img id="i" src="https://i.pinimg.com/originals/53/02/a4/5302a4c318139bf5753c433b1f4c6aa8.jpg" alt="DP" onmouseover="onHoverIn('https://i.pinimg.com/originals/b2/1b/07/b21b0738ea390fc56a4d3efe76ab88de.jpg')">
</div>
<p>content after..</p>
</div>
I'm pretty sure this is currently infeasable.
I have an animation that involves an element moving from an absolute position to an inline one. For reasons, I can not know how the container is sized, nor how the element I'm animating is sized.
What I need to know is what the size of the HTML Element will be after the transformation, without any jittery drawing.
This makes the problem very difficult (likely undoable) because I have no way to know if adding the element will resize the parent, or resize the element itself.
What I need is a means of looking into the future.
const byId = (id) => document.getElementById(id);
#container {
height: 3em;
min-width: 50%;
background: teal;
}
#mystery {
background: purple;
}
<div id="container">
<div id="mystery">Some Text</div>
</div>
<button onClick='byId("mystery").style.position = "relative"'>Position Relative</button>
<button onClick='byId("mystery").style.position = "absolute"'>Position Absolute</button>
Currently, these are the only solutions I can imagine (they're all absurd):
Clone the entire webpage HTML, make the clone have opacity: 0; pointer-events: none and render what the future will be secretly.
Capture the paint data of the current page (basically screenshot), overlay that while secretly modifying the page, get my future, revert, and remove the screenshot overlay.
Similar to number 2, is there a way to ❄️freeze❄️ rendering of a page for 3-4 frames?
I remember seeing a "sizing worker" something-or-rather a long time ago. Couldn't find any information on it now, but it seems like it might be useful?
You can simply change the property, measure the sizes you want and then change the property back. JS is fast enough to do it all between renderings, as long as you keep it all in the same thread. Have you tried that at all?
Asker Edit:
Here's the code to prove it works.
function byId(id){ return document.getElementById(id); }
const tweenyEl = byId("tweeny");
function appendTweeny() {
tweenyEl.style.opacity = "1";
const startingWidth = tweenyEl.clientWidth + "px"
tweenyEl.style.position = "relative";
const targetWidth = tweenyEl.clientWidth + "px";
console.log(startingWidth, targetWidth);
tweenyEl.style.width = startingWidth;
requestAnimationFrame(() =>
requestAnimationFrame(() =>
tweenyEl.style.width = targetWidth
)
);
}
function resetTweeny() {
tweenyEl.style.position = "";
tweenyEl.style.width = "";
tweenyEl.style.opacity = "0.1";
}
#container {
display: inline-block;
height: 3em;
min-width: 150px;
background: teal;
}
#tweeny {
font-family: arial;
color: white;
position: absolute;
background: purple;
transition: all 0.5s ease;
opacity: 0.1;
}
<div id="container">
<div id="tweeny">I'm Tweeny</div>
</div>
<br>
<button onClick='appendTweeny()'>Append Tweeny</button>
<button onClick='resetTweeny()'>Reset Tweeny</button>
I would suggest cloning the page into an iframe and then positioning the iframe off the screen.
<iframe style="width:100vw;height:100vh;left:-101vw;positionabsolute"><iframe>
Also bear in mind that the user can zoom in-and-out at will! Different browsers might render the same thing in different ways. You really don't know how big an element will be until it does so.
I don't know if you can get anywhere by specifying display: none; ... whether or not the browser would bother to make these calculations for an object that isn't visible.
You can clone on the fly an element with same transformation with delay 0 and then calculate it's width and height, then do what you want with your actual element it's still animating
I made a div which has a background image of a face, I have designed div which contains a paragraph, 2 buttons and an input box.
I know this question has been asked quite often however my situation is different, I'd like for my div with the background image of a face to be clickable so that the div containing everything else slides out from the left.
What is the best method to do this?
HTML
<div id="image"></div>
<div id="container">
<p>I like nutella and croissants</p>
<input id="message" placeholder="type...." required="required" autofocus>
<button type="button" id="send">Send</button>
<button type="button" id="close">Close</button>
</div>
CSS
div#image { background: url(http://i.imgur.com/PF2qPYL.png) no-repeat; }
JQUERY
$(document).ready(function(){
$( "#image" ).click(function() {
jQuery(this).find("#container").toggle();
});
});
Using the article link posted by Raimov (which I actually came across in a Google search before realize he posted it as well ;), we can use jQuery to animate the width when the toggling element is clicked. Remember that a background does not add size to an element, so the toggle with the background image must have a height attribute set. Also, if you have long lines of text in the form, you'll have to wrap them yourself or use another method from the article.
http://jsfiddle.net/iansan5653/wp23wrem/ is a demo, and here is the code:
$(document).ready(function () {
$("#image").click(function () {
$("#container").animate({width: 'toggle'});
});
});
and this CSS is necessary:
div#image {
background: url(http://i.imgur.com/PF2qPYL.png) no-repeat;
height: 36px;
/*height needed to actually show the div (default width is 100%)*/
}
#container {
white-space: nowrap;
overflow: hidden;
}
I created a jsFiddle for you, where after clicking on img, the form hides to the left.
$("#image").click(function() {
var $lefty = $(this).children(); //get the #container you want to hide
$lefty.animate({
left: parseInt($lefty.css('left'),10) == 0 ?
-$lefty.outerWidth() : 0
});
The resource was taken from:
Tutorial how to slide elements in different directions.
So, I use this Javascript for hide - show effect:
function effect(id) {
var h = document.getElementById(id);
h.style.display = ((h.style.display != 'none') ? 'none' : 'inline');
}
HTML:
<div class="div">
<img src="http://i.imm.io/1jf2j.png"/>
Home
</div>
and CSS:
.div {
background: #000;
}
.div .url {
font-size: 17px;
}
Here you can test (and edit!) the code: http://codepen.io/anon/pen/dhHiw
JSFiddle doesn't work for me.
All is good. Except when you click on image. It's moved 1px above. Should I use another image?
Where is the problem? And possible solutions. Thank you!
You are basically removing the text element. Since the <div class="div"> does not have a set height, it depends on the elements inside it. When the text is not displayed (display=none), the div will resize to only the image.
You can fix this by either setting a height for the div, or by setting visibility=hidden for the text instead of display=none. When making it hidden, it still has the same dimensions, but it's invisible instead.
I have a small problem with jQuery slideDown() animation. When this slideDown() is triggered, it moves all stuff below downwards too.
How do I make all the stuff below the <p> being slid down, remain stationary ?
Note:
I would prefer a solution where the change is done to the <p> element, or to the slideDown call or something. Because in my actual page, there is a lot of stuff below the <p> being slid down, so changing/re-arranging all of them will take much longer for me ~
Demo # JSFiddle: http://jsfiddle.net/ahmadka/A2mmP/24/
HTML Code:
<section class="subscribe">
<button id="submitBtn" type="submit">Subscribe</button>
<p></p>
</section>
<div style="padding-top: 30px;">
<table border="1">
<tr>
<td>This table moves</td>
<td>down when</td>
</tr>
<tr>
<td>slideDown()</td>
<td>is activated !</td>
</tr>
</table>
</div>
JavaScript:
$(function () {
$("#submitBtn").click(function (event) {
$(".subscribe p").html("Thanks for your interest!").slideDown();
});
});
CSS:
.subscribe p {
display: none;
}
You can position that element as absolute:
.subscribe p {
display: none;
position : absolute; // add this line
}
Demo: http://jsfiddle.net/A2mmP/25/
What's happening with your existing code is that the element starts out as display:none; so it doesn't take up any space at all until you slide it in and it is changed to display:block, hence the movement down of the following elements.
With position:absolute it doesn't take up space in that sense, it overlaps: in fact in my updated version of your fiddle you can see a slight overlap into the table underneath - you can obviously tweak margins on the table or whatever to make it fit the way you want.
All you need is to give a fixed height of your .subscribe.
.subscribe {
height: 50px;
}
.subscribe p {
margin: 0px;
display: none;
}
Here is the jsFiddle : http://jsfiddle.net/xL3R8/
Solution
We will put the sliding element in a div element with a fixed width, preventing the document flow from being affected by the slide event.
HTML
<section class="subscribe">
<button id="submitBtn" type="submit">Subscribe</button>
<!-- this is the modified part -->
<div><p></p></div>
</section>
CSS
.subscribe div
{
/* We force the width to stay a maximum of 22px */
height:22px;
max-height:22px;
overflow:hidden;
}
.subscribe div p {
display: none;
/* We reset the top margin so the element is shown correctly */
margin-top:0px;
}
Live Demo
The problem is your CSS, it will render as block and push the other elements down when it slides in. Set it to be absolutely positioned and change the z-index to be in front, or behind.
.subscribe p {
display: none;
position: absolute;
z-index: 100;
}
Fiddle
.subscribe p {
display: none;
margin :0px;
}
IMO a good UI practice would be to, remove the subscribe button, and instead show a message there like :
"Hurray! You have been subscribed"
e.g
http://jsfiddle.net/UvXkY/
$(function () {
$("#submitBtn").click(function (event) {
$("#submitBtn").slideToggle('slow', function(){
$(".subscribe p").html("Thanks for your interest!").slideDown();
});
});
});
The actual problem your facing is display:none which will remove the space for the element p
where as visiblity:hidden and showing will get ride of this problem
Even though it will not give the proper slideDown effects so you can use the position absolute and keep some spaces for the p element will solve your problem.
one of the solution
.subscribe p {
position:absolute;
display:none;
}
.subscribe
{
position:relative;
height:50px;
}
FIDDLE DEMO