Прокрутка к якорю с использованием перехода/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"> </a>
<div class="curtain">
Lots of text
</div>
<a name="S2" class="test"> </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 и не знаю его достаточно хорошо, чтобы придумать свое решение.
Любая помощь/идеи были бы оценены.
Ответы
Ответ 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, но столкнулся с двумя проблемами:
Я разработал следующий класс, чтобы обойти упомянутые проблемы, и он отлично работает:
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
(который поддерживается в современных браузерах, но не 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;
}
}
});
});