Подтвердить что ты не робот

Прокрутка к якорю с использованием перехода/CSS3

У меня есть ряд ссылок, которые используют механизм привязки:

<div class="header">
    <p class="menu"><a href="#S1">Section1</a></p>
    <p class="menu"><a href="#S2">Section2</a></p>
    ...
</div>
<div style="width: 100%;">
<a name="S1" class="test">&nbsp;</a>
<div class="curtain">
Lots of text
</div>

<a name="S2" class="test">&nbsp;</a>
<div class="curtain">
lots of text
</div>
...
</div>

Я использую следующий CSS:

.test
{
    position:relative; 
    margin: 0; 
    padding: 0; 
    float: left;
    display: inline-block;
    margin-top: -100px; /* whatever offset this needs to be */
}

Он работает нормально. Но, конечно, он перескакивает с одного раздела на другой, когда мы нажимаем на ссылку. Поэтому я хотел бы иметь плавный переход, используя какой-то прокрутки до начала выбранного раздел.

Я думаю, что я читал в Stackoverflow, что это невозможно (пока) с CSS3, но я бы хотел получить подтверждение, а также хотел бы знать, что "может" быть решением. Я счастлив использовать JS, но я не могу использовать jQuery. Я попытался использовать функцию щелчка по ссылке, получить "вертикальную позицию" div, которую нужно отобразить, но я не увенчался успехом. Я все еще изучаю JS и не знаю его достаточно хорошо, чтобы придумать свое решение.

Любая помощь/идеи были бы оценены.

4b9b3361

Ответ 1

Хотя некоторые ответы были очень полезными и информативными, я думал, что напишу ответ, который я придумал. Ответ от Alex был очень хорошим, однако он ограничен в том смысле, что высота div должна быть жестко закодирована в CSS.

Таким образом, решение, которое я разработал, использует JS (нет jQuery) и фактически представляет собой сокращенную версию (почти до минимума) над решениями для решения подобных проблем, которые я нашел в Statckoverflow:

HTML

<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>

ПРИМЕЧАНИЕ. "ВОЗВРАТ ЛОЖЬ"; в вызове по щелчку. Это важно, если вы хотите, чтобы ваш браузер не перескочил к самой ссылке (и пусть эффект управляется вашим JS).

Код JS:

<script>
function scrollTo(to, duration) {
    if (document.body.scrollTop == to) return;
    var diff = to - document.body.scrollTop;
    var scrollStep = Math.PI / (duration / 10);
    var count = 0, currPos;
    start = element.scrollTop;
    scrollInterval = setInterval(function(){
        if (document.body.scrollTop != to) {
            count = count + 1;
            currPos = start + diff * (0.5 - 0.5 * Math.cos(count * scrollStep));
            document.body.scrollTop = currPos;
        }
        else { clearInterval(scrollInterval); }
    },10);
}

function test(elID)
{
    var dest = document.getElementById(elID);
    scrollTo(dest.offsetTop, 500);
}
</script>

Это невероятно просто. Он находит вертикальное положение div в документе, используя его уникальный идентификатор (в тесте функции). Затем он вызывает функцию scrollTo, передающую начальную позицию (document.body.scrollTop) и место назначения (dest.offsetTop). Он выполняет переход с использованием какой-либо кривой непринужденности.

Спасибо всем за вашу помощь.

Знание немного кодирования может помочь вам избежать (иногда тяжелых) библиотек и дать вам (программисту) больше контроля.

Ответ 2

Вы можете найти ответ на свой вопрос на следующей странице:

fooobar.com/questions/4511/...

Вот JSFiddle, который был указан:

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

HTML:

<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>

CSS (обратите внимание на раздел прокрутки в конце, в частности):

/*
 *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 );
}

Ответ 3

Только mozzila реализует простое свойство в css: http://caniuse.com/#search=scroll-behavior

вам придется использовать JS как минимум.

Я лично использую это, потому что он прост в использовании (используйте JQ, но я могу адаптировать его, я думаю):

/*Scroll transition to anchor*/
$("a.toscroll").on('click',function(e) {
    var url = e.target.href;
    var hash = url.substring(url.indexOf("#")+1);
    $('html, body').animate({
        scrollTop: $('#'+hash).offset().top
    }, 500);
    return false;
});

просто добавьте класс для перехода к тегу

Ответ 4

Я предполагаю, что можно было бы установить какой-то хардкорный переход в стиль top для #container div для перемещения всей страницы в нужном направлении при нажатии на ваш якорь. Что-то вроде добавления класса с top:-2000px.

Я использовал JQuery, потому что я должен лениться и использовать собственный JS, но это не обязательно для того, что я сделал.

Это, вероятно, не лучшее возможное решение, потому что верхнее содержимое просто движется к вершине, и вы не можете легко его вернуть, вам обязательно нужно использовать JQuery, если вам действительно нужна эта прокрутка.

DEMO

Ответ 5

Вот чистое css-решение, использующее единицы просмотра и переменные, которые автоматически масштабируются для устройства (и работают с изменением размера окна). Я добавил следующее решение Alex:

        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)) );

Ответ 6

Я внедрил ответ, предложенный @user18490, но столкнулся с двумя проблемами:

  • Первый отскакивающий, когда пользователь нажимает несколько вкладок/ссылок несколько раз подряд.
  • Во-вторых, undefined ошибка, указанная @krivar

Я разработал следующий класс, чтобы обойти упомянутые проблемы, и он отлично работает:

export class SScroll{
    constructor(){
        this.delay=501      //ms
        this.duration=500   //ms
        this.lastClick=0
    }

    lastClick
    delay
    duration

    scrollTo=(destID)=>{
        /* To prevent "bounce" */
        /* /questions/210838/javascript-prevent-function-from-executing-multiple-times/1133749#1133749 */
        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

Проблема с Firefox, как упоминалось здесь. Поэтому, чтобы заставить его работать в Firefox, я применил следующий код. Он отлично работает с браузерами на основе хрома, а также с Firefox.

export class SScroll{
    constructor(){
        this.delay=501      //ms
        this.duration=500   //ms
        this.lastClick=0
    }
    lastClick
    delay
    duration
    scrollTo=(destID)=>{
        /* To prevent "bounce" */
        /* /questions/210838/javascript-prevent-function-from-executing-multiple-times/1133749#1133749 */
        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)
    }
}

Ответ 7

Использование scroll-behavior Свойство CSS:

(который поддерживается в современных браузерах, но не Edge):

a {
  display: inline-block;
  padding: 5px 7%;
  text-decoration: none;
}

nav, section {
  display: block;
  margin: 0 auto;
  text-align: center;
}

nav {
  width: 350px;
  padding: 5px;
}

section {
  width: 350px;
  height: 130px;
  overflow-y: scroll;
  border: 1px solid black;
  font-size: 0; 
  scroll-behavior: smooth;    /* <----- THE SECRET ---- */
}

section div{
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  font-size: 8vw;
}
<nav>
  <a href="#page-1">1</a>
  <a href="#page-2">2</a>
  <a href="#page-3">3</a>
</nav>
<section>
  <div id="page-1">1</div>
  <div id="page-2">2</div>
  <div id="page-3">3</div>
</section>

Ответ 8

Добавьте эту функцию на свою страницу после вставки jQuery и ваша проблема решена.

$(function() {
  $('a[href*=#]:not([href=#])').click(function() {
    if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostname == this.hostname) {
      var target = $(this.hash);
      target = target.length ? target : $('[name=' + this.hash.slice(1) +']');
      if (target.length) {
        $('html,body').animate({
          scrollTop: target.offset().top
        }, 1000);
        return false;
      }
    }
  });
});