React scrollIntoView moves page only a little, not to the specified element - html

I want to scroll a page to specified div when the page loads. So here is my code to achieve the goal
const ref = useCallback((node: HTMLDivElement) => {
if (node !== null) {
node.scrollIntoView({behavior: 'smooth'})
}
}, [])
return (
<div>
//content
<div ref={ref}/>
</div>
)
but the page moves only a litle (about dozens of pixels from the top) when it loads but not to the specified element. When the any state on the page changes, then it moves to the specified element while I want this action on the first render.
Here is the screen of scrollbar place on the page after first render to better visualise what I mean saying that page moves only a little.
The scrollbar should be almost at the bottom where the specified div is placed while its just some pixes from the top od page.

You can do this by using a useRef to reference the element you want to scroll to and a useEffect to trigger the scroll when the component mounts.
import { useRef, useEffect } from "react";
const ref = useRef(null);
useEffect(() => {
if (ref.current === null) return;
ref.current.scrollIntoView({ behavior: "smooth" });
}, []);
return (
<div>
//content
<div ref={ref} />
</div>
);

Related

Is there a way to animate a <div> or <p> when its height changes because of a change in the html value?

Hello this is for a React/Gatsby website i'm working on.
I'm searching for a way to animate the child paragraph of a div using only CSS transition:
<div>
<p>{excerpt}</p>
</div>
Where excerpt is a variable i'm changing via Javascript when the cursor hovers the parent <div>.
This is the simplified React component. excerpt is a React state:
import React, { useState } from 'react'
const PostExcerpt = ({ post, featured }) => {
const [excerpt, setExcerpt] = useState(post.shortExcerpt)
const handleHover = (event, hover) => {
event.preventDefault()
if (hover) setExcerpt(post.longExcerpt)
else setExcerpt(post.shortExcerpt)
}
return (
<div
onPointerOver={(event) => {
handleHover(event, true)
}}
onPointerOut={(event) => {
handleHover(event, false)
}}
>
<p>{excerpt}</p>
</div>
)
}
export default PostExcerpt
The height of the <p> is adjusted automatically when content changes and i would like to animate the height change.
How can I transition height: 0; to height: auto; using CSS? doesn't apply because the height of my element is always set to auto. It simply changes because it follows content dimensions.

react-perfect-scrollbar - doesn't get updated for div holding accordions

I have a container div with a fixed height (depending on 100vh i.e. window height). Inside that container, I have few accordions added which will affect the height of the area runtime when they get opened/closed. I have implemented a react-perfect-scrollbar in my container div.
It doesn't get updated when I open/close any of the accordions automatically, but works fine when I manually scroll that area. I need the updation of the scrollbar to be done automatically - when I open/close the accordions as well as when I resize the screen.
Here is the working link: https://codesandbox.io/s/heuristic-pascal-2sqmt?file=/src/Example.js
If anyone has got some fixes for this, please guide.
the only solution I've found for this is from the documentation:
class Container extends Component {
...
render() {
return (
<ScrollBar
ref = {(ref) => { this._scrollBarRef = ref; }}
>
...
<ChildComponent
onUpdateSize = {() => { this._scrollBarRef.updateScroll(); }}
/>
...
</ScrollBar>
);
}
}
class ChildComponent extends Component {
handleClick = () => {
this.setState({
show: !this.state.show,
}, () => this.props.onUpdateSize());
}
render () {
return (
<div>
<button onClick={this.handleClick} />
{ this.state.show ? <div /> }
</div>
)
}
}

Deck.gl (Mapbox) StaticMap doesn't resize - overwrites everything on the screen

