Scrolling to an Anchor using Transition/CSS3

前端 未结 10 877
-上瘾入骨i
-上瘾入骨i 2020-11-30 20:07

I have a series of links which are using an anchor mechanism:


                      
相关标签:
10条回答
  • 2020-11-30 20:45

    You can find the answer to your question on the following page:

    https://stackoverflow.com/a/17633941/2359161

    Here is the JSFiddle that was given:

    http://jsfiddle.net/YYPKM/3/

    Note the scrolling section at the end of the CSS, specifically:

    /*
     *Styling
     */
    
    html,body {
        width: 100%;
        height: 100%;
        position: relative; 
    }
    body {
    overflow: hidden;
    }
    
    header {
    background: #fff; 
    position: fixed; 
    left: 0; top: 0; 
    width:100%;
    height: 3.5rem;
    z-index: 10; 
    }
    
    nav {
    width: 100%;
    padding-top: 0.5rem;
    }
    
    nav ul {
    list-style: none;
    width: inherit; 
    margin: 0; 
    }
    
    
    ul li:nth-child( 3n + 1), #main .panel:nth-child( 3n + 1) {
    background: rgb( 0, 180, 255 );
    }
    
    ul li:nth-child( 3n + 2), #main .panel:nth-child( 3n + 2) {
    background: rgb( 255, 65, 180 );
    }
    
    ul li:nth-child( 3n + 3), #main .panel:nth-child( 3n + 3) {
    background: rgb( 0, 255, 180 );
    }
    
    ul li {
    display: inline-block; 
    margin: 0 8px;
    margin: 0 0.5rem;
    padding: 5px 8px;
    padding: 0.3rem 0.5rem;
    border-radius: 2px; 
    line-height: 1.5;
    }
    
    ul li a {
    color: #fff;
    text-decoration: none;
    }
    
    .panel {
    width: 100%;
    height: 500px;
    z-index:0; 
    -webkit-transform: translateZ( 0 );
    transform: translateZ( 0 );
    -webkit-transition: -webkit-transform 0.6s ease-in-out;
    transition: transform 0.6s ease-in-out;
    -webkit-backface-visibility: hidden;
    backface-visibility: hidden;
    
    }
    
    .panel h1 {
    font-family: sans-serif;
    font-size: 64px;
    font-size: 4rem;
    color: #fff;
    position:relative;
    line-height: 200px;
    top: 33%;
    text-align: center;
    margin: 0;
    }
    
    /*
     *Scrolling
     */
    
    a[ id= "servicios" ]:target ~ #main article.panel {
    -webkit-transform: translateY( 0px);
    transform: translateY( 0px );
    }
    
    a[ id= "galeria" ]:target ~ #main article.panel {
    -webkit-transform: translateY( -500px );
    transform: translateY( -500px );
    }
    a[ id= "contacto" ]:target ~ #main article.panel {
    -webkit-transform: translateY( -1000px );
    transform: translateY( -1000px );
    }
    <a id="servicios"></a>
    <a id="galeria"></a>
    <a id="contacto"></a>
    <header class="nav">
    <nav>
        <ul>
            <li><a href="#servicios"> Servicios </a> </li>
            <li><a href="#galeria"> Galeria </a> </li>
            <li><a href="#contacto">Contacta  nos </a> </li>
        </ul>
    </nav>
    </header>
    
    <section id="main">
    <article class="panel" id="servicios">
        <h1> Nuestros Servicios</h1>
    </article>
    
    <article class="panel" id="galeria">
        <h1> Mustra de nuestro trabajos</h1>
    </article>
    
    <article class="panel" id="contacto">
        <h1> Pongamonos en contacto</h1>
    </article>
    </section>

    0 讨论(0)
  • 2020-11-30 20:45

    I guess it might be possible to set some kind of hardcore transition to the top style of a #container div to move your entire page in the desired direction when clicking your anchor. Something like adding a class that has top:-2000px.

    I did use JQuery because I'm to lazy too use native JS, but it is not necessary for what I did.

    This is probably not the best possible solution because the top content just moves towards the top and you can't get it back easily, you should definitely use JQuery if you really need that scroll animation.

    DEMO

    0 讨论(0)
  • 2020-11-30 20:46

    I tried user18490 solution but there were some problems like:

    • Bouncing when clicked more than once
    • Bouncing if there isn't sufficient space below the target elements
    • Element is not defined
    • Problem of parent Element
    • e.t.c

    Well after I edited and researched, I was able to come up with a solution. Hopefully it'll work for everyone

    Just change the script tag to:

    var html = document.documentElement
    
    var body = document.body
    
    var documentHeight = Math.max(body.scrollHeight, body.offsetHeight, html.scrollHeight, html.clientHeight, html.offsetHeight)
    
    var PageHeight = Math.max(html.clientHeight || 0, window.innerHeight || 0)
    
    function scrollDownTo(to, duration) {
        if (document.body.scrollTop == to) return;
        if ((documentHeight-to) < PageHeight) {
            to = documentHeight - PageHeight;
        }
        var diff = to - window.pageYOffset;
        var scrollStep = Math.PI / (duration / 10);
        var count = 0, currPos; ajaxe = 1
        var start = window.pageYOffset;
        var scrollInterval = setInterval(function(){
            if (window.pageYOffset != to) {
                count = count + 1;
                if (ajaxe > count) {
                    clearInterval(scrollInterval)
                }
                currPos = start +  diff * (0.5 - 0.5 * Math.cos(count * scrollStep));
                scroll( 0, currPos)
                ajaxe = count
            }
            else { clearInterval(scrollInterval);}
        },20);
        }
    
    function test (elID) {
        var dest = document.getElementById(elID);
        scrollDownTo((dest.getBoundingClientRect().top + window.pageYOffset), 500);
    }
    

    The HTML is still the same:

    <div class="header">
        <p class="menu"><a href="#S1" onclick="test('S1'); return false;">S1</a></p>
        <p class="menu"><a href="#S2" onclick="test('S2'); return false;">S2</a></p>
        <p class="menu"><a href="#S3" onclick="test('S3'); return false;">S3</a></p>
        <p class="menu"><a href="#S4" onclick="test('S4'); return false;">S3</a></p>
    </div>
    <div style="width: 100%;">
        <div id="S1" class="curtain">
        blabla
        </div>
        <div id="S2" class="curtain">
        blabla
        </div>
        <div id="S3" class="curtain">
        blabla
        </div>
        <div id="S4" class="curtain">
        blabla
        </div>
     </div>
    

    If you still encounter any issues kindly comment

    0 讨论(0)
  • 2020-11-30 20:49

    If anybody is just like me willing to use jQuery, but still found himself looking to this question then this may help you guys:

    https://html-online.com/articles/animated-scroll-anchorid-function-jquery/

    $(document).ready(function () {
                $("a.scrollLink").click(function (event) {
                    event.preventDefault();
                    $("html, body").animate({ scrollTop: $($(this).attr("href")).offset().top }, 500);
                });
            });
    <a href="#anchor1" class="scrollLink">Scroll to anchor 1</a>
    <a href="#anchor2" class="scrollLink">Scroll to anchor 2</a>
    <p id="anchor1"><strong>Anchor 1</strong> - Lorem ipsum dolor sit amet, nonumes voluptatum mel ea.</p>
    <p id="anchor2"><strong>Anchor 2</strong> - Ex ignota epicurei quo, his ex doctus delenit fabellas.</p>

    0 讨论(0)
  • 2020-11-30 20:51

    Here is a pure css solution using viewport units and variables that automatically scales to the device (and works on window resize). I added the following to Alex's solution:

            html,body {
                width: 100%;
                height: 100%;
                position: fixed;/* prevents scrolling */
                --innerheight: 100vh;/* variable 100% of viewport height */
            }
    
            body {
                overflow: hidden; /* prevents scrolling */
            }
    
            .panel {
                width: 100%;
                height: var(--innerheight); /* viewport height */
    
            a[ id= "galeria" ]:target ~ #main article.panel {
                -webkit-transform: translateY( calc(-1*var(--innerheight)) );
                transform: translateY( calc(-1*var(--innerheight)) );
            }
    
            a[ id= "contacto" ]:target ~ #main article.panel {
                -webkit-transform: translateY( calc(-2*var(--innerheight)) );
                transform: translateY( calc(-2*var(--innerheight)) );
    
    0 讨论(0)
  • 2020-11-30 20:52

    I implemented the answer suggested by @user18490 but ran into two problems:

    • First bouncing when user clicks on several tabs/links multiple times in short succession
    • Second, the undefined error mentioned by @krivar

    I developed the following class to get around the mentioned problems, and it works fine:

    export class SScroll{
        constructor(){
            this.delay=501      //ms
            this.duration=500   //ms
            this.lastClick=0
        }
    
        lastClick
        delay
        duration
    
        scrollTo=(destID)=>{
            /* To prevent "bounce" */
            /* https://stackoverflow.com/a/28610565/3405291 */
            if(this.lastClick>=(Date.now()-this.delay)){return}
            this.lastClick=Date.now()
    
            const dest=document.getElementById(destID)
            const to=dest.offsetTop
            if(document.body.scrollTop==to){return}
            const diff=to-document.body.scrollTop
            const scrollStep=Math.PI / (this.duration/10)
            let count=0
            let currPos
            const start=window.pageYOffset
            const scrollInterval=setInterval(()=>{
                if(document.body.scrollTop!=to){
                    count++
                    currPos=start+diff*(.5-.5*Math.cos(count*scrollStep))
                    document.body.scrollTop=currPos
                }else{clearInterval(scrollInterval)}
            },10)
        }
    }
    

    UPDATE

    There is a problem with Firefox as mentioned here. Therefore, to make it work on Firefox, I implemented the following code. It works fine on Chromium-based browsers and also Firefox.

    export class SScroll{
        constructor(){
            this.delay=501      //ms
            this.duration=500   //ms
            this.lastClick=0
        }
        lastClick
        delay
        duration
        scrollTo=(destID)=>{
            /* To prevent "bounce" */
            /* https://stackoverflow.com/a/28610565/3405291 */
            if(this.lastClick>=(Date.now()-this.delay)){return}
    
            this.lastClick=Date.now()
            const dest=document.getElementById(destID)
            const to=dest.offsetTop
            if((document.body.scrollTop || document.documentElement.scrollTop || 0)==to){return}
    
            const diff=to-(document.body.scrollTop || document.documentElement.scrollTop || 0)
            const scrollStep=Math.PI / (this.duration/10)
            let count=0
            let currPos
            const start=window.pageYOffset
            const scrollInterval=setInterval(()=>{
                if((document.body.scrollTop || document.documentElement.scrollTop || 0)!=to){
                    count++
                    currPos=start+diff*(.5-.5*Math.cos(count*scrollStep))
                    /* https://stackoverflow.com/q/28633221/3405291 */
                    /* To support both Chromium-based and Firefox */
                    document.body.scrollTop=currPos
                    document.documentElement.scrollTop=currPos
                }else{clearInterval(scrollInterval)}
            },10)
        }
    }
    
    0 讨论(0)
提交回复
热议问题