我有一个带有:target
页内锚点的固定标题,并且需要通过JavaScript或JQuery动态调整属性值,以便在调整窗口大小时在标题下直接保持相关:target
的位置,同时进行调整调整大小时上一部分的.container高度和.header_container
高度的变化。
最简单的解决方案似乎是::before
伪类的:target
伪元素,然后利用CSS自定义属性动态修改样式属性。
加载(或重新加载)页面时,我可以使用以下功能正确定位:target
,也可以将第一个:target
正确地放置在$(window).resize()
上,但是对于< cc>。
小提琴
简化代码:https://jsfiddle.net/chayanyc/g6p3549s/
响应式设计(简化):https://jsfiddle.net/chayanyc/wuk92dns/
代码段
CSS:
.header_container {height: 98px; margin: 0; padding: 0; position: fixed; top: 0; display: block; z-index: 100;}
.main {margin-top: 98px; width: 100%;}
:target::before {height: var(--target_position1); margin-top: var(--target_position2); content: ""; display: block; visibility: hidden;}
JavaScript:
var headerHeight;
function setTarget() {
headerHeight = document.getElementById('header').offsetHeight;
headerHeight1 = headerHeight + "px";
document.documentElement.style.setProperty('--target_position1', headerHeight1);
document.documentElement.style.setProperty('--target_position2', '-' + headerHeight1);
}
$(window).resize(function () {
setTarget();
});
$(document).ready(function () {
setTarget();
});
最佳答案
对于此问题还没有完整的解决方案,
因为您希望目标元素在文档调整大小时保留在原位,但是如果用户在页面上滚动,则无法知道停留在显示的第一行的相同第一个单词处。
所以在这里,当用户调整文档大小时,即使他之前进行过滚动,我也只是替换在顶部的同一目标上。
不需要此CSS部分(将其删除)
:target::before {margin: 0; content: ""; dis.....
并将您的jQuery更改为:
$(document).ready(function () {
// global info for menu -> target elememt
var InfoTarget = { ID: null, tempo:300 }
$('a').click(function(evt){
InfoTarget.ID = $(this).attr('href') // possible target elm
// check if InfoTarget.ID exist on page
let nbElements = 0
try { nbElements = $(InfoTarget.ID).length }
catch(err) { nbElements = 0 }
if ( nbElements != 1 ) {
InfoTarget.ID = null // not target element found
}
else {
evt.preventDefault() // disable auto scroll to target element
$('html').animate({
scrollTop: ($(InfoTarget.ID).offset().top - $('#header').outerHeight(true))
}, InfoTarget.tempo );
}
});
$(window).resize(function (){
if (InfoTarget.ID) { // if InfoTarget.ID exist <=> InfoTarget.ID != null
$('html').animate({
scrollTop: ($(InfoTarget.ID).offset().top - $('#header').outerHeight(true))
}, InfoTarget.tempo);
}
});
});
我的代码说明了一切,但是这里有一个完整的解释:
原理很简单:单击链接
<a href="#...">
激活目标css函数,以触发页面滚动到具有id =到初始href中包含的元素的元素。因此,此代码会拦截对页面上链接的任何单击,并且必须首先确定它是否是指向锚点的链接。
要确定这是否是页面上锚点的链接,只需测试页面的元素是否具有此值作为此
ID
(// check if InfoTarget.ID exists on page
)。由于这种测试也会产生错误,因此将该测试放在
try / catch
中。如果结果确实是锚点,则单击操作将被取消(使用
evt.preventDefault()
),这将阻止浏览器触发其自动滚动至链接;参考链接保存在对象变量(全局)中
var InfoTarget = {ID:null,速度:300}
见于:
InfoTarget.ID = $(this).attr('href') // possible target elm
其余的很简单,您必须向下滚动到锚点。
根据页面的宽度和之前的元素,浏览器会不断重新计算页面上每个标签的位置,并且
$(element).offset().Top
可以从jQuery检索此偏移位置因为页面上有一个菜单栏掩盖了页面的顶部,所以必须从滚动位置中减去它的高度(= $('#header')。externalHeight(true))
scroll = 0
将强制移动到页面顶部scroll = $(element).offset().top
将element
放在页面顶部我们必须减去
#header
的高度完整的公式是
scrollTop:($(InfoTarget.ID).offset()。top-$('#header')。outHeight(true))
此命令放置在
jQuery.animate
中,以实现视觉上更平滑的移动,并使用InfoTarget.tempo
值作为此动画的持续时间。在调整页面大小的过程中,如果事先单击了具有目标的链接(因此始终处于活动状态),则将触发相同类型的滚动。
所使用的不同jQuery方法均在jQuery文档中进行了说明(例如:https://api.jquery.com/outerHeight/)
新解决方案-隆迪2019年10月14日/ 01:00(星期日/星期一晚上)
该脚本必须放在正文的所有html元素之后
// scroll to target upon window.location.hash
$(window).on('hashchange', function() {
$('.TargetMark').removeClass('TargetMark')
$(window.location.hash).addClass('TargetMark')
setTimeout( scrollTop2, 220 ) // scroll to target after browser auto scrolling conflit
})
function scrollTop2() {
if ($('.TargetMark').length===1) { // if target exist
$('html').animate({
scrollTop: ($('.TargetMark').offset().top - $('#header').outerHeight(true))
}, 100);
}
}
在此版本中,目标元素添加了一个类(TargetMark),可以在调整窗口大小时找到它
结束部分
$(document).ready(function () {
//...
// ---------------------------> no call to scrollTop();
//...
});
$(window).resize(function () {
//...
scrollTop2();
//...
});
关于toggleMenu冲突:
function toggleMenu() {
$('.navbar-toggle').on('click', function () {
if ($("#js-menu").is(".expand")) {
$("#js-menu").toggleClass("expand");
$("#submenu").removeClass("active_sub").addClass("inactive_sub");
} else {
$("#js-menu").toggleClass("expand");
$("#submenu").removeClass("inactive_sub").addClass("active_sub");
}
resetTarget();
setTimeout( scrollTop2, 220 ) // scroll to target after browser auto scrolling conflit
});
}
我花了很多时间在您的问题上,研究了导航员自己使用的不同方法和不同的自动方法,这对于获得您想要的结果是必不可少的。我得出的结论是,问题首先来自页面的体系结构。
菜单(“ #header”)覆盖页面(“ #main”)的事实是一个主要缺陷,导致无法为您的问题提供有效的JS代码。
对锚点哈希的调用会触发页面的一个或多个滚动,页面大小的调整也需要进行滚动计算,因为通过更改屏幕上的大小,它也会更改页面的大小。页面(将屏幕大小减半使页面大小加倍),通过更改字体大小来实现相同,它也更改页面中的大小。
每当页面大小更改时,浏览器都必须重新计算很多事情,其中某些机制可能会触发一个或多个滚动。
您在这里要问的是要根据一个元素重新计算页面定位,我们不能确定它是否已完全建立,因为此过程与浏览器的其他过程并行执行,而其他过程可能会更改有用的值。
加上某些浏览器进程也可以滚动页面的事实,而且这可能是最后一次完成!
因此,菜单和页面之间存在重叠的事实增加了更多的复杂性,并且使解决方案的可能性变得不可能。
更改布局,将修复问题的3/4。
关于javascript - JavaScript函数来处理无法在$(window).resize()上使用的CSS自定义属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58250899/