offsetTop / getBoundingClientRect().top of the element with position: sticky - scroll

When element with position: sticky reach his offset (top: 0, for example) and stops on the screen, i can't get his offsetTop properly, it shows more than necessary. At the same time, I can't get getBoundingClientRect().top, because it shows 0. Please take a look at this example:
https://jsfiddle.net/Lxud76ma/
When the element is sticky, it reserves its place in DOM, but the calculations are takes on its actual location.
So, how can I get coordinates of an element when it is sticky? Any ideas?

I think i find an answer, but correct me if somebody know more properly way.
Before calculating need to change position of element from sticky to static. Get his coordinates and bring him back to position: sticky.
https://jsfiddle.net/Lk74do8u/

You just need to calculate the getBoundingClientRect on the content/child of the sticky element.
<div class="sticky" id="sticky">
<div id="stickyContent">
...
</div>
</div>
I have updated your example:
https://jsfiddle.net/3962n0ov/

I had the same question just by curiosity .... but why we would need to get the position from the top of the page(offsetTop) since its always gonna be sticky to the top .... if its sticky to the top the position gonna be surely the window.scrollY position i tested it .... if its sticky to the left i dont really know the correct answer

Related

cdk-virtual-scroll-viewport,Any way to solve the blank area when user is scrolling quickly?

Especially obvious at the mobile.it will refresh immediately whenever the user scrolls, if user is scrolling quickly, it is hard to render?
you can reduce the itemSize to a lower number which should trick the scroller into rendering more rows above/below the current viewable area.
this should allow you to scroll faster but it will also take more cpu to run.
for ex:
change this
<cdk-virtual-scroll-viewport itemSize="50">
to this
<cdk-virtual-scroll-viewport itemSize="10">
You can use minBufferPx and maxBufferPx to reduce the blank space, as it's name indicates, you can buffer the list so user will see less blank space, for example you display 5 items (50px height for each) at a time, you can set minBufferPx to 250px (5 items) and maxBufferPx to 500px (10 items), when user scrolling and less then 5 items (240px) are buffered, it will load another 6 items (>500px). The downside of this is it consume more CPU.
I had some similar issue and came across these:
https://github.com/angular/components/issues/24943
https://github.com/angular/components/issues/20971
There is also a stackblitz linked in the second issue with the following hacky fix outside the cdk-virtual-scroll-viewport:
<div style="position: absolute; top:0; left:0; width:100%; height:100%; pointer-events:none"></div>
Try using templateCacheSize: 30 in *cdkVirtualFor.
try any greater value if not working.

Trying to change the width of a DOM from right to left

This seems like it would be an easy thing to figure out, but I can't seem to find what I'm looking for.
I want to animate the width of a div from right to left. It seems that this works left to right by default.
TweenMax.from($("#hero-container"),0.5,{width:0});
I tried to change the origin of the div, but that didn't seem to make a difference.
You need to align #hero-container to the right edge of whatever container it's in, and then animate the width.
I prefer using flexbox, but you can use position: absolute; right: 0; too if that tickles your fancy - But that presents a whole new level of problems, as it removes your element from the document flow.
Quick example using flexbox: https://codepen.io/jeppeolesen/pen/VyKebx

Skrollr.js relative key frames and best practices

