Please test this demo.
The whole layout bounce back and forth at the beginning. It seems that it is waiting for Javascripts code interpretation.
I use this code to set the width.
document.getElementById("headc").setAttribute("style","width:800px;");
Don't set the initial width using Javascript. Do it directly in the HTML or CSS.
There are some instances where you want to set it with javascript like this but only when you need some initial effect like divs arriving at the center and so on. If you only need static initial declaration then you should use inline definition or css. For one, there is certain delay between loading DOM structure and firing javascript (in case you are firing js after the DOM is loaded which you should in this case). For fwo, you are forcing some additional computational power to be used where it is not necessary.
Related
I am a developer for a web application. In this application there is a certain scenario where there are multiple position:fixed elements, and canvases and a overflow:scroll element. In this scenario, scrolling is super slow on firefox when smooth scrolling is enabled.
From the user's perspective the solution is simply to disable smooth scrolling. However, as a developer I can't ensure that the user has done this.
Is there anywhere that I can tell firefox to not to use smooth scrolling for my website from javascript (or html)? Or is there any other known workaround for this?
I do understand that your question basically is how to disable smooth scrolling. however I will answer you a little differently to get this working.
Why different?
Even if you can detect smooth scrolling of users, you cannot force the user to disable it. In other words, you are trying to cover the problem instead of solving it. so lets solve it!
Intro: pixels-to-screen pipeline
On each frame the browser does the following steps to render the page on screen.
JavaScript. Typically JavaScript is used to handle work that will result in visual changes, whether it’s jQuery’s animate function, sorting a data set, or adding DOM elements to the page. It doesn’t have to be JavaScript that triggers a visual change, though: CSS Animations, Transitions, and the Web Animations API are also commonly used.
Style calculations. This is the process of figuring out which CSS rules apply to which elements based on matching selectors, e.g. .headline or .nav > .nav__item. From there, once rules are known, they are applied and the final styles for each element are calculated.
Layout. Once the browser knows which rules apply to an element it can begin to calculate how much space it takes up and where it is on screen. The web’s layout model means that one element can affect others, e.g. the width of the element typically affects its children’s widths and so on all the way up and down the tree, so the process can be quite involved for the browser.
Paint. Painting is the process of filling in pixels. It involves drawing out text, colors, images, borders, and shadows, essentially every visual part of the elements. The drawing is typically done onto multiple surfaces, often called layers.
Compositing. Since the parts of the page were drawn into potentially multiple layers they need to be drawn to the screen in the correct order so that the page renders correctly. This is especially important for elements that overlap another, since a mistake could result in one element appearing over the top of another incorrectly.
details and source: https://developers.google.com/web/fundamentals/performance/rendering/?hl=en
Step 1:
First step is to remove render costly css properties. You might not be able to remove alot, however you can replace rgba(255,255,255,1); with #fff which removes the alpha layer.
check this for more details: https://csstriggers.com/
some properties do not need to do a layout or a paint and there are less heavy than others.
Step 2:
Check for forced synchronous layout triggers. These happen when you force the browser to do a layout while its in the javascript step, then return to javascript, instead of walking smoothly along the pipeline on each frame. to do this, avoid getting layout attributes and setting them directly afterwards in a loop for example.
here is a list of what causes sync layout: https://gist.github.com/paulirish/5d52fb081b3570c81e3a
read more: https://developers.google.com/web/tools/chrome-devtools/profile/rendering-tools/forced-synchronous-layouts?hl=en
Step 3:
Move components on the page that need to be repainted regularly into new layers.
The browser needs to repaint every time you scroll or an animation is playing. to avoid a full page repaint and only repaint the part that is changing, move that part (ex parallax, navigation, animation) to a new layer on the browser (think about it like photoshop layers)
to do so use the will-change css property to tell the browser to move it to a new layer, and use transform: translateZ(0); if you want to force the broswer to move it.
Have you tried adding
backface-visibility: hidden;
to you fixed position elements?
I would rather fix the source of the problem. Often there is one small detail that creates a giant bottleneck and that is easy to fix with the change of one line of code or something. Note that you most probably won't need to reduce the "good looks" of the app at all; it's just a matter of avoiding the small but devastating-for-performance details of the browser's layout engine.
I'll make a guess and say that something on you web app is causing very large repaints and/or frequent reflows. Check for things like usage of offsetTop and position: fixed. Also using requestAnimationFrame instead of updating for every scroll event is something worth looking at. Here's a good guide on both finding and fixing scrolling performance problems.
Use inspect element to try and get a handle on the specific cause.
Also, if you've not installed FireBug, install it and use it instead of the default inspect element. This will give you more code details and allow you to step through the script to find the problem.
There also plugins for FireBug for various frameworks, which can aid the diagnostics if your using one of those frameworks.
We can make assumptions about the cause or come up with shotgun solutions; but, only you can diagnose your code to find the specifics.
If, for example, you put a CSS hover effect on an element, and also put a JS mouseenter event on it, which one will happen first? Is there any variance with this? Can you control it somehow? Is it possible to force them to execute in a particular order?
which one will happen first?
Notice that there is no such thing as a "CSS event". However, the behaviour is undefined; you could consider the CSS change and the JS event to happen at the same time. The relevant specs CSS Selectors 4, DOM 3 Events and HTML 5 point out the similarities between hover and mouseenter, but do not specify an order. Mouse event order is specified, but does not refer to CSS user action pseudo classes.
Is there any variance with this?
Yes, browsers are free to implement it either way. They could change the layout and redraw the page before they fire the JS events, or they could not. It should however not make much difference.
Is it possible to force them to execute in a particular order?
I personally would expect in the CSS to be applied already when the JS event handler is executed. Even if it was not yet computed, when querying styles (e.g. getComputedStyle(this)) a CSS recomputation is done so that you should always get the dynamic styles - see also When does reflow happen in a DOM environment?.
Try it out at http://jsfiddle.net/n4Z8H/. While most major browsers will yield the expected value (rgb(0, 0, 255), the blue :hover style), older IEs don't seem to do.
Depends a lot on how the browser works, and shouldn't be relied on. Most browsers should run the two at almost exactly the same time. If you want one to execute before/after the other, just control the CSS styling via JavaScript, for example on hover add a class and on not hover remove the class.
Although, if this is an actual issue you have, you're probably doing something wrong.
I'm searching for a jQuery plugin which adds custom scrollbars to a div. I know, there are tons of plugins like this out there and i tried about 10 of them now with no success because i need a plugin with some very special features and i was wondering if anyone knows one which comes near.
Its very important that the plugin does not poll for changes of its content (setInterval) or that it can at least be disabled.
It must be possible to tell the plugin to update itsself manually when i know that its contents has been changed
The most important thing (which seems to be the thing that is missing on most plugins): the original element reference must be kept.
So if i do:
$("#myElement").coolScrollbarPlugin();
$("#myElement").append("<h1>New Content</h1>");
$("#myElement").coolScrollbarPlugin("update");
the plugin needs to recognize this. In the best case, the plugin takes the jquery element i applied the plugin on as its content pane to recognize any manipulation done on the element.
What i can't do:
$("#myElement").coolScrollbarPlugin();
$("#myElement").coolScrollbarPlugin("getConentElement").append("<h1>New Content</h1>");
$("#myElement").coolScrollbarPlugin("update");
This limitation is due to the surrounding application framework which will do manipulations on the scrollable elements that i'm not able to affect.
Are there any plugins that you know matching all this criteria?
Are there other ideas on how to achieve this?
If you get scrollable element by id or assign element to variable before applying scrollbar, you can try jQuery Scrollbar. The only change that is made - element is wrapped into another element with the same classes (to apply CSS styles of source element's height/width & design for scrollbar).
You can disable content/container size cheking using option autoUpdate:false and call init function to recalculate scrollbar sizes after update.
Background:
I am using the skrollr plugin as part of a Rails project that is using Slim for markup.
The plugin requires data attributes for start and end points for scrolling animations. Here is an example:
#canvas-1 data-0="top:-80px;" data-1180="top:0px;"
The plugin will basically animate the top css from data-0 (scroll position 0px) to data-1180 (scroll position 1180px).
Question:
A few elements on the page that need to be animated are positioned below containers with varying heights. So, the data-xxxx can be different depending on the content in the preceding containers. I have a javascript function that figures out the height of all the preceding elements and returns a variable of what the data-xxxx should be. This is theoretically what the output should look like in Slim:
#logo.unit data-#{ "<script>logoPosition</script>" }="top:5px" data-#{ "<script>logoPosition + 200</script>" }="top:-8px;"
Slim errors. No matter how I try to add the inline javascript attribute - it errors. My current solution is all javascript (which replaced the attribute completely). However, I would like to know the proper way of doing inline javascript generated attributes.
Possible?
If I'm understanding you correctly, you can do this with skrollr alone. Read the docs about relative mode https://github.com/Prinzhorn/skrollr#absolute-vs-relative-mode
Like this (you get the idea):
#logo.unit data-top="top:5px" data-200-top="top:-8px;"
Using data-anchor-target="#logo.unit" you could even have the animation of other elements depend on the position of the logo.
Will the element be visible even for a blink of an eye If it is added to DOM and instantly removed?
var feed = $('<div class="entry"></div>').text(data.status).appendTo(app.twitter_feed);
console.log(feed.height());
feed.remove();
I've tried the above code on a few browsers and couldn't see the element. But is this behaviour consistent through all platforms/browsers?
After reading your previous question as well, it seems that you very badly want to calculate the display height of an element before actually displaying it. I 'm not entirely clear why you want to do this (it gives off a bad smell), but here's how to anyway.
Put a <div> in your page with height: 0, overflow: hidden, and the desired width of your element¹. Add the <div> we 're talking about inside that outer helper div (it will not show no matter what), and get its height after the browser performs layout. After that you can proceed however you want (e.g. by moving the inner <div> to another position in the DOM tree).
¹ it would be best to put it exactly where you want the .entry to end up (i.e. the .entry and the helper div will end up being siblings).
PS: It's always better for everyone if you mention your real purpose.
I can imagine a situation wherein for the browser to be able to compute the element's effective height, it will have to render it on the window, or at least have the element's box reflow against the current site layout. It might not be visible (as, yeah, it's instantly removed), but a situation like this will reflow the page, and the movement of the affected elements on the page can be seen.
Images come to mind, for example, because browsers generally have no idea what the dimensions of images are until they try to lay them out (correct me if I'm wrong there though).
So, no, I wouldn't say that this is consistent behavior.
Implement it like this. Make a clone of app.twitter_feed, and send it to hell (Coordinates: x:-30000, y:-30000) and try whatever you like there.
var cloneTWFeed = $(app.twitter_feed).clone();
cloneTWFeed.css("position", "absolute").css("top","-30000").css("left","-30000");
var feed = $('<div class="entry"></div>').text(data.status).appendTo(cloneTWFeed);
console.log(feed.height());
feed.remove();
You current code works just fine, but you never get to see the element, since just after you append it, you remove it.
The browser sees it, by the time that he takes to remove it, just after being appended.
See this working Fiddle Example!
There I've replaced the console.log with an alert() to force the browser to wait for my response, thus enabling me to see the element on the page.
Note: Also works fine with console.log(), given me the 18px of height.
You either have the remove() wrapped on a timer to actually see the element (visually), or if the HTML markup is to intense, or the desired effect is to only collect data from the element, place your element inside an hidden one, that way you can remove it whenever you've done collecting data from it.
If what you must acheive is an height measurement, try to add the element without visibility (see CSS:
http://reference.sitepoint.com/css/visibility)
In a zone of the page that causes no problems on the element flow.