I need to get the available height between the top and bottom elements. Currently, I am calculating it by
screenHeight - statusBarHeight - topElementHeight - bottomElementHeight.
This method is working, but I always have to look up if all the top and bottom elements are visible and account for that.
Is there any better method of getting this height?
Place a View element in between top and bottom elements and use onLayout prop to receive dimensions of this View.
render() {
<TopComponent />
<View onLayout={this.measureView} />
<BottomComponent />
}
measureView = (event) => {
console.log(event.nativeEvent.layout.height)
}
Make sure that the View occupies the entire space between top and bottom elements. You can use flexbox or absolute positioning for that depending on your current layout.
Related
I'm using DetalisList within ScrollablePane component to keep the header in view, and let the rows scrollable. However, this requires me to manually set the height of the scrollable container.
div.scrollable-container
ScrollablePane
DetailsList
When I investigate the DOM elements for DetalisList, I can see that it's wrapped inside a ViewPort element. The height of this element is the actual height of the sum of the height of all components that make up the list (column headers, rows. etc.). Thus, I want to be able to read this value and set the container height based on whether it exceeds a certain value or not.
Is there a nice to way to access the height of the ViewPort? I can always query the DOM, and find the element, but I'd like to avoid relying on the internal structure of the component.
So, far I could not find any information on this. I noticed DetailsList takes a prop called viewport, but I don't think this is what I want.
You can try by giving height in "vh" (viewport height) unit. For example,
const gridContainerStyle: IStackStyles = {
root: { height: "70vh", position: "relative" },
};
I have a collection of photos that uses React Virtualized's Grid element.
We've designed an indicator to appear during photo uploads. This hides and shows dynamically and is rendered via the cellRangeRenderer per these docs.
The tricky part has been getting the rest of the Grid items to respect the additional height added by this new element. The approach that's currently in place is to add the height of that element to the style.top of each element rendered in cellRenderer.
const adjustedTopOffset = style.top + heightOfTopElement;
That above calculation is done for each element. This correctly places all elements at the appropriate offsets. However, the height of the Grid does not adjust for the recalculation of the top offsets.
The consequence is that the bottom of the Grid is cut off by the adjusted top amount.
How do I correctly account for adjusted top offsets? Calling recomputeGridSize doesn't seem to do it.
Is adjusting the top offset in cellRenderer the correct approach for accounting for an additional top element? I'll clarify that this isn't a fixed element but rather one that needs to scroll with the Grid like the other elements.
Given that your cell heights are fixed, you should be able to overrides the default height style using the containerStyle prop, like so:
let containerStyle;
if (isTopElementVisible) {
containerStyle = {
height: rowHeight * rowCount + heightOfTopElement,
maxHeight: rowHeight * rowCount + heightOfTopElement,
};
}
I would like an image to become fixed where it is once it appears on screen during a scroll, but become unfixed if the user scrolls back up.
However, when I use a JS on scroll function to change the image position to fixed, it suddenly "jumps"/resizes, and I'm not sure why. My fix was to create variables that alter the width and left values of the image after it becomes fixed, but I want to do this will multiple images on a page and each one seems to require a different width and left adjustment. I'm not sure what is conceptually causing this issue. Simply resetting the width and left to their original values does not work. Does a fixed position resize and image.
Here is a jsfiddle of the issue. And here is the code. JS:
var sitckyImageWidth = "38.4%";
var normalImageWidth = "48%";
document.addEventListener("scroll", function(){
var windowTop = $(window).scrollTop();
var windowWidth = window.innerWidth;
var windowHeight = window.innerHeight;
//loop through each div and grab top/bottom/midpoint info and find id
$('.articles').each(function(i){
var top = $(this).offset().top;
var bottom = top+ $(this).height();
var midPoint = (bottom+top)/2;
var thisId = this.id;
var newId;
//use container div info to find media info
var newId = thisId+"Media";
var sectionImage=document.getElementById(newId);
var sectionImageTop = $(sectionImage).offset().top;
//if article is on the page, change position to fixed and set top position
if (top<=windowTop&&bottom>windowTop){
$(sectionImage).css("top","10px")
$(sectionImage).css("position","fixed")
//$(sectionImage).css("width",sitckyImageWidth)
}
//if container is not at top of the page, return to relative
if (bottom<=windowTop||(bottom>windowTop&&top>windowTop)){
$(sectionImage).css("position","relative")
}
})
}); //end scroll
Position fixed means that an element will have relative sizes and positioning in relation to the viewport, not their parent elements.
Specifically what is happening here is that your div with ID article1Media is set to have a width of 48%. When it has the CSS property of position: relative then that resolves as 48% of the width of it's containing element (the div with id article1) however when it is position fixed that resolves as 48% of the width of the viewport. Since there is an implicit 8px margin on the <body> element then these are different.
There are a few different solutions to this, and how you tackle it depends on how you want to build your site.
Example fix 1
A simple fix for your immediate example is to simply add the following CSS.
body{
margin:0px;
}
.image{
margin:8px;
}
https://jsfiddle.net/Chipmo/k56qkk5b/13/
This moves the implicit margin onto the image element. Of course you can set it to whatever you like, or omit it entirely.
Look into CSS resets for more information about overriding implicit default styles, though be warned that it is possible to cause problems with overzealous reset codes.
( Edit: To be clear the above code is definitely not a drop in code for this problem everywhere. It will only work on quite simple HTML pages like your jsFiddle. )
Example fix 2
Another technique you could consider is locking the width and height to it's initial values using jQuery .width() and .height() functions. This would be inflexible, and you would have to do extra work to make it responsive (for mobile etc), but could be appropriate in some circumstances.
Example fix 3
A more portable solution might be to eschew relative sizing in favour of fixed widths and then use CSS media queries for reponsivity. Something like this:
.image{
width:500px;
}
#media(min-width:800px){
width:300px;
}
Example fix 4
If you wish to preserve the 'fluid' nature of using percentages I would suggest looking into using calc along with an offset that gets applied when the position is fixed (so, you add a class when you make the image fixed) that adjusts the sizing appropriately.
.media.image-fixed{
position:fixed;
width:calc(48% - 8px);
}
See this example https://jsfiddle.net/Chipmo/6mu2Lt9g/2/
Above behavior is observed since because of applying the position property not because of the scroll.Please take a look at the following link Position Properties
Position Fixed : Fixed position elements relative to document not on
any parent container.Hence occupies the complete width available.
Position Relative: Relative positioned elements behaves relative to hosted
containers.And inner elements consumes the hosted parent width.
I'm looking for a JS / React solution to count height or lines number of draggable div blocks (having different width). Height is needed to calculate the content height inside dashed border which is equal to (viewport - draggable_blocks_height).
As you can imagine, calculation should work dynamically during the window sizing / changing resolution and during dragging the blocks / removing or adding to the draggable_blocks_container.
Any ideas, concepts or similar examples?
Thank you
https://www.npmjs.com/package/react-height
Or go npm shopping for any number of variations.
I would assign a ref to a wrapper div. Then write a function that gets the height of the ref and run that func on window resize. Something like...
<dif ref={(div) => this.Wrapper = div}>
{/* blocks */}
</div>
function calcHeight() {
const rect = this.Wrapper.getBoundingClientRect();
return rect.height;
}
componentDidMount() {
window.addEventListener('resize', this.calcHeight());
}
A bit confused on what you want to do, but if you want to mirror the height in another div, set the calculated height to state and then use a style prop to control the height of the 2nd div.
Let's say I have an <li> element inside a scrollable div and the scroll was set to show that element in the viewport.
I need to get the distance between that element and its scrollable parent, as shown in the picture above, but both element.getBoundingClientRect().top and element.offsetTop give me the wrong values. Can that be done?
I made a pen, to make things a little bit easier:
http://codepen.io/Darksoulsong/pen/LbYMex
A piece of my code:
document.addEventListener("DOMContentLoaded", function(event) {
var selectedEl = document.getElementById('consequatur-51');
var selectedElRect = selectedEl.getBoundingClientRect();
var sidebar = document.getElementById('sidebar');
sidebar.scrollTop = selectedEl.offsetTop - 60;
document.getElementById('offsetTop').innerText = selectedEl.offsetTop;
document.getElementById('rectTop').innerText = selectedElRect.top;
});
I found out how to make it work. Actually, #Dummy's answer gave me some important insights.
Basically, the formulae is:
childElementDistanceFromParentTop = actualChildElementDistancefromTop - parentElementDistanceFromTop
With these coordinates I can even tell if the element is visible in the viewport or not.
Updated pen: http://codepen.io/Darksoulsong/pen/rWawrZ
var parentTop = parentElem.getBoundingClientRect().top; // Initial parent's top distance from the top of the viewport;
var currentChildTop = childElement.getBoundingClientRect().top; // Initial child's top distance from the top of the viewport;
If you do var childParentDistance = Math.abs(parentTop - currentChildTop), you will get the initial distance between the child element and its parent. But as you scroll, you need to account for the scroll amount. Like this
var scrolledParentDistance= Math.abs(parentTop - parentElem.getBoundingClientRect().top);
and if you subtract scrolledParentDistance from childParentDistance, you will get the new distance between this child and its parent
I was in a similar situation, and I guess one of the missing parts was the distance that a human observer does not see; as scrollable containers usually hide their overflowing content. Hence I felt adding my answer may be useful, with a little example.
Find a way to programmatically scroll a parent element that hides content which overflows it and has:
position: fixed;
top: whateveryouwant;
height: 80%;
overflow-y: scroll;
in a way such that a specific child's top border is aligned with your parent's top.
With the CSS above you have a parent div which always fills 80% of your screen's height, with a getBoundingClientRect().top value which thus always stays the same for a given device.
You then need to build a formula where you can use parent.scrollTo(0,outputOfFormula); to scroll the parent in a way such that the targeted child's top is aligned with your parent's top.
#TrashCan was actually almost there, and he / she was right that what's missing is that you have to consider the amount by which the parent scrolled, to account for all possible cases. So all in all you have something like this:
------------------------------------ Viewport's Top
------------------------------------ Popup (Parent)'s Top
| |
| --- | Horizontal Level of Targeted Child's Top
| |
| |
------------------------------------ Popup (Parent)'s Bottom
------------------------------------ Viewport's Bottom
Which gives you:
d(Viewport's Top - Horizontal Level of Targeted Child's Top) = child.getBoundingClientRect().top
d(Viewport's Top - Popup (Parent)'s Top) = parent.getBoundingClientRect().top
d(Popup (Parent)'s Top - Horizontal Level of Targeted Child's Top) = d1 - d2
If you count the pixels on your screen that separate your parent's top form your child's top, you now get exactly d3. But d3 may not be the correct value to use to scroll down your parent to display the child at its top. If your Popup has already been scrolled down, d3 only represents a part of the actual distance of your parent's top to your child's top. Your child may actually be situated much much lower inside your Popup, so you'd be missing all of that distance needed to be scrolled down too. To thus complete the formula and get the actual distance we have to scroll our parent to display our child within its top, we have to add parent.scrollTop to d3. If we did not scroll the parent by any pixel, the scrollTop property will simply be 0.
Hence for this scenario, you need to use:
child.getBoundingClientRect().top - parent.getBoundingClientRect().top + parent.scrollTop
and then do
parent.scrollTo(0,result)
and you're covered for all cases of this scenario.