【问题标题】:HTML - How to Anchor-Jump to display:none element?HTML - 如何锚点跳转到显示:无元素?
【发布时间】:2020-06-26 11:15:48
【问题描述】:

设置说明

我正在为我在 Django 中的 DnD 活动建立一个网站,并使用此 HTML5up.net 页面的修改版本(CSS 和 JS 库存不变)。在我的设置中,我有 2 个页面,一个是人们登陆的索引页面(HTML5up 页面)和一个超链接到索引页面中的“字符”页面。

一个演示索引页面(没有图片)的jsfiddle是here

在开始时,索引页面仅显示<header>,而超链接位于<article id="characters"> 部分,在开始时不可见。这些部分只有通过单击它们各自的按钮才可见,例如<a href="#characters">Characters</a> 跳转到相应的部分。

我的目标:

我希望不仅能够跳转到<article> 部分,而且我希望能够打开<article> 并跳转到其中的特定超链接(例如,指向“字符页”的链接)扎特”)。有了这个,我可以在字符页面上创建一个按钮,该按钮可以在用户离开索引页面的位置返回索引页面。

我的问题:

超链接回到索引和锚点跳转到<article>部分(例如“字符”)很容易做到这一点:

<a href="LinkOfIndexPagePlaceholder#characters"> Back to Characters </a>

以打开文章部分并跳转到文章中的特定字符(例如“Zart”)的方式返回索引的超链接不起作用,尽管项目的锚点(例如“Zart”)也具有正确的 id(例如“Zart”):

<a href="LinkOfIndexPagePlaceholder#Zart"> Back to Characters </a>

事实上,只要“字符”的文章部分尚未显示,我完全无法锚点跳转到 id 为“Zart”的锚点。

