我有一个固定位置的标题,当用户向下滚动时(类似于https://medium.com/@sunknudsen/brute-forcing-your-very-own-vanity-onion-address-at-11-646mh-s-9a9c1fa93663#368a),该标题会“向下滑动以隐藏”。
问题在iOS上,当浏览器滚动到页面加载时哈希(例如,在Medium上为#368a
)时,某些内容(例如在Medium上为How to get your very own vanity onion address?
)出现在标题下方。
我希望处理(覆盖)默认的滚动到哈希逻辑(类似于event.preventDefault()
之类的东西),以便更好地控制滚动位置,并考虑标头的高度。
我能够使用以下逻辑在React上处理页内导航。
const scrollWithOffset = (element: HTMLElement, offset:number) => {
let offsetTop = element.getBoundingClientRect().top;
const elementPosition = offsetTop - offset - 20;
window.scroll({
top: elementPosition,
left: 0,
behavior: 'smooth'
});
};
<HashLink
to={props.href}
scroll={el => scrollWithOffset(el, 104)}
smooth
>{props.children}</HashLink>
很乐意将相同的逻辑应用于默认滚动,以在页面加载时实现哈希行为。
答案 0 :(得分:2)
在这种情况下,我希望您的幻灯片向上隐藏标头会向上滑动并隐藏,作为定义方式的一部分。
如果没有,您可以通过查看DOMContentLoaded
并在那一刻触发向上滑动隐藏行为来响应window
和load
window.scrollY
事件
如果您的目标是浏览器不要滚动到该元素,那么这对我有效(iOS Safari,Chrome和Brave):
window.addEventListener("DOMContentLoaded", function() {
if (location.hash === "#foo") {
setTimeout(function() {
window.scrollTo(0,0);
}, 0);
}
});
它将哈希保留在URL中,但将窗口滚动到顶部。我的实验中没有看到闪光灯,但是您的行驶里程可能会有所不同。
答案 1 :(得分:0)
由于@ T.J.Crowder和this question的宝贵反馈,我能够将一个React组件放在一起,该组件可以覆盖浏览器默认的滚动到页面加载时的哈希行为。
此组件的行为受Medium启发。页面最初加载时没有滚动到该元素,并且经过短暂延迟(一旦所有内容都有时间加载),它就会启动滚动。参见https://medium.com/@sunknudsen/brute-forcing-your-very-own-vanity-onion-address-at-11-646mh-s-9a9c1fa93663#368a。我喜欢这种延迟如何帮助使滚动内容更加生动。
秘密之处在于快速交换哈希所引用的元素的id
(这将禁用默认滚动滚动到哈希),并在DOM具有后恢复为真实的id
有时间加载。
export const scrollToWithOffset = (element: HTMLElement, offset:number, smooth?: boolean) => {
let offsetTop = element.getBoundingClientRect().top + window.pageYOffset;
let maxScrollTop = document.body.scrollHeight - document.body.clientHeight;
let options: ScrollToOptions = {
top: Math.min(offsetTop - offset, maxScrollTop),
left: 0,
};
if (smooth === true) {
options.behavior = 'smooth';
}
window.scroll(options);
};
interface ScrollToHashProps {}
interface ScrollToHashState {
element?: HTMLElement;
}
export class ScrollToHash extends Component<ScrollToHashProps, ScrollToHashState> {
constructor(props: ScrollToHashProps) {
super(props);
this.handleScroll = this.handleScroll.bind(this);
}
handleScroll() {
setTimeout(() => {
if (this.state.element) {
this.state.element.id = this.state.element.id.replace('-sth', '');
setTimeout(() => {
if (this.state.element) {
scrollToWithOffset(this.state.element, 0);
}
}, 1000);
}
}, 0);
}
componentDidMount() {
if (window.location.hash !== '') {
let element = document.getElementById(window.location.hash.replace('#', ''));
if (element) {
element.id += '-sth';
this.setState({
element: element
});
if (document.readyState === 'loading') {
window.addEventListener('DOMContentLoaded', this.handleScroll);
} else {
this.handleScroll();
}
}
}
}
componentWillUnmount() {
window.removeEventListener('DOMContentLoaded', this.handleScroll);
}
render() {
return null;
}
}