I'm not sure if something I want to do is possible with skrollr, it doesn't seem to be possible but maybe I am misunderstanding. I would like to be able to describe keyframes in scroll points relative to other keyframe events, as in "start this animation event 500px after another element's animation event", and wondering what the best practice is. I am working on a large page of multiple sections of animated content. Each section scrolls to the top, then becomes temporarily fixed as multiple animations occur within the section on many key frames, then once that section's animations are done it scrolls up off the screen and the next section comes into view and does it's own animating, and so on (not unlike the main skrollr demo but more complex with many more animation events). My main issue is that I want to be able to easily edit in the future each sections' animation timings independently, for example to adjust little details here and there as needed, anticipating some back-and-forth with the artists and clients I'm working with. But when relying on an absolute scrollTop for all timings, this becomes problematic because one little timing change means I have to adjust all subsequent timings throughout the remainder of the page. To get around this I am using constants to denote the start of each animated section so that at least I can have each animated section be timed relative to its start, as in:
<style type="text/css">
#fixedanimatedcontent1, #fixedanimatedcontent2 {position: fixed;}
</style>
<section id="fixedanimatedcontent1" data-_fixedanimstart1--630="top:100%;" data-_fixedanimstart1="top:0%;" data-_fixedanimstart1-1500="top:0%;" data-_fixedanimstart2="top:-100%;">
<div data-_fixedanimstart1="width: 0%;" data-_fixedanimstart1-470="width: 100%"></div>
<img src="x.png" data-_fixedanimstart1-270="opacity: 0;" data-_fixedanimstart1-670="opacity: 1;" data-_fixedanimstart1-1170="opacity: 0;" />
</section>
<section id="fixedanimatedcontent2" data-_fixedanimstart2--630="top:100%;" data-_fixedanimstart2="top:0%;" data-_fixedanimstart2-2000="top:0%;" data-_fixedanimstart3="top:-100%;">
<img src="y.png" data-_fixedanimstart2-500="opacity: 0;" data-_fixedanimstart2-1000="opacity: 1;" data-_fixedanimstart2-1500="opacity: 0;" />
</section>
But even still, for complex sequences making a small timing change will be a bit of a mess, requiring at the least changing all key frame offsets within that section, and probably also changing constant values. Looking at my example above, 2 questions:
1) Is there a way to describe a relative keyframe that, let's say, begins 500px after section #fixedanimatedcontent2's top=0%? I know I can do data-top, but in my setup #fixedanimatedcontent2 becomes fixed at the top for some time once it hits the top. So how do I describe a keyframe that I want to begin 500px of scrolling after #fixedanimatedcontent2 hits data-top? Is this not possible within the syntax of "relative key frames" since offsets are only relative to element position in the viewport? If this were doable somehow, I wouldn't have to rely on constants so much...
2) How about a keyframe that begins when section #fixedanimatedcontent2's <img> reaches an opacity of 1? That way I could later if I needed make a change in the length of that <img>'s opacity interpolation without having to change all subsequent key frame timings. Pretty sure this is not possible but had to ask...
So: Am I misunderstanding what is the best way to do this sort of relative sequencing most efficiently? Or is using constants as in the example above the best practice?
(this was a really verbose post, sorry!)
It is very well possible in skrollrjs. I am telling nothing different from skrollrjs documentation. If you look carefully there, there are two modes for keyframes
absolute
relative
I think you wanted to use relative mode. So, i would answer each of your questions orderly.
1) Is there a way to describe a relative keyframe that, let's say, begins 500px after section #fixedanimatedcontent2's top=0%? I know I can do data-top, but in my setup #fixedanimatedcontent2 becomes fixed at the top for some time once it hits the top. So how do I describe a keyframe that I want to begin 500px of scrolling after #fixedanimatedcontent2 hits data-top? Is this not possible within the syntax of "relative key frames" since offsets are only relative to element position in the viewport? If this were doable somehow, I wouldn't have to rely on constants so much...
Answer:- It is possible to do that. In relative mode of work, you can define your relative targets and you can define css accordingly. So for your element #fixedanimatedcontent2 when reaches top i would use like following html
You can use following cheatseet for this. This is helpful.
https://ihatetomatoes.net/skrollr-cheatsheet/
I think all you need is already described if you read carefully
https://github.com/Prinzhorn/skrollr

Why does CSS2.1 define overflow values other than "visible" to establish a new block formatting context?