如果它已显示(通过将 jsfiddle 中“添加字符”按钮的 href 更改为“#Zart”进行测试),那么我可以跳转到到那个锚点,所以一般的跳跃方式有效。它会跳转到没有显示的锚点(因此在 CSS“display:none”中)这是有问题的。我需要在跳转之前以某种方式显示该文章部分。

如何让它工作?

到目前为止,我尝试的是here 讨论的方法。他们都没有为我工作。第一个答案导致所有文章部分的文本和超链接消失,第二个已经是我试图做的。

资源

以下是页面 HTML 的简化版本。

我将它缩短为解决问题的基本部分,因此只剩下一个条目和字符部分。要获取 CSS,请从 HTML5up 下载页面或从 filebin as zip 获取其 css 文件。遗憾的是,它们太长了,无法在此处发布,我不知道哪些部分是必不可少的。

索引页的 HTML:

<!DOCTYPE HTML>
<!--
    Dimension by HTML5 UP
    html5up.net | @ajlkn
    Free for personal and commercial use under the CCA 3.0 license (html5up.net/license)
    -->
<html>
<head>
    <title> Aldrune </title>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
          integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"/>
    <link rel="stylesheet" href="{% static 'frontpage/assets/css/main.css' %}"/>
    <link rel="stylesheet" href="{% static 'fontawesome47/css/font-awesome.min.css' %}">

    <noscript>
        <link rel="stylesheet" href="{% static 'frontpage/assets/css/noscript.css' %}"/>
    </noscript>
</head>
<body class="is-preload">

<!-- Wrapper -->
<div id="wrapper">

    <!-- Header -->
    <header id="header">
        <div class="logo">
            <a class="icon"><span class="icon fa-gem"> </span></a>
        </div>
        <div class="content">
            <div class="inner">
                <h1>Aldrune</h1>
                <p><b> A campaign made by X and recorded by Y</b></p>
            </div>
        </div>
        <nav>
            <ul> <!-- The anchor-jump buttons to <article> -->
                <li><b><a href="#characters">Characters</a></b></li>
            </ul>
        </nav>
    </header>

    <!-- Main -->
    <div id="main">

        <!-- Characters article -->
        <article id="characters">
            <h2 class="major">Characters</h2>
            <ul> 
                <li><a id="Zart" href="LinkToCharactersPage1"> Zart </a></li>
                <li><a id="Zenevieva" href="LinkToCharactersPage2"> Zenevieva </a></li>
                <li><a id="Zuxus" href="LinkToCharactersPage3"> Zuxus </a></li>
            </ul>
        </article>
    </div>
</div>

<!-- Scripts -->
<script src="{% static 'frontpage/assets/js/jquery.min.js' %}"></script>
<script src="{% static 'frontpage/assets/js/browser.min.js' %}"></script>
<script src="{% static 'frontpage/assets/js/breakpoints.min.js' %}"></script>
<script src="{% static 'frontpage/assets/js/util.js' %}"></script>
<script src="{% static 'frontpage/assets/js/main.js' %}"></script>

</body>
</html>

【问题讨论】:

    标签: html css


    【解决方案1】:

    有点 js-wizardry 是可能的。 基本原理是设置元素可见以获得计算偏移量所需的值。这样做之后,元素将被设置为其原始状态。 - 不用担心元素不会在短时间内闪烁。 js跑完后会重新渲染内容。

    这个脚本需要在页面渲染后运行,所以把js放在底部或者用window.addEventListener('load', function() { /* Code here... */ });包裹它

    // Pick every element having the class "js-jump"
    document.querySelectorAll('.js-jump').forEach(function(element) {
      // Handle the "onclick" event for each given element
      element.onclick = function() {
        // read "data-target" of element to select the target
        const target = document.querySelector(element.dataset.target);
        
        // set the element you want to scroll
        // const scrollArea = document.window; // <- If you want to scroll the whole frame
        const scrollArea = document.querySelector('.scrollArea');
        
        // save the original "display" state of your element (to restore it, as soon we are done)
        const originalTargetDisplay = target.style.display;
        
        // "show" the target to get required values
        target.style.display = 'inline-block';
        
        // get the distance to top
        offset = target.offsetTop;
        offset -= Math.ceil(target.offsetHeight / 2);
        
        // restore original display-attribute
        target.style.display = originalTargetDisplay;
    
        // scroll :)
        scrollArea.scrollTop = offset;
      }
    });
    .scrollArea {
      border: 1px solid black;
      padding: 15px;
      height: 50px;
      overflow: scroll;
    }
    
    #a-tag {
      display: none;
    }
    <div class="scrollArea">
      Some<br />Content<br />Content<br />Content<br />Content<br />Content<br />
      <br />
      Hidden A-Tag -> <a id='a-tag'>I am hidden!</a> <- here!
      <hr />
      Some<br />More<br />Content<br />Content<br />Content<br />Content<br />
      Content<br />Content<br />Content<br />Content<br />
    </div>
    <hr / >
    Controls:<br />
    <a href='#a-tag'>Jump via LINK</a> (no working)<br/>
    <a href='#' data-target='#a-tag' class='js-jump'>Jump via JS</a><br />

    【讨论】:

    • 作为没有适当JS知识的人值得一提,我假设目标是使用标签中的“data-target”属性指定的?该标签的内容如何/在 JS 代码中的何处到达 JS 函数?代码是在启动时执行还是由事件触发?这演示了从页面内跳转,如果我在一个完全不同的 HTML 页面上(字符页面是具有自己的 URL 等的单独的 HTML 页面)并链接回我想要执行的旧页面,这是否仍然有效跳跃?
    • 这只是基本原理。你不能在不调整的情况下复制/粘贴它。例如,我为演示硬编码了“scrollArea”。通常你想滚动document.window。我会添加一些 cmets 来回答您的问题。
    • 非常感谢。我想了很多,只是对我需要更明确地学习什么才能应用它有更多的了解,这将使事情在学习时间方面变得容易得多。
    • 终于有时间仔细看看了。我想我现在明白了整体要点。本质上,我们正在滚动到目标。 1)获取单击元素的“data-target”值,因为它定义了要跳转到的目标元素的id。 2) 定义要在 DOM 中的哪个元素内部滚动 3) 临时存储当前滚动位置以便之后恢复 4) 将目标元素设置为可见并计算滚动距离(从滚动元素顶部到中间的距离target-element) 5) 再次设置元素不可见 6) 使用计算的偏移量向下滚动
    • 要在加载时滚动,您需要在 url (myPage.com#myTarget) 中有目标。您通过解析window.location.href 收到此信息。其余的和上面的差不多:)
    【解决方案2】:

    感谢@Pilan 的解释和对 JS 的深入研究,我设法为此构建了一个解决方案。那是因为他的解决方案更通用,所以我接受他的回答作为这个问题的答案。

    此解决方案基于 Pilan 的方法,但为我想要实现的目标添加了必要的额外步骤。因此,这适用于任何使用 HTML5up 的精确 HTML 设计(维度)的人。

    最后我将这段 javascript 附加到 HTML:

    //I have 3 possible urls to expect: 
    // 1) http://localhost:8000/wiki/ - Open wiki page
    // 2) http://localhost:8000/wiki/#characters - Open wiki page and display otherwise hidden article element with that Id ('characters') on wiki page
    // 3) http://localhost:8000/wiki/#characters#Mruvain - Open wiki page, display article  ('characters') and scroll to element with that id ('Mruvain) in that article
    // Only in case of url 3) do I want to scroll
    
    // get url as string, e.g. http://localhost:8000/wiki/#characters#Mruvain
    const url = window.location.href;
    
    // Check if we are in scenario 2) or 3) by checking if URL includes "#"
    if (url.includes('#')){
        // split the url into an array, in scenario 3 we will have the article id in index 1 and target-element-id in index 2
        const hash = url.split('#');
        // Checks if we are in scenario 3) by checking if hash has exactly 3 elements
        if (hash.length == 3) {
            //Get the article element
            const article_id = hash[1];
            const article = document.getElementById(article_id);
    
            //Get the target element
            const target_id = hash[2];
            const target = document.getElementById(target_id);
    
            // Hide the initially displayed part of the page
            document.getElementById('header').style.display='none';
            // Make background blurry as it is when an article is open
            document.body.className = 'is-article-visible';
            // Display the background frame for the article to display
            document.getElementById('main').style.display='flex';
            // Set the article as active to display it
            article.className = 'active';
            article.style.display='block';
    
            // The element is now visible since the entire article is visible. Calculate it's distance to the top 
            offset = target.offsetTop;
            offset -= Math.ceil(target.offsetHeight / 2);
            // Scroll the window on the Y-axis for that many pixel downwards
            window.scrollBy(0, offset);
        }
    }
    

    【讨论】:

      【解决方案3】:

      我认为链接到隐藏元素是不可能的,因为它不包含计算定位所需的 css 属性。有多种方法可以在不使用 display: none; 的情况下隐藏某些内容。

      例如:溢出:隐藏;高度:0;

      为了根据点击事件更改样式以显示内容,我相信只有 JS 才有可​​能。你可以使用 css 选择器和 input:active 状态来做一些非常 hacky 的东西,但我不建议使用到目前为止在 DOM 中分离的元素。

      您是否尝试避免使用 JS 来实现此功能或您的方法?

      【讨论】:

      • 我避免使用 js 是经验问题。我是一名 Python 开发人员,这是我第一次涉足 Web 开发。 HTML 和 CSS 处于最基本的水平,在旅途中很容易上手,js 需要更专注的心态。我确实计划学习它,只是不是立即用于我的第一个项目,所以我想避免它。我认为,如果我想让它以我想要的方式工作,虽然(使用干净的代码)没有办法解决这个问题。该死。
      • 您可能对我必须在 JS 中学习的内容有一些建议吗?解决方案的一般粗略架构是什么样的?
      • 我建议从这里开始进行任何 DOM 操作:w3schools.com/js/js_htmldom.asp
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-26
      • 2019-12-26
      • 1970-01-01
      • 2013-09-18
      • 1970-01-01
      相关资源
      最近更新 更多