I am trying to add a basic deck.gl (mapbox static map) to a react project - which I can do; however, once the map is loaded it takes up the entire page and any other information is hidden behind the map. For example, I have some text in a <p> above the map and it gets hidden behind the map, when it should show just above it.
Any attempt to resize the div that the map sits in has been unsuccessful:
margin-top, height etc..
The class is called DglMap
class DglMap extends Component {
render() {
const layers = [];
return (
<div className="dglMapStyle">
<DeckGL
initialViewState={initialViewState}
controller={true}
layers={layers}
>
<StaticMap mapboxApiAccessToken={MAPBOX_ACCESS_TOKEN} />
</DeckGL>
</div>
);
}
}
added to a class called Content
class Content extends Component {
state = {};
render() {
return (
<div>
<BaseMap />
</div>
);
}
}
added to app.js
function App() {
return (
<Router>
<div>
<SomeText />
<Route exact path="/" component={MainContent} />
</div>
</Router>
);
}
export default App;
The file SomeText returns <div><p>SomeText</p></div>
The expected result is for the map to show underneath the text and not show on top of it. In another case I may want to resize the map to a specific size; for example 500x500px.
Any help appreciated and happy to elaborate.
Cheers!
In the part of Deck.Gl where the width and the height of the canvas is set,
there seems to be this code:
if (width || width === 0) {
width = Number.isFinite(width) ? `${width}px` : width;
this.canvas.style.width = width;
}
if (height || height === 0) {
height = Number.isFinite(height) ? `${height}px` : height;
this.canvas.style.position = 'absolute';
this.canvas.style.height = height;
}
which adds absolute positioning regardless of width and height, which might cause some fo your problems. Try adding left and top css styles to move the canvas. Resizing of the canvas should however work without any problems, see snippet below that works.
<DeckGL width={width} height={height}></DeckGL>

Absolutely position one element relative to its sibling element

I have this kind of situation. I am using Navigation bar wrapper that when clicked pull out an overlay across whole page.
For this to work all the elements that overlay goes across are sibling elements. One of those siblings is Header, Body, Footer...
I need to position navigation bar absolutely on top of Header element, so it doesn’t go out of boundaries of Header. If I put position absolute on Navigation bar it positions it relative to whole page since there is no parent element with position relative above it. If I put position relative on Header it doesn't help since it a sibling and not parent of Navigation bar.
Is it possible to absolutely position one element relative to its sibling element?
EDIT: Don't know how much code will help since it's a pretty big application and I bolied the question down to simple terms.
Scenes
const Scenes = (props: Props) => (
<NavigationWrapper routes={props.routes}>
<Header />
{renderRoutes(props.routes)}
</NavigationWrapper>
)
NavigationWrapper
/* #flow */
import React, { Component, Fragment, } from 'react'
import { NavLink, } from 'react-router-dom'
import Icon from 'semantic-ui-react/dist/commonjs/elements/Icon/Icon'
import Image from 'semantic-ui-react/dist/commonjs/elements/Image/Image'
import Menu from 'semantic-ui-react/dist/commonjs/collections/Menu/Menu'
import Sidebar from 'semantic-ui-react/dist/commonjs/modules/Sidebar/Sidebar'
import Responsive from 'semantic-ui-react/dist/commonjs/addons/Responsive/Responsive'
// Flow
import type { Element, } from 'react'
import logo from '../../../assets/img/logo.png'
import './navigationWrapper.local.scss'
const NavBarMobile = ({
children, onPusherClick, onToggle, rightItems, visible,
}) => (
<Sidebar.Pushable>
<Sidebar
as={Menu}
animation="overlay"
icon="labeled"
items={rightItems}
vertical
visible={visible}
>
<Menu.Item>
<Image size="mini" src={logo} />
</Menu.Item>
<Menu.Menu>{rightItems.map(item => <Menu.Item as={NavLink} {...item} exact />)}</Menu.Menu>
</Sidebar>
<Sidebar.Pusher dimmed={visible} onClick={onPusherClick} style={{ minHeight: '100vh', }}>
<Menu fixed="top" inverted>
<Menu.Item onClick={onToggle} position="right">
<Icon name="sidebar" />
</Menu.Item>
</Menu>
{children}
</Sidebar.Pusher>
</Sidebar.Pushable>
)
const NavBarDesktop = ({ rightItems, }) => (
<Menu>
<Menu.Item>
<Image size="mini" src={logo} />
</Menu.Item>
<Menu.Menu position="right">
{rightItems.map(item => <Menu.Item as={NavLink} {...item} exact />)}
</Menu.Menu>
</Menu>
)
const NavBarChildren = ({ children, }) => children
type State = {
visible: boolean,
}
type Props = {
children: Object,
}
class NavigationWrapper extends Component<Props, State> {
state = {
visible: false,
}
handlePusher = () => {
const { visible, } = this.state
if (visible) this.setState({ visible: false, })
}
handleToggle = () => this.setState({ visible: !this.state.visible, })
render(): Element<any> {
const rightItems = [
{
to: '/',
content: 'Kuci',
key: 'home',
},
{
to: '/o-nama',
content: 'O Nama',
key: 'aboutus',
},
{
to: '/usluge',
content: 'Usluge',
key: 'services',
},
{
to: '/kontakti',
content: 'Kontakti',
key: 'contacts',
},
]
const { children, } = this.props
const { visible, } = this.state
return (
<Fragment>
<Responsive {...Responsive.onlyMobile}>
<NavBarMobile
onPusherClick={this.handlePusher}
onToggle={this.handleToggle}
rightItems={rightItems}
visible={visible}
>
<NavBarChildren>{children}</NavBarChildren>
</NavBarMobile>
</Responsive>
<Responsive minWidth={Responsive.onlyTablet.minWidth}>
<NavBarDesktop rightItems={rightItems} />
<NavBarChildren>{children}</NavBarChildren>
</Responsive>
</Fragment>
)
}
}
export default NavigationWrapper
I am passing everything inside NavigationWrapper and render it as a children. It looks like this inside of DOM. As you can see in the console, ui menu is navigation bar, container__header is cover image. They are all siblings. I need to position ui menu relative to container__header, for example put it in the middle, but if I put for example bottom: 0, it must not go out of container__header.
Without seeing an example of your code, it's difficult to assist; however, it sounds like you want to use position: fixed as opposed to position: absolute.
Use JQuery to get the sibling-elements position after the page has completely loaded, then use jquery to set the CSS of your element to the exact position in which it needs to be. -another trick is to open Developer Tools in your browser and just look for the CSS section, and change it to each possible option for position and see if any of them or a combination of CSS attributes work for you. It's very easy in FireFox.