The CSS2.1 spec mandates that overflow other than visible establish a new "block formatting context". This strikes me as odd, that a property whose obvious purpose is to hide overflow without affecting layout, actually does affect layout in a major way.
It seems like overflow values other than visible combine two completely unrelated features: whether a BFC is created and whether the overflow is hidden. It’s not like "overflow:hidden" is completely meaningless without a BFC, because floats historically can overflow their parent element, hiding the overflow without changing the layout seems sensible.
What are the reasons behind this decision, assuming they are known? Have the people who worked on the spec described why this was decided to be the case?
I asked about this on the mailing list on your behalf; the thread can be found here. In summary, this has to do with scrolling content for the most part:
Fundamentally, because if the spec didn't say this, then having floats intersect with something that's scrollable would require the browser to rewrap (around intruding floats) the contents of the scrollable element every time it scrolls. This is technically what
CSS 2.0 required, but it was never implemented, and it would have been a huge problem for speed of scrolling.
-David
Most likely, it refers to scrollable content in a box that may occur outside of the float's parent but would intersect with the float. I don't think this is related to rewrapping content around a float within a scrollable container, as that already happens naturally, plus the float would clip into the container and scroll along with the rest of its content anyway.
Finally this makes sense to me. In fact, I'm going to provide an example here so hopefully it makes sense to you and anyone else who may be wondering. Consider a scenario involving two boxes with the same fixed height and overflow: visible (the default), of which the first contains a float that stretches beyond its parent's height:
<div>
<p>...</p>
</div>
<div>
<p>...</p>
<p>...</p>
</div>
/* Presentational properties omitted */
div {
height: 80px;
}
div:first-child:before {
float: left;
height: 100px;
margin: 10px;
content: 'Float';
}
Notice the similarity to one of the examples given in section 9.5. The second box here is simply shown to have overflowing content for the purposes of this answer.
This is fine since the content will never be scrolled, but when overflow is set to something other than visible, that causes the content to not only be clipped by the bounds of the box, but also to become scrollable. If the second box has overflow: auto, this is what it would look like had a browser implemented the original CSS2 spec:
Because of the float, attempting to scroll the content would cause the browser to have to rewrap it so it doesn't become obscured by the float (and what should happen to the part that scrolls out of the top edge?). It would probably look something like this when scrolled to the bottom:
The catch here is that the browser has to rewrap the content every time it repaints it during scrolling. For browsers that are capable of pixel-based smooth scrolling — which is to say, all of them — I can see why it would be a performance disaster! (And a user experience one, too.)
But that's for when the user can scroll the content, right? This would make sense for overflow: auto and overflow: scroll, but what about overflow: hidden?
Well, a common misconception is that a container with overflow: hidden simply hides content by clipping and cannot be scrolled. This is not completely true:
While scrolling UI is not provided, the content is still scrollable programmatically, and a number of pages perform just such scrolling (e.g. by setting scrollTop on the relevant element).
-Boris
Indeed, this is what it'd look like if the second box was set to overflow: hidden and then scrolled to the bottom with the following JavaScript:
var div = document.getElementsByTagName('div')[1];
div.scrollTop = div.scrollHeight;
Again, notice that the content would have to be rewrapped to avoid being obscured by the float.
Even though this wouldn't be as painful for performance as had scrolling UI been available, my best guess is that they made boxes with any overflow value other than visible generate a new BFC mainly for the sake of consistency.
And so, this change was brought about in CSS2.1, documented here. Now if you apply an overflow value other than visible only to the second box, what a browser does is push the entire box aside to make way for the float, because the box now creates a new block formatting context that encloses its contents, instead of flowing around the float. This particular behavior is specified in the following paragraph:
The border box of a table, a block-level replaced element, or an element in the normal flow that establishes a new block formatting context (such as an element with 'overflow' other than 'visible') must not overlap the margin box of any floats in the same block formatting context as the element itself. If necessary, implementations should clear the said element by placing it below any preceding floats, but may place it adjacent to such floats if there is sufficient space. They may even make the border box of said element narrower than defined by section 10.3.3. CSS2 does not define when a UA may put said element next to the float or by how much said element may become narrower.
Here's what it looks like with overflow: auto for example:
Note that there is no clearance; if the second box had clear: left or clear: both it would be pushed down, not to the side, regardless of whether it established its own BFC.
If you apply overflow: auto to the first box instead, the float is clipped into its containing box with the rest of the content due to its fixed height, which is set to 80px in the example code given above:
If you revert the first box to height: auto (the default value), either by overriding or removing the height: 80px declaration from above, it then stretches to the height of the float:
This happens to be new in CSS2.1 as well, in that an element with height: auto that generates a new block formatting context (i.e. a block formatting context root) will stretch vertically to the height of its floats, and not just enough to contain its in-flow content unlike a regular box. The changes are documented here and here. The change leading to the side-effect of shrinking the box so that it does not intersect the float is documented here.
In both of these cases, no matter what you do to the second box, it will never be affected by the float because it has been restricted by the bounds of its container.
I know this will be a speculative answer, however after reading the specifications a few times here is my view on this:
What section 9.4.1 is talking about is any block element that does not fully contain or does not fill the containment space. For example when you float an element it is no longer filling 100% of the parent, like in-flow elements do. Inline blocks, table cells, and table captions are also elements that you can affect height and width but that are not intrinsically 100% of the parent (yes table>tr>td is one that would fill 100% of it's parent but it is designed to allow for multiple td's so the td doesn't count as it will automatically shrink to accommodate additional td's) this also applies to any overflow other than visible because it breaks the containment of the block element.
So if I am reading this correctly the way it works is the 9.4.1 section is referring to block elements that break the default containment rules of the block elements as specified by section 9.2.1

Div Float Issue: It seems that divs automatically clear:left

I have a series of images, all of which have width:400px, but have varying heights. They are in the following container:
#content {width:808px;margin:0 auto;margin-top:100px}
All the ODD images have the following code:
{float:left;clear:left;margin:2px}
All the EVEN images have the following code:
{float:right;clear:right;margin:2px}
In theory shouldn't every ODD image be on the left, stacked ontop of each other and every EVEN image should be on the right stacked on top of each other.
Instead I get this:
It's as though some of the images on the right are clear:left or clear:both, right?
Any thoughts?
Thanks
take, for example, this code:
<div>Airplane</div>
<div style="float: left;">Symba</div><div style="float:right;">Chewbacca(?)</div>
you wouldn't expect the top of Chewbacca(?) to line up with the top of Airplane! it will line up with the top of Symba.
Symba has float: left, so is forced below the Airplane. whether Airplane happens to be floating or not doesn't matter anymore.
I've seen layouts that do what you want, by applying float:left to ALL the elements, and then using some Javascript to tidy up the white space once the page is done loading (float: left on its own won't do it, as you may have already noticed). I don't like that solution myself, but the only other alternative I can think of is to pre-sort the images in to two columns, and split them accordingly:
<div style="float:left">
<div>Myst(?)</div>
<div>Airplane</div>
<div>Symba</div>
</div>
<div style="float:right">
<div>Coastline</div>
<div>Painter</div>
<div>Chewbacca(?)</div>
</div>
but if you want the columns to always be equal height, that may not work for you, unless you know the heights of the images in advance, and can put things into columns based on that. (loop over, keeping a tally of the current height, and always adding to the shorter column; something like that.)

Resources