javascript - JavaScript函数来处理无法在$(window).resize()上使用的CSS自定义属性

标签 javascript jquery responsive pseudo-element window-resize

我有一个带有: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().topelement放在页面顶部
我们必须减去#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/

相关文章:

Javascripts "setInterval()"与 jQuery 动画一起使用会导致函数排队

javascript - 使用 angularJS .component() 但没有得到任何值

jquery - 按 Enter 键两次提交数据

javascript - 如何只显示 div 的第一行文本并在点击时展开?

jquery - FullCalendar - 时区不起作用

html - 以桌面为中心但不以移动设备为中心的弹出表单

html - 如何使用 Bootstrap 为移动站点设置容器 div 的宽度

javascript - 如何使用jquery使用前一个id获取下一个div的id

css - Chrome 瘦身 CSS 网格神秘缺口

javascript - vuejs - 如何使用点击事件附加 html