Angular Page Height Directive updating incorrectly

I am making a directive to set the height of a div equal to the height of the browser if the height of the div is less than the height of the browser.
I have created the following directive:
(function() {
var directive = function ($log, $window) {
function evaluate(element) {
var height = element.prop("offsetHeight");
var pageHeight = $window.innerHeight;
if (height < pageHeight)
{
$log.info("element height is less than page height, changing element height.");
element.css("height", pageHeight);
}
}
return {
restrict: "A",
link: function (scope, element, attrs)
{
//call it one time on load to handle first display
evaluate(element);
$window.addEventListener("resize",
function() {
$log.info("Resize directive called: evaluating window size.");
//window size changed, check if we need to adjust the height
evaluate(element);
});
//add a watch to trigger when the inside of the div changes
scope.$watch(function() { return element[0].childNodes.length }, function(values) {
evaluate(element);
});
}
}
};
angular.module('bootstrapApp')
.directive('fullSize', ["$log", "$window", directive]);
})();
and it is used in the following way:
<body>
<fullsize-background-image-1></fullsize-background-image-1>
<navbar-1></navbar-1>
<div class="container-fluid">
<div class="row">
<left-sidebar-1></left-sidebar-1>
<right-sidebar-1></right-sidebar-1>
<div class="col-xs-12 main" id="main" full-size>
<div ng-view="" autoscroll="true"></div>
<footer-1></footer-1>
</div>
</div>
</div>
....
</body>
My problem is, on page load, thing was working perfectly (without the scope.$watch statement). However, when angular routed to a different page, that content replaced what is in the div#main element. Sometimes the height of the new page is greater than the height of the previous page, causing my hidden <left-sidebar-1> to show.
What I need to do is, on initial page load have my full-size directive evaluate what the height of main should be. Then, when the page changes, have it re-evaluate it and remove the property if the content is bigger.
thanks.